From 6d49066f57ef3dc77b2af4ebb689d936eb9bdef8 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:56:56 +0100 Subject: [PATCH 001/289] Reenable ibm runners Should be fixed now --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d134bf68b7..391dfdd91d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,7 +79,7 @@ jobs: shell: bash build-ibm: - if: github.repository == 'ruby/prism' && false + if: github.repository == 'ruby/prism' strategy: fail-fast: false matrix: From c49ce84266a0ed0fb7f0fd9036cce7f28aadde34 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:06:58 +0100 Subject: [PATCH 002/289] Update testing guide I've made a few changes that aren't reflected and some info is long outdated --- docs/testing.md | 75 ++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/docs/testing.md b/docs/testing.md index a42ee2e270..ade07bfbb5 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -14,42 +14,59 @@ These test specific prism implementation details like comments, errors, and regu Snapshot tests ensure that parsed output is equivalent to previous parsed output. There are many categorized examples of valid syntax within the `test/prism/fixtures/` directory. When the test suite runs, it will parse all of this syntax, and compare it against corresponding files in the `test/prism/snapshots/` directory. For example, `test/prism/fixtures/strings.txt` has a corresponding `test/prism/snapshots/strings.txt`. -If the parsed files do not match, it will raise an error. If there is not a corresponding file in the `test/prism/snapshots/` directory, one will be created so that it exists for the next test run. +If the parsed files do not match, it will raise an error. If there is not a corresponding file in the `test/prism/snapshots/` directory, one will be created so that it exists for the next test run. If the snapshot already exists but differs you can run with `UPDATE_SNAPSHOTS=1` to regenerate them. -### Testing against repositories +When working on a specific example, you can limit tests to a single fixture via `FOCUS=strings.txt`. -To test the parser against a repository, you can run `FILEPATHS='/path/to/repository/**/*.rb' rake lex`. This will run the parser against every file matched by the glob pattern and check its generated tokens against those generated by ripper. +#### Versioning -## Local testing - -As you are working, you will likely want to test your code locally. `test.rb` is ignored by git, so it can be used for local testing. There are also two executables which may help you: - -1. **bin/lex** takes a filepath and compares prism's lexed output to Ripper's lexed output. It prints any lexed output that doesn't match. It does some minor transformations to the lexed output in order to compare them, like split prism's heredoc tokens to mirror Ripper's. - -``` -$ bin/lex test.rb -``` +Prism is capable of parsing code with different version specifiers. The test suite reflects this: +* Test files under `test/prism/snapshots/*.txt` are validated against all supported versions. +* Test files under `test/prism/snapshots/[MAJOR].[MINOR]/*.txt` are validated against all versions starting from the given version. +* Test files under `test/prism/snapshots/[MAJOR].[MINOR]-[MAJOR].[MINOR]/*.txt` are validated against the given version range. -If you would like to see the full lexed comparison, and not only the output that doesn't match, you can run with `VERBOSE=1`: - -``` -$ VERBOSE=1 bin/lex test.rb -``` +Should you add logic specific to a new ruby version, validate the new behavior but also that old behavior remains the same. -`bin/lex` can also be used with `-e` and then source code, like this: +### Error tests -``` -$ bin/lex -e "1 + 2" -``` +Error tests are similar to snapshot tests and expectations are located under `test/prism/errors/`. +They contain invalid syntax and rendered errors, similar to how `ruby -c` would show them. +Error tests are versioned in the same way that snapshot tests are and also support `FOCUS`/`UPDATE_SNAPSHOTS`. -2. **bin/parse** takes a filepath and outputs prism's parsed node structure generated from reading the file. +## Local testing +As you are working, you will likely want to test your code locally. `test.rb` is ignored by git, so it can be used for local testing. **bin/prism** contains a multitude of options to aid you, depending on which area +of prism you are working on. `bin/prism --help` prints a list of all available commands. + +Commands that take a `[source]` can be called in three different ways: +1. `bin/prism parse` will use `test.rb` as input. +1. `bin/prism parse foo.rb` will read from the given path. +1. `bin/prism parse -e "1 + 2"` will use the given source code. + +`bin/prism parse` is aliased as `bin/parse` for for convenience. + +### Validating your changes against real code + +If you create a change which is not expected to have a large impact on real code, you can use +`bin/compare` to validate that assumption. It compiles two versions of prism (for example +your feature branch and main), comparing ast, errors and warnings. Once done, a report is +printed showcasing in what way files changed, if any (syntax valid -> syntax invalid, changed AST, etc.) + +```sh +$ bin/compare main feature-branch ~/all-of-rubygems` +... +0/3157385 +1000/3157385 +... +3157000/3157385 +Oops: +intermine-1.05.00/lib/intermine/lists.rb changed from valid(true) to valid(false) +whistle-0.1.1/lib/resource.rb changed from valid(true) to valid(false) +Took 2661.5390081949999512 seconds ``` -$ bin/parse test.rb -``` - -`bin/parse` can also be used with `-e` and then source code, like this: -``` -$ bin/parse -e "1 + 2" -``` +It is up to you to aquire code samples. Here are some resources you can use for this purpose: +* https://github.com/jeromedalbert/real-world-ruby-apps +* https://github.com/eliotsykes/real-world-rails +* https://github.com/rubygems/rubygems-mirror + Requires some work to unpack the downloaded gems. You should also run with `RUBYGEMS_MIRROR_ONLY_LATEST=TRUE`. From 2e214f18a8b38bdacae1781505b8cf4a119aa53c Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:12:54 +0100 Subject: [PATCH 003/289] Remove `license-file` from rust crates https://github.com/ruby/prism/pull/3866 added `license`. Now building shows a warning: > warning: /home/user/code/ruby-prism/rust/ruby-prism/Cargo.toml: only one of `license` or `license-file` is necessary > `license` should be used if the package license can be expressed with a standard SPDX expression. > `license-file` should be used if the package uses a non-standard license. --- rust/ruby-prism-sys/Cargo.toml | 1 - rust/ruby-prism/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/rust/ruby-prism-sys/Cargo.toml b/rust/ruby-prism-sys/Cargo.toml index edda0ed1fd..4578488af3 100644 --- a/rust/ruby-prism-sys/Cargo.toml +++ b/rust/ruby-prism-sys/Cargo.toml @@ -3,7 +3,6 @@ name = "ruby-prism-sys" version = "1.9.0" edition = "2021" license = "MIT" -license-file = "../../LICENSE.md" repository = "https://github.com/ruby/prism" description = "Rust bindings to Ruby's prism parsing library" links = "prism" diff --git a/rust/ruby-prism/Cargo.toml b/rust/ruby-prism/Cargo.toml index 426ae159dc..302780399c 100644 --- a/rust/ruby-prism/Cargo.toml +++ b/rust/ruby-prism/Cargo.toml @@ -3,7 +3,6 @@ name = "ruby-prism" version = "1.9.0" edition = "2021" license = "MIT" -license-file = "../../LICENSE.md" repository = "https://github.com/ruby/prism" description = "Rustified version of Ruby's prism parsing library" authors = [ From 443e9b99599b8e8541fff1fb3b14eed4442069e9 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:31:32 +0100 Subject: [PATCH 004/289] Rewrite "version: nearest" to require no maintenance Currently I see myself not updating this when a new version is added. Instead, rewrite it to just work with new versions: * Try to set the version * If that doesn't succeed, check if it is lower * If it isn't lower, it must be higher We can then use `PM_OPTIONS_VERSION_LATEST` which doesn't need to change. Also added a very basic test. --- ext/prism/extension.c | 20 +++++++---------- lib/prism/ffi.rb | 43 ++++++++++++++++-------------------- test/prism/api/parse_test.rb | 4 ++++ 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 363144970c..fe3cd6a8f3 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -205,18 +205,14 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, ruby_version)); } } else if (RSTRING_LEN(value) == 7 && strncmp(version, "nearest", 7) == 0) { - const char *nearest_version; - - if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { - nearest_version = "3.3"; - } else if (ruby_version[0] > '4' || (ruby_version[0] == '4' && ruby_version[2] > '1')) { - nearest_version = "4.1"; - } else { - nearest_version = ruby_version; - } - - if (!pm_options_version_set(options, nearest_version, 3)) { - rb_raise(rb_eArgError, "invalid nearest version: %s", nearest_version); + if (!pm_options_version_set(options, ruby_version, 3)) { + // Prism doesn't know this specific version. Is it lower? + if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { + options->version == PM_OPTIONS_VERSION_CRUBY_3_3; + } else { + // Must be higher. + options->version == PM_OPTIONS_VERSION_LATEST; + } } } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value); diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 57d878a33f..618324ded6 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -423,27 +423,28 @@ def dump_options_command_line(options) # Return the value that should be dumped for the version option. def dump_options_version(version) - checking = - case version - when "current" - RUBY_VERSION - when "latest" - nil - when "nearest" - if RUBY_VERSION <= "3.3" - "3.3" - elsif RUBY_VERSION >= "4.1" - "4.1" - else - RUBY_VERSION - end + case version + when "current" + version_string_to_number(RUBY_VERSION) || raise(CurrentVersionError, RUBY_VERSION) + when "latest", nil + 0 # Handled in pm_parser_init + when "nearest" + dump = version_string_to_number(RUBY_VERSION) + return dump if dump + if RUBY_VERSION < "3.3" + version_string_to_number("3.3") else - version + 0 # Handled in pm_parser_init end + else + version_string_to_number(version) || raise(ArgumentError, "invalid version: #{version}") + end + end - case checking - when nil - 0 # Handled in pm_parser_init + # Converts a version string like "4.0.0" or "4.0" into a number. + # Returns nil if the version is unknown. + def version_string_to_number(version) + case version when /\A3\.3(\.\d+)?\z/ 1 when /\A3\.4(\.\d+)?\z/ @@ -452,12 +453,6 @@ def dump_options_version(version) 3 when /\A4\.1(\.\d+)?\z/ 4 - else - if version == "current" - raise CurrentVersionError, RUBY_VERSION - else - raise ArgumentError, "invalid version: #{version}" - end end end diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb index bbf28201ff..c9a47c1a61 100644 --- a/test/prism/api/parse_test.rb +++ b/test/prism/api/parse_test.rb @@ -154,6 +154,10 @@ def test_version_current end end + def test_nearest + assert Prism.parse_success?("1 + 1", version: "nearest") + end + def test_scopes assert_kind_of Prism::CallNode, Prism.parse_statement("foo") assert_kind_of Prism::LocalVariableReadNode, Prism.parse_statement("foo", scopes: [[:foo]]) From 0bd9a7d3731a0ada8fb22570ab9fbe188dcca0b1 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Fri, 6 Feb 2026 16:41:41 +0100 Subject: [PATCH 005/289] Document fewer useless methods/classes (#3908) * Add missing nodocs for FFI When generating docs in ruby/prism, this doesn't seem to matter. But on docs.ruby-lang.org these take over the actual documentation. * Nodoc various utility methods They don't tell much of a story and just pull attention away from actually unique methods * Nodoc some private functions/modules * Nodoc translator implementation details As well as some functionality from ripper that is nodoc in ruby * Stop documenting visitor implementation details These result in so many methods that are searchable and give no actual benefit. Toplevel docs are all you need to understand the usecase. --- lib/prism/ffi.rb | 4 +- lib/prism/lex_compat.rb | 2 +- lib/prism/parse_result.rb | 40 ++++++++++---------- lib/prism/pattern.rb | 28 +++++++------- lib/prism/translation/parser.rb | 2 +- lib/prism/translation/parser/compiler.rb | 4 +- lib/prism/translation/parser/lexer.rb | 8 ++-- lib/prism/translation/ripper.rb | 4 ++ lib/prism/translation/ripper/lexer.rb | 7 +--- lib/prism/translation/ripper/sexp.rb | 12 +----- lib/prism/translation/ruby_parser.rb | 2 +- templates/lib/prism/compiler.rb.erb | 9 ++--- templates/lib/prism/dispatcher.rb.erb | 6 +-- templates/lib/prism/dot_visitor.rb.erb | 9 ++--- templates/lib/prism/inspect_visitor.rb.erb | 16 ++++---- templates/lib/prism/mutation_compiler.rb.erb | 3 +- templates/lib/prism/node.rb.erb | 8 ++-- templates/lib/prism/serialize.rb.erb | 2 +- 18 files changed, 75 insertions(+), 91 deletions(-) diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 618324ded6..520c773b43 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -233,7 +233,7 @@ def self.with_file(filepath) # The version constant is set by reading the result of calling pm_version. VERSION = LibRubyParser.pm_version.read_string.freeze - class << self + class << self # :nodoc: # Mirror the Prism.dump API by using the serialization API. def dump(source, **options) LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) } @@ -554,7 +554,7 @@ def dump_options(options) # Here we are going to patch StringQuery to put in the class-level methods so # that it can maintain a consistent interface - class StringQuery + class StringQuery # :nodoc: class << self # Mirrors the C extension's StringQuery::local? method. def local?(string) diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 5b685716cc..e8d2ce1b19 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -20,7 +20,7 @@ def initialize(value, comments, magic_comments, data_loc, errors, warnings, sour end # Implement the hash pattern matching interface for Result. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end end diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 2498ae7e14..53ca168c0e 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -163,7 +163,7 @@ def deep_freeze # Binary search through the offsets to find the line number for the given # byte offset. - def find_line(byte_offset) + def find_line(byte_offset) # :nodoc: index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length index - 1 end @@ -350,7 +350,7 @@ def chop end # Returns a string representation of this location. - def inspect + def inspect # :nodoc: "#" end @@ -477,12 +477,12 @@ def cached_end_code_units_column(cache) end # Implement the hash pattern matching interface for Location. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { start_offset: start_offset, end_offset: end_offset } end # Implement the pretty print interface for Location. - def pretty_print(q) + def pretty_print(q) # :nodoc: q.text("(#{start_line},#{start_column})-(#{end_line},#{end_column})") end @@ -528,7 +528,7 @@ def initialize(location) end # Implement the hash pattern matching interface for Comment. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { location: location } end @@ -548,7 +548,7 @@ def trailing? end # Returns a string representation of this comment. - def inspect + def inspect # :nodoc: "#" end end @@ -562,7 +562,7 @@ def trailing? end # Returns a string representation of this comment. - def inspect + def inspect # :nodoc: "#" end end @@ -592,12 +592,12 @@ def value end # Implement the hash pattern matching interface for MagicComment. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { key_loc: key_loc, value_loc: value_loc } end # Returns a string representation of this magic comment. - def inspect + def inspect # :nodoc: "#" end end @@ -626,12 +626,12 @@ def initialize(type, message, location, level) end # Implement the hash pattern matching interface for ParseError. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { type: type, message: message, location: location, level: level } end # Returns a string representation of this error. - def inspect + def inspect # :nodoc: "#" end end @@ -660,12 +660,12 @@ def initialize(type, message, location, level) end # Implement the hash pattern matching interface for ParseWarning. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { type: type, message: message, location: location, level: level } end # Returns a string representation of this warning. - def inspect + def inspect # :nodoc: "#" end end @@ -705,7 +705,7 @@ def initialize(comments, magic_comments, data_loc, errors, warnings, source) end # Implement the hash pattern matching interface for Result. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings } end @@ -752,7 +752,7 @@ def initialize(value, comments, magic_comments, data_loc, errors, warnings, sour end # Implement the hash pattern matching interface for ParseResult. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end @@ -786,7 +786,7 @@ def initialize(value, comments, magic_comments, data_loc, errors, warnings, sour end # Implement the hash pattern matching interface for LexResult. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end end @@ -804,7 +804,7 @@ def initialize(value, comments, magic_comments, data_loc, errors, warnings, sour end # Implement the hash pattern matching interface for ParseLexResult. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end end @@ -830,7 +830,7 @@ def initialize(source, type, value, location) end # Implement the hash pattern matching interface for Token. - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { type: type, value: value, location: location } end @@ -842,7 +842,7 @@ def location end # Implement the pretty print interface for Token. - def pretty_print(q) + def pretty_print(q) # :nodoc: q.group do q.text(type.to_s) self.location.pretty_print(q) @@ -864,7 +864,7 @@ def ==(other) end # Returns a string representation of this token. - def inspect + def inspect # :nodoc: location super end diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index 6ad2d9e5b9..4a0c5ef54d 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -100,23 +100,23 @@ def scan(root) # Shortcut for combining two procs into one that returns true if both return # true. - def combine_and(left, right) + def combine_and(left, right) # :nodoc: ->(other) { left.call(other) && right.call(other) } end # Shortcut for combining two procs into one that returns true if either # returns true. - def combine_or(left, right) + def combine_or(left, right) # :nodoc: ->(other) { left.call(other) || right.call(other) } end # Raise an error because the given node is not supported. - def compile_error(node) + def compile_error(node) # :nodoc: raise CompilationError, node.inspect end # in [foo, bar, baz] - def compile_array_pattern_node(node) + def compile_array_pattern_node(node) # :nodoc: compile_error(node) if !node.rest.nil? || node.posts.any? constant = node.constant @@ -141,12 +141,12 @@ def compile_array_pattern_node(node) end # in foo | bar - def compile_alternation_pattern_node(node) + def compile_alternation_pattern_node(node) # :nodoc: combine_or(compile_node(node.left), compile_node(node.right)) end # in Prism::ConstantReadNode - def compile_constant_path_node(node) + def compile_constant_path_node(node) # :nodoc: parent = node.parent if parent.is_a?(ConstantReadNode) && parent.slice == "Prism" @@ -161,12 +161,12 @@ def compile_constant_path_node(node) # in ConstantReadNode # in String - def compile_constant_read_node(node) + def compile_constant_read_node(node) # :nodoc: compile_constant_name(node, node.name) end # Compile a name associated with a constant. - def compile_constant_name(node, name) + def compile_constant_name(node, name) # :nodoc: if Prism.const_defined?(name, false) clazz = Prism.const_get(name) @@ -182,7 +182,7 @@ def compile_constant_name(node, name) # in InstanceVariableReadNode[name: Symbol] # in { name: Symbol } - def compile_hash_pattern_node(node) + def compile_hash_pattern_node(node) # :nodoc: compile_error(node) if node.rest compiled_constant = compile_node(node.constant) if node.constant @@ -212,12 +212,12 @@ def compile_hash_pattern_node(node) end # in nil - def compile_nil_node(node) + def compile_nil_node(node) # :nodoc: ->(attribute) { attribute.nil? } end # in /foo/ - def compile_regular_expression_node(node) + def compile_regular_expression_node(node) # :nodoc: regexp = Regexp.new(node.unescaped, node.closing[1..]) ->(attribute) { regexp === attribute } @@ -225,7 +225,7 @@ def compile_regular_expression_node(node) # in "" # in "foo" - def compile_string_node(node) + def compile_string_node(node) # :nodoc: string = node.unescaped ->(attribute) { string === attribute } @@ -233,7 +233,7 @@ def compile_string_node(node) # in :+ # in :foo - def compile_symbol_node(node) + def compile_symbol_node(node) # :nodoc: symbol = node.unescaped.to_sym ->(attribute) { symbol === attribute } @@ -241,7 +241,7 @@ def compile_symbol_node(node) # Compile any kind of node. Dispatch out to the individual compilation # methods based on the type of node. - def compile_node(node) + def compile_node(node) # :nodoc: case node when AlternationPatternNode compile_alternation_pattern_node(node) diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb index fed4ac4cd1..70031f133a 100644 --- a/lib/prism/translation/parser.rb +++ b/lib/prism/translation/parser.rb @@ -33,7 +33,7 @@ class Parser < ::Parser::Base # The parser gem has a list of diagnostics with a hard-coded set of error # messages. We create our own diagnostic class in order to set our own # error messages. - class PrismDiagnostic < Diagnostic + class PrismDiagnostic < Diagnostic # :nodoc: # This is the cached message coming from prism. attr_reader :message diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index bd3618b162..37951a1d40 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -6,9 +6,9 @@ module Translation class Parser # A visitor that knows how to convert a prism syntax tree into the # whitequark/parser gem's syntax tree. - class Compiler < ::Prism::Compiler + class Compiler < ::Prism::Compiler # :nodoc: # Raised when the tree is malformed or there is a bug in the compiler. - class CompilationError < StandardError + class CompilationError < StandardError # :nodoc: end # The Parser::Base instance that is being used to build the AST. diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb index 0491e79cd2..8e18a3cd1e 100644 --- a/lib/prism/translation/parser/lexer.rb +++ b/lib/prism/translation/parser/lexer.rb @@ -10,7 +10,7 @@ module Translation class Parser # Accepts a list of prism tokens and converts them into the expected # format for the parser gem. - class Lexer + class Lexer # :nodoc: # These tokens are always skipped TYPES_ALWAYS_SKIP = Set.new(%i[IGNORED_NEWLINE __END__ EOF]) private_constant :TYPES_ALWAYS_SKIP @@ -188,8 +188,8 @@ class Lexer # without them. We should find another way to do this, but in the # meantime we'll hide them from the documentation and mark them as # private constants. - EXPR_BEG = 0x1 # :nodoc: - EXPR_LABEL = 0x400 # :nodoc: + EXPR_BEG = 0x1 + EXPR_LABEL = 0x400 # It is used to determine whether `do` is of the token type `kDO` or `kDO_LAMBDA`. # @@ -232,7 +232,7 @@ def initialize(source_buffer, lexed, offset_cache) @offset_cache = offset_cache end - Range = ::Parser::Source::Range # :nodoc: + Range = ::Parser::Source::Range private_constant :Range # Convert the prism tokens into the expected format for the parser gem. diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index 5b2aa37833..2a3eaa4001 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -594,6 +594,8 @@ def parse # Visitor methods ########################################################################## + # :stopdoc: + # alias foo bar # ^^^^^^^^^^^^^ def visit_alias_method_node(node) @@ -3458,6 +3460,8 @@ def bounds(location) @column = location.start_column end + # :startdoc: + ########################################################################## # Ripper interface ########################################################################## diff --git a/lib/prism/translation/ripper/lexer.rb b/lib/prism/translation/ripper/lexer.rb index cbcdcd47cc..c6aeae4bd7 100644 --- a/lib/prism/translation/ripper/lexer.rb +++ b/lib/prism/translation/ripper/lexer.rb @@ -7,8 +7,7 @@ module Prism module Translation class Ripper class Lexer < Ripper # :nodoc: - # :stopdoc: - class State + class State # :nodoc: attr_reader :to_int, :to_s def initialize(i) @@ -48,7 +47,7 @@ def self.[](i) end end - class Elem + class Elem # :nodoc: attr_accessor :pos, :event, :tok, :state, :message def initialize(pos, event, tok, state, message = nil) @@ -128,8 +127,6 @@ def parse(...) def scan(...) parse(...) end - - # :startdoc: end end end diff --git a/lib/prism/translation/ripper/sexp.rb b/lib/prism/translation/ripper/sexp.rb index 8cfefc8472..46c0333544 100644 --- a/lib/prism/translation/ripper/sexp.rb +++ b/lib/prism/translation/ripper/sexp.rb @@ -8,9 +8,7 @@ module Translation class Ripper # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that # returns the arrays of [type, *children]. - class SexpBuilder < Ripper - # :stopdoc: - + class SexpBuilder < Ripper # :nodoc: attr_reader :error private @@ -65,16 +63,12 @@ def on_error(mesg) remove_method :on_parse_error alias on_parse_error on_error alias compile_error on_error - - # :startdoc: end # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that # returns the same values as ::Ripper::SexpBuilder except with a couple of # niceties that flatten linked lists into arrays. - class SexpBuilderPP < SexpBuilder - # :stopdoc: - + class SexpBuilderPP < SexpBuilder # :nodoc: private def on_heredoc_dedent(val, width) @@ -118,8 +112,6 @@ def on_mlhs_add_post(list, post) alias_method "on_#{event}", :_dispatch_event_push end end - - # :startdoc: end end end diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb index c026c4ad9c..5f4a8cab92 100644 --- a/lib/prism/translation/ruby_parser.rb +++ b/lib/prism/translation/ruby_parser.rb @@ -19,7 +19,7 @@ module Translation # seattlerb/ruby_parser gem's syntax tree. class RubyParser # A prism visitor that builds Sexp objects. - class Compiler < ::Prism::Compiler + class Compiler < ::Prism::Compiler # :nodoc: # This is the name of the file that we are compiling. We set it on every # Sexp object that is generated, and also use it to compile `__FILE__` # nodes. diff --git a/templates/lib/prism/compiler.rb.erb b/templates/lib/prism/compiler.rb.erb index 66dbe666b9..031557a221 100644 --- a/templates/lib/prism/compiler.rb.erb +++ b/templates/lib/prism/compiler.rb.erb @@ -18,24 +18,23 @@ module Prism # class Compiler < Visitor # Visit an individual node. - def visit(node) + def visit(node) # :nodoc: node&.accept(self) end # Visit a list of nodes. - def visit_all(nodes) + def visit_all(nodes) # :nodoc: nodes.map { |node| node&.accept(self) } end # Visit the child nodes of the given node. - def visit_child_nodes(node) + def visit_child_nodes(node) # :nodoc: node.each_child_node.map { |node| node.accept(self) } end <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> - # Compile a <%= node.name %> node - def visit_<%= node.human %>(node) + def visit_<%= node.human %>(node) # :nodoc: node.each_child_node.map { |node| node.accept(self) } end <%- end -%> diff --git a/templates/lib/prism/dispatcher.rb.erb b/templates/lib/prism/dispatcher.rb.erb index 52478451c9..16ce421cc5 100644 --- a/templates/lib/prism/dispatcher.rb.erb +++ b/templates/lib/prism/dispatcher.rb.erb @@ -56,7 +56,7 @@ module Prism end # Register a listener for the given events. - private def register_events(listener, events) + private def register_events(listener, events) # :nodoc: events.each { |event| (listeners[event] ||= []) << listener } end @@ -73,9 +73,7 @@ module Prism end <%- nodes.each do |node| -%> - # Dispatch enter and leave events for <%= node.name %> nodes and continue - # walking the tree. - def visit_<%= node.human %>(node) + def visit_<%= node.human %>(node) # :nodoc: listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) } super listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) } diff --git a/templates/lib/prism/dot_visitor.rb.erb b/templates/lib/prism/dot_visitor.rb.erb index 87de1965b0..13c53af0d4 100644 --- a/templates/lib/prism/dot_visitor.rb.erb +++ b/templates/lib/prism/dot_visitor.rb.erb @@ -106,8 +106,7 @@ module Prism end <%- nodes.each do |node| -%> - # Visit a <%= node.name %> node. - def visit_<%= node.human %>(node) + def visit_<%= node.human %>(node) # :nodoc: table = Table.new("<%= node.name %>") id = node_id(node) <%- if (node_flags = node.flags) -%> @@ -165,19 +164,19 @@ module Prism private # Generate a unique node ID for a node throughout the digraph. - def node_id(node) + def node_id(node) # :nodoc: "Node_#{node.object_id}" end # Inspect a location to display the start and end line and columns in bytes. - def location_inspect(location) + def location_inspect(location) # :nodoc: "(#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column})" end <%- flags.each do |flag| -%> # Inspect a node that has <%= flag.human %> flags to display the flags as a # comma-separated list. - def <%= flag.human %>_inspect(node) + def <%= flag.human %>_inspect(node) # :nodoc: flags = [] #: Array[String] <%- flag.values.each do |value| -%> flags << "<%= value.name.downcase %>" if node.<%= value.name.downcase %>? diff --git a/templates/lib/prism/inspect_visitor.rb.erb b/templates/lib/prism/inspect_visitor.rb.erb index 3cfe615d85..9a33cb8110 100644 --- a/templates/lib/prism/inspect_visitor.rb.erb +++ b/templates/lib/prism/inspect_visitor.rb.erb @@ -17,14 +17,13 @@ module Prism private_constant :Replace # The current prefix string. - attr_reader :indent + attr_reader :indent # :nodoc: # The list of commands that we need to execute in order to compose the # final string. - attr_reader :commands + attr_reader :commands # :nodoc: - # Initializes a new instance of the InspectVisitor. - def initialize(indent = +"") + def initialize(indent = +"") # :nodoc: @indent = indent @commands = [] end @@ -37,7 +36,7 @@ module Prism end # Compose the final string. - def compose + def compose # :nodoc: buffer = +"" replace = nil @@ -66,8 +65,7 @@ module Prism end <%- nodes.each do |node| -%> - # Inspect a <%= node.name %> node. - def visit_<%= node.human %>(node) + def visit_<%= node.human %>(node) # :nodoc: commands << [inspect_node(<%= node.name.inspect %>, node), indent] <%- (fields = [node.flags || Prism::Template::Flags.empty, *node.fields]).each_with_index do |field, index| -%> <%- pointer = index == fields.length - 1 ? "└── " : "├── " -%> @@ -114,13 +112,13 @@ module Prism private # Compose a header for the given node. - def inspect_node(name, node) + def inspect_node(name, node) # :nodoc: location = node.location "@ #{name} (location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}))\n" end # Compose a string representing the given inner location field. - def inspect_location(location) + def inspect_location(location) # :nodoc: if location "(#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}) = #{location.slice.inspect}" else diff --git a/templates/lib/prism/mutation_compiler.rb.erb b/templates/lib/prism/mutation_compiler.rb.erb index 565ee4e315..b223860f2f 100644 --- a/templates/lib/prism/mutation_compiler.rb.erb +++ b/templates/lib/prism/mutation_compiler.rb.erb @@ -5,8 +5,7 @@ module Prism class MutationCompiler < Compiler <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> - # Copy a <%= node.name %> node - def visit_<%= node.human %>(node) + def visit_<%= node.human %>(node) # :nodoc: <%- fields = node.fields.select { |field| [Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::NodeListField].include?(field.class) } -%> <%- if fields.any? -%> node.copy(<%= fields.map { |field| "#{field.name}: #{field.is_a?(Prism::Template::NodeListField) ? "visit_all" : "visit"}(node.#{field.name})" }.join(", ") %>) diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index d14a06961a..e2f8c0e53c 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -161,7 +161,7 @@ module Prism # Similar to inspect, but respects the current level of indentation given by # the pretty print object. - def pretty_print(q) + def pretty_print(q) # :nodoc: q.seplist(inspect.chomp.each_line, -> { q.breakable }) do |line| q.text(line.chomp) end @@ -409,8 +409,7 @@ module Prism # def deconstruct: () -> Array[Node?] alias deconstruct child_nodes - # def deconstruct_keys: (Array[Symbol] keys) -> { <%= (["node_id: Integer", "location: Location"] + node.fields.map { |field| "#{field.name}: #{field.rbs_class}" }).join(", ") %> } - def deconstruct_keys(keys) + def deconstruct_keys(keys) # :nodoc: { <%= (["node_id: node_id", "location: location"] + node.fields.map { |field| "#{field.name}: #{field.name}" }).join(", ") %> } end <%- if (node_flags = node.flags) -%> @@ -487,8 +486,7 @@ module Prism <%- end -%> <%- end -%> - # def inspect -> String - def inspect + def inspect # :nodoc: InspectVisitor.compose(self) end diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index 2275d685ca..63ef07cb6e 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -3,7 +3,7 @@ require_relative "polyfill/unpack1" module Prism # A module responsible for deserializing parse results. - module Serialize + module Serialize # :nodoc: # The major version of prism that we are expecting to find in the serialized # strings. MAJOR_VERSION = 1 From 94e55255213a331661f3b3df7ceb85384a055173 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:08:46 +0100 Subject: [PATCH 006/289] More docs improvements (#3910) * Update C call seqs * Prefixing them with self is unusual * Also use `.` instead of `::` to refer to class methods * Capitalize location in docs It allows it to be linked to in docs * Miscelanous other doc tweaks * Format code as code * Nodoc some missed methods * Fix method reference * Really try to nodoc ffi module The previous approach was wrong, to nodoc the class methods it must be specified at the module itself. As a result, the private methods like `dump_options` are also removed. * Remove some def-style comments They are mostly redundant with the method signature and don't look great when rendered. Still remaining on nodes. I will improve docs for them in a separate PR --- config.yml | 177 +++++++++++++------------- ext/prism/api_pack.c | 2 +- ext/prism/extension.c | 80 ++++++------ lib/prism.rb | 8 +- lib/prism/desugar_compiler.rb | 60 ++++----- lib/prism/ffi.rb | 4 +- lib/prism/parse_result.rb | 10 +- lib/prism/pattern.rb | 2 +- templates/lib/prism/dispatcher.rb.erb | 8 -- 9 files changed, 172 insertions(+), 179 deletions(-) diff --git a/config.yml b/config.yml index 4e1560481e..f6e99c66b1 100644 --- a/config.yml +++ b/config.yml @@ -817,7 +817,7 @@ nodes: - name: keyword_loc type: location comment: | - The location of the `alias` keyword. + The Location of the `alias` keyword. alias $foo $bar ^^^^^ @@ -865,7 +865,7 @@ nodes: - name: keyword_loc type: location comment: | - Represents the location of the `alias` keyword. + Represents the Location of the `alias` keyword. alias foo bar ^^^^^ @@ -895,7 +895,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the alternation operator location. + Represents the alternation operator Location. foo => bar | baz ^ @@ -931,7 +931,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `and` keyword or the `&&` operator. + The Location of the `and` keyword or the `&&` operator. left and right ^^^ @@ -966,7 +966,7 @@ nodes: - name: opening_loc type: location? comment: | - Represents the optional source location for the opening token. + Represents the optional source Location for the opening token. [1,2,3] # "[" %w[foo bar baz] # "%w[" @@ -975,7 +975,7 @@ nodes: - name: closing_loc type: location? comment: | - Represents the optional source location for the closing token. + Represents the optional source Location for the closing token. [1,2,3] # "]" %w[foo bar baz] # "]" @@ -1031,14 +1031,14 @@ nodes: - name: opening_loc type: location? comment: | - Represents the opening location of the array pattern. + Represents the opening Location of the array pattern. foo in [1, 2] ^ - name: closing_loc type: location? comment: | - Represents the closing location of the array pattern. + Represents the closing Location of the array pattern. foo in [1, 2] ^ @@ -1089,7 +1089,7 @@ nodes: - name: operator_loc type: location? comment: | - The location of the `=>` operator, if present. + The Location of the `=>` operator, if present. { foo => bar } ^^ @@ -1111,7 +1111,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `**` operator. + The Location of the `**` operator. { **x } ^^ @@ -1140,7 +1140,7 @@ nodes: - name: begin_keyword_loc type: location? comment: | - Represents the location of the `begin` keyword. + Represents the Location of the `begin` keyword. begin x end ^^^^^ @@ -1179,7 +1179,7 @@ nodes: - name: end_keyword_loc type: location? comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. begin x end ^^^ @@ -1204,7 +1204,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the location of the `&` operator. + Represents the Location of the `&` operator. foo(&args) ^ @@ -1265,14 +1265,14 @@ nodes: - name: opening_loc type: location comment: | - Represents the location of the opening `{` or `do`. + Represents the Location of the opening `{` or `do`. [1, 2, 3].each { |i| puts x } ^ - name: closing_loc type: location comment: | - Represents the location of the closing `}` or `end`. + Represents the Location of the closing `}` or `end`. [1, 2, 3].each { |i| puts x } ^ @@ -1295,14 +1295,14 @@ nodes: - name: name_loc type: location? comment: | - Represents the location of the block parameter name. + Represents the Location of the block parameter name. def a(&b) ^ - name: operator_loc type: location comment: | - Represents the location of the `&` operator. + Represents the Location of the `&` operator. def a(&b) ^ @@ -1342,7 +1342,7 @@ nodes: - name: opening_loc type: location? comment: | - Represents the opening location of the block parameters. + Represents the opening Location of the block parameters. -> (a, b = 1; local) { } ^ @@ -1353,7 +1353,7 @@ nodes: - name: closing_loc type: location? comment: | - Represents the closing location of the block parameters. + Represents the closing Location of the block parameters. -> (a, b = 1; local) { } ^ @@ -1383,7 +1383,7 @@ nodes: - name: keyword_loc type: location comment: | - The location of the `break` keyword. + The Location of the `break` keyword. break foo ^^^^^ @@ -1406,14 +1406,14 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar &&= value ^ - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar &&= value ^^^ @@ -1434,7 +1434,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the location of the operator. + Represents the Location of the operator. foo.bar &&= value ^^^ @@ -1471,7 +1471,7 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar ^ @@ -1488,14 +1488,15 @@ nodes: - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar ^^^ - name: opening_loc type: location? comment: | - Represents the location of the left parenthesis. + Represents the Location of the left parenthesis. + foo(bar) ^ - name: arguments @@ -1509,14 +1510,14 @@ nodes: - name: closing_loc type: location? comment: | - Represents the location of the right parenthesis. + Represents the Location of the right parenthesis. foo(bar) ^ - name: equal_loc type: location? comment: | - Represents the location of the equal sign, in the case that this is an attribute write. + Represents the Location of the equal sign, in the case that this is an attribute write. foo.bar = value ^ @@ -1567,14 +1568,14 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar += value ^ - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar += value ^^^ @@ -1602,7 +1603,7 @@ nodes: - name: binary_operator_loc type: location comment: | - Represents the location of the binary operator. + Represents the Location of the binary operator. foo.bar += value ^^ @@ -1633,14 +1634,14 @@ nodes: - name: call_operator_loc type: location? comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar ||= value ^ - name: message_loc type: location? comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar ||= value ^^^ @@ -1661,7 +1662,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the location of the operator. + Represents the Location of the operator. foo.bar ||= value ^^^ @@ -1692,7 +1693,7 @@ nodes: - name: call_operator_loc type: location comment: | - Represents the location of the call operator. + Represents the Location of the call operator. foo.bar = 1 ^ @@ -1706,7 +1707,7 @@ nodes: - name: message_loc type: location comment: | - Represents the location of the message. + Represents the Location of the message. foo.bar = 1 ^^^ @@ -1744,7 +1745,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the location of the `=>` operator. + Represents the Location of the `=>` operator. foo => bar ^^ @@ -1782,14 +1783,14 @@ nodes: - name: case_keyword_loc type: location comment: | - Represents the location of the `case` keyword. + Represents the Location of the `case` keyword. case true; in false; end ^^^^ - name: end_keyword_loc type: location comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. case true; in false; end ^^^ @@ -1829,14 +1830,14 @@ nodes: - name: case_keyword_loc type: location comment: | - Represents the location of the `case` keyword. + Represents the Location of the `case` keyword. case true; when false; end ^^^^ - name: end_keyword_loc type: location comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. case true; when false; end ^^^ @@ -1854,7 +1855,7 @@ nodes: - name: class_keyword_loc type: location comment: | - Represents the location of the `class` keyword. + Represents the Location of the `class` keyword. class Foo end ^^^^^ @@ -1867,7 +1868,7 @@ nodes: - name: inheritance_operator_loc type: location? comment: | - Represents the location of the `<` operator. + Represents the Location of the `<` operator. class Foo < Bar ^ @@ -1893,7 +1894,7 @@ nodes: - name: end_keyword_loc type: location comment: | - Represents the location of the `end` keyword. + Represents the Location of the `end` keyword. class Foo end ^^^ @@ -1920,14 +1921,14 @@ nodes: - name: name_loc type: location comment: | - Represents the location of the variable name. + Represents the Location of the variable name. @@target &&= value ^^^^^^^^ - name: operator_loc type: location comment: | - Represents the location of the `&&=` operator. + Represents the Location of the `&&=` operator. @@target &&= value ^^^ @@ -2015,7 +2016,7 @@ nodes: - name: name_loc type: location comment: | - The location of the variable name. + The Location of the variable name. @@foo = :bar ^^^^^ @@ -2033,7 +2034,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. @@foo = :bar ^ @@ -2129,7 +2130,7 @@ nodes: - name: delimiter_loc type: location comment: | - The location of the `::` delimiter. + The Location of the `::` delimiter. ::Foo ^^ @@ -2139,7 +2140,7 @@ nodes: - name: name_loc type: location comment: | - The location of the name of the constant. + The Location of the name of the constant. ::Foo ^^^ @@ -2215,7 +2216,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. ::ABC = 123 ^ @@ -2275,7 +2276,7 @@ nodes: - name: name_loc type: location comment: | - The location of the constant name. + The Location of the constant name. FOO = 1 ^^^ @@ -2293,7 +2294,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. FOO = :bar ^ @@ -2474,7 +2475,7 @@ nodes: - name: opening_loc type: location? comment: | - The location of the opening brace. + The Location of the opening brace. foo in [*bar, baz, *qux] ^ @@ -2484,7 +2485,7 @@ nodes: - name: closing_loc type: location? comment: | - The location of the closing brace. + The Location of the closing brace. foo in [*bar, baz, *qux] ^ @@ -2574,28 +2575,28 @@ nodes: - name: for_keyword_loc type: location comment: | - The location of the `for` keyword. + The Location of the `for` keyword. for i in a end ^^^ - name: in_keyword_loc type: location comment: | - The location of the `in` keyword. + The Location of the `in` keyword. for i in a end ^^ - name: do_keyword_loc type: location? comment: | - The location of the `do` keyword, if present. + The Location of the `do` keyword, if present. for i in a do end ^^ - name: end_keyword_loc type: location comment: | - The location of the `end` keyword. + The Location of the `end` keyword. for i in a end ^^^ @@ -2723,7 +2724,7 @@ nodes: - name: name_loc type: location comment: | - The location of the global variable's name. + The Location of the global variable's name. $foo = :bar ^^^^ @@ -2741,7 +2742,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. $foo = :bar ^ @@ -2755,7 +2756,7 @@ nodes: - name: opening_loc type: location comment: | - The location of the opening brace. + The Location of the opening brace. { a => b } ^ @@ -2775,7 +2776,7 @@ nodes: - name: closing_loc type: location comment: | - The location of the closing brace. + The Location of the closing brace. { a => b } ^ @@ -2826,7 +2827,7 @@ nodes: - name: opening_loc type: location? comment: | - The location of the opening brace. + The Location of the opening brace. foo => { a: 1 } ^ @@ -2836,7 +2837,7 @@ nodes: - name: closing_loc type: location? comment: | - The location of the closing brace. + The Location of the closing brace. foo => { a: 1 } ^ @@ -2862,7 +2863,7 @@ nodes: - name: if_keyword_loc type: location? comment: | - The location of the `if` keyword if present. + The Location of the `if` keyword if present. bar if foo ^^ @@ -2887,7 +2888,7 @@ nodes: - name: then_keyword_loc type: location? comment: | - The location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. + The Location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. if foo then bar end ^^^^ @@ -2928,7 +2929,7 @@ nodes: - name: end_keyword_loc type: location? comment: | - The location of the `end` keyword if present, `nil` otherwise. + The Location of the `end` keyword if present, `nil` otherwise. if foo bar @@ -3213,7 +3214,7 @@ nodes: - name: name_loc type: location comment: | - The location of the variable name. + The Location of the variable name. @_x = 1 ^^^ @@ -3231,7 +3232,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. @x = y ^ @@ -3538,7 +3539,7 @@ nodes: - name: name_loc type: location comment: | - The location of the variable name. + The Location of the variable name. foo = :bar ^^^ @@ -3560,7 +3561,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `=` operator. + The Location of the `=` operator. x = :y ^ @@ -3660,7 +3661,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the operator. + The Location of the operator. foo => bar ^^ @@ -3781,14 +3782,14 @@ nodes: - name: lparen_loc type: location? comment: | - The location of the opening parenthesis. + The Location of the opening parenthesis. a, (b, c) = 1, 2, 3 ^ - name: rparen_loc type: location? comment: | - The location of the closing parenthesis. + The Location of the closing parenthesis. a, (b, c) = 1, 2, 3 ^ @@ -3870,21 +3871,21 @@ nodes: - name: lparen_loc type: location? comment: | - The location of the opening parenthesis. + The Location of the opening parenthesis. (a, b, c) = 1, 2, 3 ^ - name: rparen_loc type: location? comment: | - The location of the closing parenthesis. + The Location of the closing parenthesis. (a, b, c) = 1, 2, 3 ^ - name: operator_loc type: location comment: | - The location of the operator. + The Location of the operator. a, b, c = 1, 2, 3 ^ @@ -4018,7 +4019,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `or` keyword or the `||` operator. + The Location of the `or` keyword or the `||` operator. left or right ^^ @@ -4101,21 +4102,21 @@ nodes: - name: operator_loc type: location comment: | - The location of the `^` operator + The Location of the `^` operator foo in ^(bar) ^ - name: lparen_loc type: location comment: | - The location of the opening parenthesis. + The Location of the opening parenthesis. foo in ^(bar) ^ - name: rparen_loc type: location comment: | - The location of the closing parenthesis. + The Location of the closing parenthesis. foo in ^(bar) ^ @@ -4145,7 +4146,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `^` operator + The Location of the `^` operator foo in ^bar ^ @@ -4223,7 +4224,7 @@ nodes: - name: operator_loc type: location comment: | - The location of the `..` or `...` operator. + The Location of the `..` or `...` operator. comment: | Represents the use of the `..` or `...` operators. @@ -4449,7 +4450,7 @@ nodes: fields: - name: filepath type: string - comment: Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism::parse*` APIs. + comment: Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism.parse*` APIs. comment: | Represents the use of the `__FILE__` keyword. @@ -4576,7 +4577,7 @@ nodes: - name: keyword_loc type: location comment: | - The location of the `unless` keyword. + The Location of the `unless` keyword. unless cond then bar end ^^^^^^ @@ -4597,7 +4598,7 @@ nodes: - name: then_keyword_loc type: location? comment: | - The location of the `then` keyword, if present. + The Location of the `then` keyword, if present. unless cond then bar end ^^^^ @@ -4621,7 +4622,7 @@ nodes: - name: end_keyword_loc type: location? comment: | - The location of the `end` keyword, if present. + The Location of the `end` keyword, if present. unless cond then bar end ^^^ diff --git a/ext/prism/api_pack.c b/ext/prism/api_pack.c index 98509ae65c..84dc613de0 100644 --- a/ext/prism/api_pack.c +++ b/ext/prism/api_pack.c @@ -173,7 +173,7 @@ pack_encoding_to_ruby(pm_pack_encoding encoding) { /** * call-seq: - * Pack::parse(version, variant, source) -> Format + * parse(version, variant, source) -> Format * * Parse the given source and return a format object. */ diff --git a/ext/prism/extension.c b/ext/prism/extension.c index fe3cd6a8f3..c4395b1cbc 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -390,10 +390,10 @@ dump_input(pm_string_t *input, const pm_options_t *options) { /** * call-seq: - * Prism::dump(source, **options) -> String + * dump(source, **options) -> String * * Dump the AST corresponding to the given string to a string. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE dump(int argc, VALUE *argv, VALUE self) { @@ -423,10 +423,10 @@ dump(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::dump_file(filepath, **options) -> String + * dump_file(filepath, **options) -> String * * Dump the AST corresponding to the given file to a string. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE dump_file(int argc, VALUE *argv, VALUE self) { @@ -795,10 +795,10 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod /** * call-seq: - * Prism::lex(source, **options) -> LexResult + * lex(source, **options) -> LexResult * * Return a LexResult instance that contains an array of Token instances - * corresponding to the given string. For supported options, see Prism::parse. + * corresponding to the given string. For supported options, see Prism.parse. */ static VALUE lex(int argc, VALUE *argv, VALUE self) { @@ -815,10 +815,10 @@ lex(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::lex_file(filepath, **options) -> LexResult + * lex_file(filepath, **options) -> LexResult * * Return a LexResult instance that contains an array of Token instances - * corresponding to the given file. For supported options, see Prism::parse. + * corresponding to the given file. For supported options, see Prism.parse. */ static VALUE lex_file(int argc, VALUE *argv, VALUE self) { @@ -866,7 +866,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) { /** * call-seq: - * Prism::parse(source, **options) -> ParseResult + * parse(source, **options) -> ParseResult * * Parse the given string and return a ParseResult instance. The options that * are supported are: @@ -934,10 +934,10 @@ parse(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_file(filepath, **options) -> ParseResult + * parse_file(filepath, **options) -> ParseResult * * Parse the given file and return a ParseResult instance. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE parse_file(int argc, VALUE *argv, VALUE self) { @@ -969,11 +969,11 @@ profile_input(pm_string_t *input, const pm_options_t *options) { /** * call-seq: - * Prism::profile(source, **options) -> nil + * profile(source, **options) -> nil * * Parse the given string and return nothing. This method is meant to allow * profilers to avoid the overhead of reifying the AST to Ruby. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE profile(int argc, VALUE *argv, VALUE self) { @@ -990,11 +990,11 @@ profile(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::profile_file(filepath, **options) -> nil + * profile_file(filepath, **options) -> nil * * Parse the given file and return nothing. This method is meant to allow * profilers to avoid the overhead of reifying the AST to Ruby. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE profile_file(int argc, VALUE *argv, VALUE self) { @@ -1042,10 +1042,10 @@ parse_stream_fgets(char *string, int size, void *stream) { /** * call-seq: - * Prism::parse_stream(stream, **options) -> ParseResult + * parse_stream(stream, **options) -> ParseResult * * Parse the given object that responds to `gets` and return a ParseResult - * instance. The options that are supported are the same as Prism::parse. + * instance. The options that are supported are the same as Prism.parse. */ static VALUE parse_stream(int argc, VALUE *argv, VALUE self) { @@ -1095,10 +1095,10 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { /** * call-seq: - * Prism::parse_comments(source, **options) -> Array + * parse_comments(source, **options) -> Array * * Parse the given string and return an array of Comment objects. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE parse_comments(int argc, VALUE *argv, VALUE self) { @@ -1115,10 +1115,10 @@ parse_comments(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_file_comments(filepath, **options) -> Array + * parse_file_comments(filepath, **options) -> Array * * Parse the given file and return an array of Comment objects. For supported - * options, see Prism::parse. + * options, see Prism.parse. */ static VALUE parse_file_comments(int argc, VALUE *argv, VALUE self) { @@ -1137,17 +1137,17 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_lex(source, **options) -> ParseLexResult + * parse_lex(source, **options) -> ParseLexResult * * Parse the given string and return a ParseLexResult instance that contains a * 2-element array, where the first element is the AST and the second element is * an array of Token instances. * * This API is only meant to be used in the case where you need both the AST and - * the tokens. If you only need one or the other, use either Prism::parse or - * Prism::lex. + * the tokens. If you only need one or the other, use either Prism.parse or + * Prism.lex. * - * For supported options, see Prism::parse. + * For supported options, see Prism.parse. */ static VALUE parse_lex(int argc, VALUE *argv, VALUE self) { @@ -1164,17 +1164,17 @@ parse_lex(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_lex_file(filepath, **options) -> ParseLexResult + * parse_lex_file(filepath, **options) -> ParseLexResult * * Parse the given file and return a ParseLexResult instance that contains a * 2-element array, where the first element is the AST and the second element is * an array of Token instances. * * This API is only meant to be used in the case where you need both the AST and - * the tokens. If you only need one or the other, use either Prism::parse_file - * or Prism::lex_file. + * the tokens. If you only need one or the other, use either Prism.parse_file + * or Prism.lex_file. * - * For supported options, see Prism::parse. + * For supported options, see Prism.parse. */ static VALUE parse_lex_file(int argc, VALUE *argv, VALUE self) { @@ -1210,10 +1210,10 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { /** * call-seq: - * Prism::parse_success?(source, **options) -> bool + * parse_success?(source, **options) -> bool * * Parse the given string and return true if it parses without errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_success_p(int argc, VALUE *argv, VALUE self) { @@ -1230,10 +1230,10 @@ parse_success_p(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_failure?(source, **options) -> bool + * parse_failure?(source, **options) -> bool * * Parse the given string and return true if it parses with errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_failure_p(int argc, VALUE *argv, VALUE self) { @@ -1242,10 +1242,10 @@ parse_failure_p(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_file_success?(filepath, **options) -> bool + * parse_file_success?(filepath, **options) -> bool * * Parse the given file and return true if it parses without errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_file_success_p(int argc, VALUE *argv, VALUE self) { @@ -1264,10 +1264,10 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) { /** * call-seq: - * Prism::parse_file_failure?(filepath, **options) -> bool + * parse_file_failure?(filepath, **options) -> bool * * Parse the given file and return true if it parses with errors. For - * supported options, see Prism::parse. + * supported options, see Prism.parse. */ static VALUE parse_file_failure_p(int argc, VALUE *argv, VALUE self) { @@ -1298,7 +1298,7 @@ string_query(pm_string_query_t result) { /** * call-seq: - * Prism::StringQuery::local?(string) -> bool + * local?(string) -> bool * * Returns true if the string constitutes a valid local variable name. Note that * this means the names that can be set through Binding#local_variable_set, not @@ -1312,7 +1312,7 @@ string_query_local_p(VALUE self, VALUE string) { /** * call-seq: - * Prism::StringQuery::constant?(string) -> bool + * constant?(string) -> bool * * Returns true if the string constitutes a valid constant name. Note that this * means the names that can be set through Module#const_set, not necessarily the @@ -1326,7 +1326,7 @@ string_query_constant_p(VALUE self, VALUE string) { /** * call-seq: - * Prism::StringQuery::method_name?(string) -> bool + * method_name?(string) -> bool * * Returns true if the string constitutes a valid method name. */ diff --git a/lib/prism.rb b/lib/prism.rb index 781bd4bb01..4fbe67a717 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -56,18 +56,18 @@ def initialize(version) end # :call-seq: - # Prism::lex_compat(source, **options) -> LexCompat::Result + # lex_compat(source, **options) -> LexCompat::Result # # Returns a parse result whose value is an array of tokens that closely - # resembles the return value of Ripper::lex. + # resembles the return value of Ripper.lex. # - # For supported options, see Prism::parse. + # For supported options, see Prism.parse. def self.lex_compat(source, **options) LexCompat.new(source, **options).result # steep:ignore end # :call-seq: - # Prism::load(source, serialized, freeze) -> ParseResult + # load(source, serialized, freeze) -> ParseResult # # Load the serialized AST using the source as a reference into a tree. def self.load(source, serialized, freeze = false) diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb index 5d7d38d841..7d4201c1c4 100644 --- a/lib/prism/desugar_compiler.rb +++ b/lib/prism/desugar_compiler.rb @@ -254,137 +254,137 @@ def desugar # :nodoc: # DesugarCompiler is a compiler that desugars Ruby code into a more primitive # form. This is useful for consumers that want to deal with fewer node types. class DesugarCompiler < MutationCompiler - # @@foo &&= bar + # `@@foo &&= bar` # # becomes # - # @@foo && @@foo = bar + # `@@foo && @@foo = bar` def visit_class_variable_and_write_node(node) node.desugar end - # @@foo ||= bar + # `@@foo ||= bar` # # becomes # - # defined?(@@foo) ? @@foo : @@foo = bar + # `defined?(@@foo) ? @@foo : @@foo = bar` def visit_class_variable_or_write_node(node) node.desugar end - # @@foo += bar + # `@@foo += bar` # # becomes # - # @@foo = @@foo + bar + # `@@foo = @@foo + bar` def visit_class_variable_operator_write_node(node) node.desugar end - # Foo &&= bar + # `Foo &&= bar` # # becomes # - # Foo && Foo = bar + # `Foo && Foo = bar` def visit_constant_and_write_node(node) node.desugar end - # Foo ||= bar + # `Foo ||= bar` # # becomes # - # defined?(Foo) ? Foo : Foo = bar + # `defined?(Foo) ? Foo : Foo = bar` def visit_constant_or_write_node(node) node.desugar end - # Foo += bar + # `Foo += bar` # # becomes # - # Foo = Foo + bar + # `Foo = Foo + bar` def visit_constant_operator_write_node(node) node.desugar end - # $foo &&= bar + # `$foo &&= bar` # # becomes # - # $foo && $foo = bar + # `$foo && $foo = bar` def visit_global_variable_and_write_node(node) node.desugar end - # $foo ||= bar + # `$foo ||= bar` # # becomes # - # defined?($foo) ? $foo : $foo = bar + # `defined?($foo) ? $foo : $foo = bar` def visit_global_variable_or_write_node(node) node.desugar end - # $foo += bar + # `$foo += bar` # # becomes # - # $foo = $foo + bar + # `$foo = $foo + bar` def visit_global_variable_operator_write_node(node) node.desugar end - # @foo &&= bar + # `@foo &&= bar` # # becomes # - # @foo && @foo = bar + # `@foo && @foo = bar` def visit_instance_variable_and_write_node(node) node.desugar end - # @foo ||= bar + # `@foo ||= bar` # # becomes # - # @foo || @foo = bar + # `@foo || @foo = bar` def visit_instance_variable_or_write_node(node) node.desugar end - # @foo += bar + # `@foo += bar` # # becomes # - # @foo = @foo + bar + # `@foo = @foo + bar` def visit_instance_variable_operator_write_node(node) node.desugar end - # foo &&= bar + # `foo &&= bar` # # becomes # - # foo && foo = bar + # `foo && foo = bar` def visit_local_variable_and_write_node(node) node.desugar end - # foo ||= bar + # `foo ||= bar` # # becomes # - # foo || foo = bar + # `foo || foo = bar` def visit_local_variable_or_write_node(node) node.desugar end - # foo += bar + # `foo += bar` # # becomes # - # foo = foo + bar + # `foo = foo + bar` def visit_local_variable_operator_write_node(node) node.desugar end diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 520c773b43..1bcbfc367c 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -12,7 +12,7 @@ # autoloaded from within a non-main Ractor. require "prism/serialize" if defined?(Ractor) -module Prism +module Prism # :nodoc: module LibRubyParser # :nodoc: extend FFI::Library @@ -233,7 +233,7 @@ def self.with_file(filepath) # The version constant is set by reading the result of calling pm_version. VERSION = LibRubyParser.pm_version.read_string.freeze - class << self # :nodoc: + class << self # Mirror the Prism.dump API by using the serialization API. def dump(source, **options) LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) } diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 53ca168c0e..07529c4295 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -519,7 +519,7 @@ def adjoin(string) # This represents a comment that was encountered during parsing. It is the # base class for all comment types. class Comment - # The location of this comment in the source. + # The Location of this comment in the source. attr_reader :location # Create a new comment object with the given location. @@ -556,7 +556,7 @@ def inspect # :nodoc: # EmbDocComment objects correspond to comments that are surrounded by =begin # and =end. class EmbDocComment < Comment - # This can only be true for inline comments. + # Returns false. This can only be true for inline comments. def trailing? false end @@ -670,9 +670,9 @@ def inspect # :nodoc: end end - # This represents the result of a call to ::parse or ::parse_file. It contains - # the requested structure, any comments that were encounters, and any errors - # that were encountered. + # This represents the result of a call to Prism.parse or Prism.parse_file. + # It contains the requested structure, any comments that were encounters, + # and any errors that were encountered. class Result # The list of comments that were encountered during parsing. attr_reader :comments diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index 4a0c5ef54d..dde9d3b6f9 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -41,7 +41,7 @@ class Pattern class CompilationError < StandardError # Create a new CompilationError with the given representation of the node # that caused the error. - def initialize(repr) + def initialize(repr) # :nodoc: super(<<~ERROR) prism was unable to compile the pattern you provided into a usable expression. It failed on to understand the node represented by: diff --git a/templates/lib/prism/dispatcher.rb.erb b/templates/lib/prism/dispatcher.rb.erb index 16ce421cc5..e4ca84db24 100644 --- a/templates/lib/prism/dispatcher.rb.erb +++ b/templates/lib/prism/dispatcher.rb.erb @@ -41,16 +41,12 @@ module Prism end # Register a listener for one or more events. - # - # def register: (Listener, *Symbol) -> void def register(listener, *events) register_events(listener, events) end # Register all public methods of a listener that match the pattern # `on__(enter|leave)`. - # - # def register_public_methods: (Listener) -> void def register_public_methods(listener) register_events(listener, listener.public_methods(false).grep(/\Aon_.+_(?:enter|leave)\z/)) end @@ -61,13 +57,9 @@ module Prism end # Walks `root` dispatching events to all registered listeners. - # - # def dispatch: (Node) -> void alias dispatch visit # Dispatches a single event for `node` to all registered listeners. - # - # def dispatch_once: (Node) -> void def dispatch_once(node) node.accept(DispatchOnce.new(listeners)) end From caf018ec50aa06071330a975358c13a5df3c227f Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:36:18 +0100 Subject: [PATCH 007/289] Improve node docs (#3912) Currently I find them hard to follow because there are just so many methods. This groups them by topic instead so that the more unique methods appear first. I also added call-seqs because we have the type information, so why not. --- templates/lib/prism/node.rb.erb | 192 +++++++++++++++++++++----------- templates/template.rb | 70 ++++++++++++ 2 files changed, 198 insertions(+), 64 deletions(-) diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index e2f8c0e53c..8c88529c66 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -1,9 +1,11 @@ +# :markup: markdown + module Prism # This represents a node in the tree. It is the parent class of all of the # various node types. class Node # A pointer to the source that this node was created from. - attr_reader :source + attr_reader :source # :nodoc: private :source # A unique identifier for this node. This is used in a very specific @@ -30,99 +32,108 @@ module Prism repository.enter(node_id, :location) end - # Delegates to the start_line of the associated location object. + # -------------------------------------------------------------------------- + # :section: Location Delegators + # These methods provide convenient access to the underlying Location object. + # -------------------------------------------------------------------------- + + # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. def start_line location.start_line end - # Delegates to the end_line of the associated location object. + # Delegates to [`end_line`](rdoc-ref:Location#end_line) of the associated location object. def end_line location.end_line end - # The start offset of the node in the source. This method is effectively a - # delegate method to the location object. + # Delegates to [`start_offset`](rdoc-ref:Location#start_offset) of the associated location object. def start_offset location = @location location.is_a?(Location) ? location.start_offset : location >> 32 end - # The end offset of the node in the source. This method is effectively a - # delegate method to the location object. + # Delegates to [`end_offset`](rdoc-ref:Location#end_offset) of the associated location object. def end_offset location = @location location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF)) end - # Delegates to the start_character_offset of the associated location object. + # Delegates to [`start_character_offset`](rdoc-ref:Location#start_character_offset) + # of the associated location object. def start_character_offset location.start_character_offset end - # Delegates to the end_character_offset of the associated location object. + # Delegates to [`end_character_offset`](rdoc-ref:Location#end_character_offset) + # of the associated location object. def end_character_offset location.end_character_offset end - # Delegates to the cached_start_code_units_offset of the associated location - # object. + # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) + # of the associated location object. def cached_start_code_units_offset(cache) location.cached_start_code_units_offset(cache) end - # Delegates to the cached_end_code_units_offset of the associated location - # object. + # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) + # of the associated location object. def cached_end_code_units_offset(cache) location.cached_end_code_units_offset(cache) end - # Delegates to the start_column of the associated location object. + # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. def start_column location.start_column end - # Delegates to the end_column of the associated location object. + # Delegates to [`end_column`](rdoc-ref:Location#end_column) of the associated location object. def end_column location.end_column end - # Delegates to the start_character_column of the associated location object. + # Delegates to [`start_character_column`](rdoc-ref:Location#start_character_column) + # of the associated location object. def start_character_column location.start_character_column end - # Delegates to the end_character_column of the associated location object. + # Delegates to [`end_character_column`](rdoc-ref:Location#end_character_column) + # of the associated location object. def end_character_column location.end_character_column end - # Delegates to the cached_start_code_units_column of the associated location - # object. + # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) + # of the associated location object. def cached_start_code_units_column(cache) location.cached_start_code_units_column(cache) end - # Delegates to the cached_end_code_units_column of the associated location - # object. + # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) + # of the associated location object. def cached_end_code_units_column(cache) location.cached_end_code_units_column(cache) end - # Delegates to the leading_comments of the associated location object. + # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. def leading_comments location.leading_comments end - # Delegates to the trailing_comments of the associated location object. + # Delegates to [`trailing_comments`](rdoc-ref:Location#trailing_comments) of the associated location object. def trailing_comments location.trailing_comments end - # Delegates to the comments of the associated location object. + # Delegates to [`comments`](rdoc-ref:Location#comments) of the associated location object. def comments location.comments end + # :section: + # Returns all of the lines of the source code associated with this node. def source_lines location.source_lines @@ -146,7 +157,7 @@ module Prism # An bitset of flags for this node. There are certain flags that are common # for all nodes, and then some nodes have specific flags. - attr_reader :flags + attr_reader :flags # :nodoc: protected :flags # Returns true if the node has the newline flag set. @@ -248,10 +259,9 @@ module Prism end # -------------------------------------------------------------------------- - # :section: Node interface - # These methods are effectively abstract methods that must be implemented by - # the various subclasses of Node. They are here to make it easier to work - # with typecheckers. + # :section: Node Interface + # These methods are effectively abstract methods that are implemented by + # the various subclasses of Node. # -------------------------------------------------------------------------- # Accepts a visitor and calls back into the specialized visit function. @@ -335,12 +345,23 @@ module Prism <%- end -%> end - # def accept: (Visitor visitor) -> void + # --------- + # :section: Repository + # Methods related to Relocation. + # --------- + + # ---------------------------------------------------------------------------------- + # :section: Node Interface + # These methods are present on all subclasses of Node. + # Read the [node interface docs](rdoc-ref:Node@node-interface) for more information. + # ---------------------------------------------------------------------------------- + + # See Node.accept. def accept(visitor) visitor.visit_<%= node.human %>(self) end - # def child_nodes: () -> Array[Node?] + # See Node.child_nodes. def child_nodes [<%= node.fields.map { |field| case field @@ -350,7 +371,7 @@ module Prism }.compact.join(", ") %>] end - # def each_child_node: () { (Prism::node) -> void } -> void | () -> Enumerator[Prism::node] + # See Node.each_child_node. def each_child_node return to_enum(:each_child_node) unless block_given? @@ -366,7 +387,7 @@ module Prism <%- end -%> end - # def compact_child_nodes: () -> Array[Node] + # See Node.compact_child_nodes. def compact_child_nodes <%- if node.fields.any? { |field| field.is_a?(Prism::Template::OptionalNodeField) } -%> compact = [] #: Array[Prism::node] @@ -391,7 +412,7 @@ module Prism <%- end -%> end - # def comment_targets: () -> Array[Node | Location] + # See Node.comment_targets. def comment_targets [<%= node.fields.map { |field| case field @@ -401,49 +422,85 @@ module Prism }.compact.join(", ") %>] #: Array[Prism::node | Location] end - # def copy: (<%= (["?node_id: Integer", "?location: Location", "?flags: Integer"] + node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" }).join(", ") %>) -> <%= node.name %> + # :call-seq: + # copy(**fields) -> <%= node.name %> + # + # Creates a copy of self with the given fields, using self as the template. def copy(<%= (["node_id", "location", "flags"] + node.fields.map(&:name)).map { |field| "#{field}: self.#{field}" }.join(", ") %>) <%= node.name %>.new(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>) end - # def deconstruct: () -> Array[Node?] alias deconstruct child_nodes def deconstruct_keys(keys) # :nodoc: { <%= (["node_id: node_id", "location: location"] + node.fields.map { |field| "#{field.name}: #{field.name}" }).join(", ") %> } end + + # See `Node#type`. + def type + :<%= node.human %> + end + + # See `Node.type`. + def self.type + :<%= node.human %> + end + + def inspect # :nodoc: + InspectVisitor.compose(self) + end + + # :section: + <%- if (node_flags = node.flags) -%> <%- node_flags.values.each do |value| -%> - - # def <%= value.name.downcase %>?: () -> bool + # :category: Flags + # <%= value.comment %> def <%= value.name.downcase %>? flags.anybits?(<%= node_flags.name %>::<%= value.name %>) end + <%- end -%> <%- end -%> <%- node.fields.each do |field| -%> - + <%- case field -%> + <%- when Prism::Template::LocationField -%> + # :category: Locations + # :call-seq: + # <%= field.name %> -> <%= field.call_seq_type %> + # <%- if field.comment.nil? -%> - # attr_reader <%= field.name %>: <%= field.rbs_class %> + # Returns the Location represented by `<%= field.name %>`. <%- else -%> <%- field.each_comment_line do |line| -%> #<%= line %> <%- end -%> <%- end -%> - <%- case field -%> - <%- when Prism::Template::LocationField -%> def <%= field.name %> location = @<%= field.name %> return location if location.is_a?(Location) @<%= field.name %> = Location.new(source, location >> 32, location & 0xFFFFFFFF) end + # :category: Repository # Save the <%= field.name %> location using the given saved source so that # it can be retrieved later. def save_<%= field.name %>(repository) repository.enter(node_id, :<%= field.name %>) end + <%- when Prism::Template::OptionalLocationField -%> + # :category: Locations + # :call-seq: + # <%= field.name %> -> <%= field.call_seq_type %> + # + <%- if field.comment.nil? -%> + # Returns the Location represented by `<%= field.name %>`. + <%- else -%> + <%- field.each_comment_line do |line| -%> + #<%= line %> + <%- end -%> + <%- end -%> def <%= field.name %> location = @<%= field.name %> case location @@ -456,53 +513,60 @@ module Prism end end + # :category: Repository # Save the <%= field.name %> location using the given saved source so that # it can be retrieved later. def save_<%= field.name %>(repository) repository.enter(node_id, :<%= field.name %>) unless @<%= field.name %>.nil? end <%- else -%> - attr_reader :<%= field.name %> + # :call-seq: + # <%= field.name %> -> <%= field.call_seq_type %> + # + <%- if field.comment.nil? -%> + # Returns the `<%= field.name %>` attribute. + <%- else -%> + <%- field.each_comment_line do |line| -%> + #<%= line %> + <%- end -%> + <%- end -%> + def <%= field.name %> + @<%= field.name %> + end + <%- end -%> <%- end -%> + # :section: Slicing + <%- node.fields.each do |field| -%> <%- case field -%> <%- when Prism::Template::LocationField -%> <%- raise unless field.name.end_with?("_loc") -%> <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - - # def <%= field.name.delete_suffix("_loc") %>: () -> String + # :call-seq: + # <%= field.name.delete_suffix("_loc") %> -> String + # + # Slice the location of <%= field.name %> from the source. def <%= field.name.delete_suffix("_loc") %> <%= field.name %>.slice end + <%- when Prism::Template::OptionalLocationField -%> <%- raise unless field.name.end_with?("_loc") -%> <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - - # def <%= field.name.delete_suffix("_loc") %>: () -> String? + # :call-seq: + # <%= field.name.delete_suffix("_loc") %> -> String | nil + # + # Slice the location of <%= field.name %> from the source. def <%= field.name.delete_suffix("_loc") %> <%= field.name %>&.slice end + <%- end -%> <%- end -%> + # :section: - def inspect # :nodoc: - InspectVisitor.compose(self) - end - - # Return a symbol representation of this node type. See `Node#type`. - def type - :<%= node.human %> - end - - # Return a symbol representation of this node type. See `Node::type`. - def self.type - :<%= node.human %> - end - - # Implements case-equality for the node. This is effectively == but without - # comparing the value of locations. Locations are checked only for presence. - def ===(other) + def ===(other) # :nodoc: other.is_a?(<%= node.name %>)<%= " &&" if (fields = [*node.flags, *node.fields]).any? %> <%- fields.each_with_index do |field, index| -%> <%- if field.is_a?(Prism::Template::LocationField) || field.is_a?(Prism::Template::OptionalLocationField) -%> diff --git a/templates/template.rb b/templates/template.rb index aca626b5eb..0c695fade5 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -156,6 +156,16 @@ def rbs_class end end + def call_seq_type + if specific_kind + specific_kind + elsif union_kind + union_kind.join(" | ") + else + "Node" + end + end + def rbi_class if specific_kind "Prism::#{specific_kind}" @@ -188,6 +198,16 @@ def rbs_class end end + def call_seq_type + if specific_kind + "#{specific_kind} | nil" + elsif union_kind + [*union_kind, "nil"].join(" | ") + else + "Node | nil" + end + end + def rbi_class if specific_kind "T.nilable(Prism::#{specific_kind})" @@ -220,6 +240,16 @@ def rbs_class end end + def call_seq_type + if specific_kind + "Array[#{specific_kind}]" + elsif union_kind + "Array[#{union_kind.join(" | ")}]" + else + "Array[Node]" + end + end + def rbi_class if specific_kind "T::Array[Prism::#{specific_kind}]" @@ -250,6 +280,10 @@ def rbs_class "Symbol" end + def call_seq_type + "Symbol" + end + def rbi_class "Symbol" end @@ -266,6 +300,10 @@ def rbs_class "Symbol?" end + def call_seq_type + "Symbol | nil" + end + def rbi_class "T.nilable(Symbol)" end @@ -282,6 +320,10 @@ def rbs_class "Array[Symbol]" end + def call_seq_type + "Array[Symbol]" + end + def rbi_class "T::Array[Symbol]" end @@ -297,6 +339,10 @@ def rbs_class "String" end + def call_seq_type + "String" + end + def rbi_class "String" end @@ -316,6 +362,10 @@ def rbs_class "Location" end + def call_seq_type + "Location" + end + def rbi_class "Prism::Location" end @@ -335,6 +385,10 @@ def rbs_class "Location?" end + def call_seq_type + "Location | nil" + end + def rbi_class "T.nilable(Prism::Location)" end @@ -350,6 +404,10 @@ def rbs_class "Integer" end + def call_seq_type + "Integer" + end + def rbi_class "Integer" end @@ -365,6 +423,10 @@ def rbs_class "Integer" end + def call_seq_type + "Integer" + end + def rbi_class "Integer" end @@ -381,6 +443,10 @@ def rbs_class "Integer" end + def call_seq_type + "Integer" + end + def rbi_class "Integer" end @@ -397,6 +463,10 @@ def rbs_class "Float" end + def call_seq_type + "Float" + end + def rbi_class "Float" end From 430da84deaa3b8074b733ec0bca608915fa9bbc3 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:36:40 +0100 Subject: [PATCH 008/289] Remove rdoc coverage workaround (#3913) This is long dead code --- rakelib/rdoc.rake | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/rakelib/rdoc.rake b/rakelib/rdoc.rake index 340a5cd831..5bba3e3cd5 100644 --- a/rakelib/rdoc.rake +++ b/rakelib/rdoc.rake @@ -7,30 +7,6 @@ rescue LoadError return end -if RDoc::VERSION <= "6.5.0" - # RDoc 6.5.0 and earlier did not create an rdoc:coverage task. This patches it - # in in the same way newer versions do. - RDoc::Task.prepend( - Module.new { - def define - super.tap do - namespace rdoc_task_name do - desc "Print RDoc coverage report" - task :coverage do - @before_running_rdoc.call if @before_running_rdoc - opts = option_list << "-C" - args = opts + @rdoc_files - - $stderr.puts "rdoc #{args.join(" ")}" if Rake.application.options.trace - RDoc::RDoc.new.document(args) - end - end - end - end - } - ) -end - RDoc::Task.new(:rdoc) do |rdoc| rdoc.main = "README.md" rdoc.markup = "markdown" From 1afdc7252303f4ded470eeda0fcc4d11b9354ca4 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:38:02 +0100 Subject: [PATCH 009/289] Make typechecking work without setting gemfile (#3914) It's annoying having to set `BUNDLE_GEMFILE` manually for this I tried simply putting it in the main gemfile but that would mean it's not usable with ruby-dev because of nokogiri. --- rakelib/typecheck.rake | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index 5da23ac34f..55a8730106 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -1,13 +1,21 @@ # frozen_string_literal: true namespace :typecheck do + def with_gemfile + Bundler.with_original_env do + ENV['BUNDLE_GEMFILE'] = "gemfiles/typecheck/Gemfile" + yield + end + end + task tapioca: :templates do Rake::Task["compile:prism"].invoke - require "tapioca/internal" - Tapioca::Cli.start(["configure"]) - Tapioca::Cli.start(["gems", "--exclude", "prism"]) - Tapioca::Cli.start(["todo"]) + with_gemfile do + sh "bundle", "exec", "tapioca", "configure" + sh "bundle", "exec", "tapioca", "gems", "--exclude", "prism" + sh "bundle", "exec", "tapioca", "todo" + end end desc "Typecheck with Sorbet" @@ -63,11 +71,15 @@ namespace :typecheck do --suppress-error-code=7001 CONFIG - exec "#{::Gem::Specification.find_by_name("sorbet-static").full_gem_path}/libexec/sorbet" + with_gemfile do + sh "bundle", "exec", "srb" + end end desc "Typecheck with Steep" task steep: :templates do - exec Gem.bin_path("steep", "steep"), "check" + with_gemfile do + sh "bundle", "exec", "steep", "check" + end end end From c64260077a753a44f272b52dde4b7f625e210740 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:38:28 +0100 Subject: [PATCH 010/289] Remove explicit rbs dependency (#3915) We don't actually use it. For typechecking, it's just a transitive dependency of tapioca/steep --- gemfiles/2.7/Gemfile | 1 - gemfiles/2.7/Gemfile.lock | 2 -- gemfiles/3.0/Gemfile | 1 - gemfiles/3.0/Gemfile.lock | 4 ---- gemfiles/3.1/Gemfile | 1 - gemfiles/3.1/Gemfile.lock | 4 ---- gemfiles/3.2/Gemfile | 1 - gemfiles/3.2/Gemfile.lock | 4 ---- gemfiles/3.3/Gemfile | 1 - gemfiles/3.3/Gemfile.lock | 4 ---- gemfiles/3.4/Gemfile | 1 - gemfiles/3.4/Gemfile.lock | 4 ---- gemfiles/4.0/Gemfile | 1 - gemfiles/4.0/Gemfile.lock | 4 ---- gemfiles/4.1/Gemfile | 1 - gemfiles/4.1/Gemfile.lock | 4 ---- gemfiles/typecheck/Gemfile | 1 - gemfiles/typecheck/Gemfile.lock | 1 - 18 files changed, 40 deletions(-) diff --git a/gemfiles/2.7/Gemfile b/gemfiles/2.7/Gemfile index 8d1fbb82cd..a3ac724e5e 100644 --- a/gemfiles/2.7/Gemfile +++ b/gemfiles/2.7/Gemfile @@ -10,6 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/2.7/Gemfile.lock b/gemfiles/2.7/Gemfile.lock index f75112d346..fd5d5e89c8 100644 --- a/gemfiles/2.7/Gemfile.lock +++ b/gemfiles/2.7/Gemfile.lock @@ -16,7 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.1.3) ruby_parser (3.21.1) racc (~> 1.5) sexp_processor (~> 4.16) @@ -33,7 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_parser test-unit diff --git a/gemfiles/3.0/Gemfile b/gemfiles/3.0/Gemfile index c52f90eaf8..4000b519d1 100644 --- a/gemfiles/3.0/Gemfile +++ b/gemfiles/3.0/Gemfile @@ -10,7 +10,6 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.0/Gemfile.lock b/gemfiles/3.0/Gemfile.lock index 9174ab2a9e..5a50ce8765 100644 --- a/gemfiles/3.0/Gemfile.lock +++ b/gemfiles/3.0/Gemfile.lock @@ -7,7 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) mini_portile2 (2.8.9) nokogiri (1.17.2) mini_portile2 (~> 2.8.2) @@ -21,8 +20,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.6.1) - logger ruby_memcheck (3.0.1) nokogiri ruby_parser (3.21.1) @@ -41,7 +38,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.1/Gemfile b/gemfiles/3.1/Gemfile index b17401ffc3..b88e0925f1 100644 --- a/gemfiles/3.1/Gemfile +++ b/gemfiles/3.1/Gemfile @@ -10,7 +10,6 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.1/Gemfile.lock b/gemfiles/3.1/Gemfile.lock index 8247f879fd..31f225440a 100644 --- a/gemfiles/3.1/Gemfile.lock +++ b/gemfiles/3.1/Gemfile.lock @@ -7,7 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) mini_portile2 (2.8.9) nokogiri (1.18.10) mini_portile2 (~> 2.8.2) @@ -21,8 +20,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger ruby_memcheck (3.0.1) nokogiri ruby_parser (3.21.1) @@ -41,7 +38,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.2/Gemfile b/gemfiles/3.2/Gemfile index 009b09ec1a..527f61bd5c 100644 --- a/gemfiles/3.2/Gemfile +++ b/gemfiles/3.2/Gemfile @@ -10,7 +10,6 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.2/Gemfile.lock b/gemfiles/3.2/Gemfile.lock index c9c75907d6..e76d556607 100644 --- a/gemfiles/3.2/Gemfile.lock +++ b/gemfiles/3.2/Gemfile.lock @@ -7,7 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) mini_portile2 (2.8.9) nokogiri (1.19.0) mini_portile2 (~> 2.8.2) @@ -21,8 +20,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger ruby_memcheck (3.0.1) nokogiri ruby_parser (3.22.0) @@ -41,7 +38,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.3/Gemfile b/gemfiles/3.3/Gemfile index 73006ce144..557302757f 100644 --- a/gemfiles/3.3/Gemfile +++ b/gemfiles/3.3/Gemfile @@ -10,7 +10,6 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.3/Gemfile.lock b/gemfiles/3.3/Gemfile.lock index d452f1bc2f..cd6f04e894 100644 --- a/gemfiles/3.3/Gemfile.lock +++ b/gemfiles/3.3/Gemfile.lock @@ -7,7 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) mini_portile2 (2.8.9) nokogiri (1.19.0) mini_portile2 (~> 2.8.2) @@ -21,8 +20,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger ruby_memcheck (3.0.1) nokogiri ruby_parser (3.22.0) @@ -41,7 +38,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.4/Gemfile b/gemfiles/3.4/Gemfile index 2e86887f58..260ced90ac 100644 --- a/gemfiles/3.4/Gemfile +++ b/gemfiles/3.4/Gemfile @@ -10,7 +10,6 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.4/Gemfile.lock b/gemfiles/3.4/Gemfile.lock index a1195453db..715b6ade14 100644 --- a/gemfiles/3.4/Gemfile.lock +++ b/gemfiles/3.4/Gemfile.lock @@ -7,7 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - logger (1.7.0) mini_portile2 (2.8.9) nokogiri (1.19.0) mini_portile2 (~> 2.8.2) @@ -21,8 +20,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger ruby_memcheck (3.0.1) nokogiri ruby_parser (3.22.0) @@ -41,7 +38,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/4.0/Gemfile b/gemfiles/4.0/Gemfile index f3fef38fe8..660d3ce929 100644 --- a/gemfiles/4.0/Gemfile +++ b/gemfiles/4.0/Gemfile @@ -11,7 +11,6 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/4.0/Gemfile.lock b/gemfiles/4.0/Gemfile.lock index c7670f7ea1..34273e8ff4 100644 --- a/gemfiles/4.0/Gemfile.lock +++ b/gemfiles/4.0/Gemfile.lock @@ -8,7 +8,6 @@ GEM specs: ast (2.4.3) ffi (1.17.3) - logger (1.7.0) mini_portile2 (2.8.9) nokogiri (1.19.0) mini_portile2 (~> 2.8.2) @@ -22,8 +21,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger ruby_memcheck (3.0.1) nokogiri ruby_parser (3.22.0) @@ -43,7 +40,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/4.1/Gemfile b/gemfiles/4.1/Gemfile index 3fde9d4ac1..3ad947d147 100644 --- a/gemfiles/4.1/Gemfile +++ b/gemfiles/4.1/Gemfile @@ -11,7 +11,6 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/4.1/Gemfile.lock b/gemfiles/4.1/Gemfile.lock index cd652a75b4..4dd58fb002 100644 --- a/gemfiles/4.1/Gemfile.lock +++ b/gemfiles/4.1/Gemfile.lock @@ -8,7 +8,6 @@ GEM specs: ast (2.4.3) ffi (1.17.3) - logger (1.7.0) mini_portile2 (2.8.9) nokogiri (1.19.0) mini_portile2 (~> 2.8.2) @@ -22,8 +21,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rbs (3.10.2) - logger ruby_memcheck (3.0.1) nokogiri ruby_parser (3.22.0) @@ -43,7 +40,6 @@ DEPENDENCIES prism! rake rake-compiler - rbs ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/typecheck/Gemfile b/gemfiles/typecheck/Gemfile index b535d28729..7d552d2404 100644 --- a/gemfiles/typecheck/Gemfile +++ b/gemfiles/typecheck/Gemfile @@ -6,7 +6,6 @@ gem "minitest" gem "parser" gem "rake-compiler" gem "rake" -gem "rbs" gem "ruby_parser" gem "sorbet", "<= 0.6.12666" # until tapioca is bumped gem "steep", ">= 1.7.0.dev.1" diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index d3d512dc9e..d880e049a5 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -131,7 +131,6 @@ DEPENDENCIES parser rake rake-compiler - rbs ruby_parser sorbet (<= 0.6.12666) steep (>= 1.7.0.dev.1) From 8b63780a9d6b7debd4de656f68a0c666cfc2bda1 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:28:18 +0100 Subject: [PATCH 011/289] Remove unneeded exit conditions for `parse_stream` As I understand it, the code operates line-by-line. When finding `__END__`, it has to decide if it is the end marker or just appears as part of of a multi-line literal (see tests). For a future PR I plan to make, `lex_modes` may be empty after parsing finished, even if it was syntax invalid. Currently there will _always_ be errors when lex modes are not popped. So these extra checks are redundant. Basically, if we found `__END__` on a line by itself and there are syntax errors, it's impossible to be the end marker. --- src/prism.c | 24 +------------- test/prism/api/parse_stream_test.rb | 51 +++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/src/prism.c b/src/prism.c index 8f3617adce..34e5d38b0a 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22282,28 +22282,6 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t #undef LINE_SIZE } -/** - * Determine if there was an unterminated heredoc at the end of the input, which - * would mean the stream isn't finished and we should keep reading. - * - * For the other lex modes we can check if the lex mode has been closed, but for - * heredocs when we hit EOF we close the lex mode and then go back to parse the - * rest of the line after the heredoc declaration so that we get more of the - * syntax tree. - */ -static bool -pm_parse_stream_unterminated_heredoc_p(pm_parser_t *parser) { - pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) parser->error_list.head; - - for (; diagnostic != NULL; diagnostic = (pm_diagnostic_t *) diagnostic->node.next) { - if (diagnostic->diag_id == PM_ERR_HEREDOC_TERM) { - return true; - } - } - - return false; -} - /** * Parse a stream of Ruby source and return the tree. * @@ -22319,7 +22297,7 @@ pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); pm_node_t *node = pm_parse(parser); - while (!eof && parser->error_list.size > 0 && (parser->lex_modes.index > 0 || pm_parse_stream_unterminated_heredoc_p(parser))) { + while (!eof && parser->error_list.size > 0) { pm_node_destroy(parser, node); eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); diff --git a/test/prism/api/parse_stream_test.rb b/test/prism/api/parse_stream_test.rb index 1c068c617c..3bc86fbd61 100644 --- a/test/prism/api/parse_stream_test.rb +++ b/test/prism/api/parse_stream_test.rb @@ -30,16 +30,28 @@ def test_multi_read end def test___END__ - io = StringIO.new("1 + 2\n3 + 4\n__END__\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + __END__ + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? assert_equal 2, result.value.statements.body.length - assert_equal "5 + 6", io.read + assert_equal "5 + 6\n", io.read end def test_false___END___in_string - io = StringIO.new("1 + 2\n3 + 4\n\"\n__END__\n\"\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + " + __END__ + " + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -47,7 +59,14 @@ def test_false___END___in_string end def test_false___END___in_regexp - io = StringIO.new("1 + 2\n3 + 4\n/\n__END__\n/\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + / + __END__ + / + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -55,7 +74,14 @@ def test_false___END___in_regexp end def test_false___END___in_list - io = StringIO.new("1 + 2\n3 + 4\n%w[\n__END__\n]\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + %w[ + __END__ + ] + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -63,7 +89,14 @@ def test_false___END___in_list end def test_false___END___in_heredoc - io = StringIO.new("1 + 2\n3 + 4\n<<-EOF\n__END__\nEOF\n5 + 6") + io = StringIO.new(<<~RUBY) + 1 + 2 + 3 + 4 + <<-EOF + __END__ + EOF + 5 + 6 + RUBY result = Prism.parse_stream(io) assert result.success? @@ -71,7 +104,11 @@ def test_false___END___in_heredoc end def test_nul_bytes - io = StringIO.new("1 # \0\0\0 \n2 # \0\0\0\n3") + io = StringIO.new(<<~RUBY) + 1 # \0\0\0\t + 2 # \0\0\0 + 3 + RUBY result = Prism.parse_stream(io) assert result.success? From bf8ce5629332d5c9b92ae994ed691490bb5bb40d Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Fri, 6 Feb 2026 18:37:47 +0100 Subject: [PATCH 012/289] Remove pack parsing It was never adopted by ruby or other implementations. Ruby 4.1 may add new directives, so now is a good time to remove it. It was actually never properly documented (just shows `Prism::Pack` with no methods) so removing seems safe to do even now. --- Makefile | 2 +- docs/build_system.md | 1 - ext/prism/api_pack.c | 276 ------------- ext/prism/extension.c | 1 - ext/prism/extension.h | 1 - include/prism.h | 1 - include/prism/defines.h | 3 - include/prism/pack.h | 163 -------- lib/prism.rb | 1 - lib/prism/pack.rb | 230 ----------- prism.gemspec | 5 - rust/ruby-prism-sys/build/main.rs | 10 - rust/ruby-prism-sys/tests/pack_tests.rs | 57 --- sig/prism/_private/pack.rbs | 69 ---- sig/prism/pack.rbs | 43 -- src/pack.c | 509 ------------------------ 16 files changed, 1 insertion(+), 1371 deletions(-) delete mode 100644 ext/prism/api_pack.c delete mode 100644 include/prism/pack.h delete mode 100644 lib/prism/pack.rb delete mode 100644 rust/ruby-prism-sys/tests/pack_tests.rs delete mode 100644 sig/prism/_private/pack.rbs delete mode 100644 sig/prism/pack.rbs delete mode 100644 src/pack.c diff --git a/Makefile b/Makefile index 265d478734..da6b96a000 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) $(ECHO) "building $@" $(Q) $(WASI_SDK_PATH)/bin/clang --sysroot=$(WASI_SDK_PATH)/share/wasi-sysroot/ \ $(DEBUG_FLAGS) \ - -DPRISM_EXPORT_SYMBOLS -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_JSON -DPRISM_EXCLUDE_PACK \ + -DPRISM_EXPORT_SYMBOLS -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXCLUDE_JSON \ -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(CFLAGS) \ -Wl,--export-all -Wl,--gc-sections -Wl,--strip-all -Wl,--lto-O3 -Wl,--no-entry -mexec-model=reactor \ -Oz -g0 -flto -fdata-sections -ffunction-sections \ diff --git a/docs/build_system.md b/docs/build_system.md index 3595c69741..096edb8ad0 100644 --- a/docs/build_system.md +++ b/docs/build_system.md @@ -113,7 +113,6 @@ MAKEFLAGS="-j10" bundle exec rake compile * `PRISM_ENCODING_EXCLUDE_FULL` - Will cause the library to exclude the full encoding API, and only include the minimal number of encodings to support parsing Ruby code without encoding comments. By default this is off. * `PRISM_EXPORT_SYMBOLS` - Will cause the shared library to export symbols. By default this is off. * `PRISM_EXCLUDE_JSON` - Will cause the library to exclude the JSON API. By default this is off. -* `PRISM_EXCLUDE_PACK` - Will cause the library to exclude the pack API. By default this is off. * `PRISM_EXCLUDE_PRETTYPRINT` - Will cause the library to exclude the prettyprint API. By default this is off. * `PRISM_EXCLUDE_SERIALIZATION` - Will cause the library to exclude the serialization API. By default this is off. * `PRISM_XALLOCATOR` - Will cause the library to use the custom memory allocator. By default this is off. diff --git a/ext/prism/api_pack.c b/ext/prism/api_pack.c deleted file mode 100644 index 84dc613de0..0000000000 --- a/ext/prism/api_pack.c +++ /dev/null @@ -1,276 +0,0 @@ -#include "prism/extension.h" - -#ifdef PRISM_EXCLUDE_PACK - -void -Init_prism_pack(void) {} - -#else - -static VALUE rb_cPrism; -static VALUE rb_cPrismPack; -static VALUE rb_cPrismPackDirective; -static VALUE rb_cPrismPackFormat; - -static VALUE v3_2_0_symbol; -static VALUE pack_symbol; -static VALUE unpack_symbol; - -#if SIZEOF_UINT64_T == SIZEOF_LONG_LONG -# define UINT64T2NUM(x) ULL2NUM(x) -# define NUM2UINT64T(x) (uint64_t)NUM2ULL(x) -#elif SIZEOF_UINT64_T == SIZEOF_LONG -# define UINT64T2NUM(x) ULONG2NUM(x) -# define NUM2UINT64T(x) (uint64_t)NUM2ULONG(x) -#else -// error No uint64_t conversion -#endif - -static VALUE -pack_type_to_symbol(pm_pack_type type) { - switch (type) { - case PM_PACK_SPACE: - return ID2SYM(rb_intern("SPACE")); - case PM_PACK_COMMENT: - return ID2SYM(rb_intern("COMMENT")); - case PM_PACK_INTEGER: - return ID2SYM(rb_intern("INTEGER")); - case PM_PACK_UTF8: - return ID2SYM(rb_intern("UTF8")); - case PM_PACK_BER: - return ID2SYM(rb_intern("BER")); - case PM_PACK_FLOAT: - return ID2SYM(rb_intern("FLOAT")); - case PM_PACK_STRING_SPACE_PADDED: - return ID2SYM(rb_intern("STRING_SPACE_PADDED")); - case PM_PACK_STRING_NULL_PADDED: - return ID2SYM(rb_intern("STRING_NULL_PADDED")); - case PM_PACK_STRING_NULL_TERMINATED: - return ID2SYM(rb_intern("STRING_NULL_TERMINATED")); - case PM_PACK_STRING_MSB: - return ID2SYM(rb_intern("STRING_MSB")); - case PM_PACK_STRING_LSB: - return ID2SYM(rb_intern("STRING_LSB")); - case PM_PACK_STRING_HEX_HIGH: - return ID2SYM(rb_intern("STRING_HEX_HIGH")); - case PM_PACK_STRING_HEX_LOW: - return ID2SYM(rb_intern("STRING_HEX_LOW")); - case PM_PACK_STRING_UU: - return ID2SYM(rb_intern("STRING_UU")); - case PM_PACK_STRING_MIME: - return ID2SYM(rb_intern("STRING_MIME")); - case PM_PACK_STRING_BASE64: - return ID2SYM(rb_intern("STRING_BASE64")); - case PM_PACK_STRING_FIXED: - return ID2SYM(rb_intern("STRING_FIXED")); - case PM_PACK_STRING_POINTER: - return ID2SYM(rb_intern("STRING_POINTER")); - case PM_PACK_MOVE: - return ID2SYM(rb_intern("MOVE")); - case PM_PACK_BACK: - return ID2SYM(rb_intern("BACK")); - case PM_PACK_NULL: - return ID2SYM(rb_intern("NULL")); - default: - return Qnil; - } -} - -static VALUE -pack_signed_to_symbol(pm_pack_signed signed_type) { - switch (signed_type) { - case PM_PACK_UNSIGNED: - return ID2SYM(rb_intern("UNSIGNED")); - case PM_PACK_SIGNED: - return ID2SYM(rb_intern("SIGNED")); - case PM_PACK_SIGNED_NA: - return ID2SYM(rb_intern("SIGNED_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_endian_to_symbol(pm_pack_endian endian) { - switch (endian) { - case PM_PACK_AGNOSTIC_ENDIAN: - return ID2SYM(rb_intern("AGNOSTIC_ENDIAN")); - case PM_PACK_LITTLE_ENDIAN: - return ID2SYM(rb_intern("LITTLE_ENDIAN")); - case PM_PACK_BIG_ENDIAN: - return ID2SYM(rb_intern("BIG_ENDIAN")); - case PM_PACK_NATIVE_ENDIAN: - return ID2SYM(rb_intern("NATIVE_ENDIAN")); - case PM_PACK_ENDIAN_NA: - return ID2SYM(rb_intern("ENDIAN_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_size_to_symbol(pm_pack_size size) { - switch (size) { - case PM_PACK_SIZE_SHORT: - return ID2SYM(rb_intern("SIZE_SHORT")); - case PM_PACK_SIZE_INT: - return ID2SYM(rb_intern("SIZE_INT")); - case PM_PACK_SIZE_LONG: - return ID2SYM(rb_intern("SIZE_LONG")); - case PM_PACK_SIZE_LONG_LONG: - return ID2SYM(rb_intern("SIZE_LONG_LONG")); - case PM_PACK_SIZE_8: - return ID2SYM(rb_intern("SIZE_8")); - case PM_PACK_SIZE_16: - return ID2SYM(rb_intern("SIZE_16")); - case PM_PACK_SIZE_32: - return ID2SYM(rb_intern("SIZE_32")); - case PM_PACK_SIZE_64: - return ID2SYM(rb_intern("SIZE_64")); - case PM_PACK_SIZE_P: - return ID2SYM(rb_intern("SIZE_P")); - case PM_PACK_SIZE_NA: - return ID2SYM(rb_intern("SIZE_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_length_type_to_symbol(pm_pack_length_type length_type) { - switch (length_type) { - case PM_PACK_LENGTH_FIXED: - return ID2SYM(rb_intern("LENGTH_FIXED")); - case PM_PACK_LENGTH_MAX: - return ID2SYM(rb_intern("LENGTH_MAX")); - case PM_PACK_LENGTH_RELATIVE: - return ID2SYM(rb_intern("LENGTH_RELATIVE")); - case PM_PACK_LENGTH_NA: - return ID2SYM(rb_intern("LENGTH_NA")); - default: - return Qnil; - } -} - -static VALUE -pack_encoding_to_ruby(pm_pack_encoding encoding) { - int index; - switch (encoding) { - case PM_PACK_ENCODING_ASCII_8BIT: - index = rb_ascii8bit_encindex(); - break; - case PM_PACK_ENCODING_US_ASCII: - index = rb_usascii_encindex(); - break; - case PM_PACK_ENCODING_UTF_8: - index = rb_utf8_encindex(); - break; - default: - return Qnil; - } - return rb_enc_from_encoding(rb_enc_from_index(index)); -} - -/** - * call-seq: - * parse(version, variant, source) -> Format - * - * Parse the given source and return a format object. - */ -static VALUE -pack_parse(VALUE self, VALUE version_symbol, VALUE variant_symbol, VALUE format_string) { - if (version_symbol != v3_2_0_symbol) { - rb_raise(rb_eArgError, "invalid version"); - } - - pm_pack_variant variant; - if (variant_symbol == pack_symbol) { - variant = PM_PACK_VARIANT_PACK; - } else if (variant_symbol == unpack_symbol) { - variant = PM_PACK_VARIANT_UNPACK; - } else { - rb_raise(rb_eArgError, "invalid variant"); - } - - StringValue(format_string); - - const char *format = RSTRING_PTR(format_string); - const char *format_end = format + RSTRING_LEN(format_string); - pm_pack_encoding encoding = PM_PACK_ENCODING_START; - - VALUE directives_array = rb_ary_new(); - - while (format < format_end) { - pm_pack_type type; - pm_pack_signed signed_type; - pm_pack_endian endian; - pm_pack_size size; - pm_pack_length_type length_type; - uint64_t length; - - const char *directive_start = format; - - pm_pack_result parse_result = pm_pack_parse(variant, &format, format_end, &type, &signed_type, &endian, - &size, &length_type, &length, &encoding); - - const char *directive_end = format; - - switch (parse_result) { - case PM_PACK_OK: - break; - case PM_PACK_ERROR_UNSUPPORTED_DIRECTIVE: - rb_raise(rb_eArgError, "unsupported directive"); - case PM_PACK_ERROR_UNKNOWN_DIRECTIVE: - rb_raise(rb_eArgError, "unsupported directive"); - case PM_PACK_ERROR_LENGTH_TOO_BIG: - rb_raise(rb_eRangeError, "pack length too big"); - case PM_PACK_ERROR_BANG_NOT_ALLOWED: - rb_raise(rb_eRangeError, "bang not allowed"); - case PM_PACK_ERROR_DOUBLE_ENDIAN: - rb_raise(rb_eRangeError, "double endian"); - default: - rb_bug("parse result"); - } - - if (type == PM_PACK_END) { - break; - } - - VALUE directive_args[9] = { - version_symbol, - variant_symbol, - rb_usascii_str_new(directive_start, directive_end - directive_start), - pack_type_to_symbol(type), - pack_signed_to_symbol(signed_type), - pack_endian_to_symbol(endian), - pack_size_to_symbol(size), - pack_length_type_to_symbol(length_type), - UINT64T2NUM(length) - }; - - rb_ary_push(directives_array, rb_class_new_instance(9, directive_args, rb_cPrismPackDirective)); - } - - VALUE format_args[2]; - format_args[0] = directives_array; - format_args[1] = pack_encoding_to_ruby(encoding); - return rb_class_new_instance(2, format_args, rb_cPrismPackFormat); -} - -/** - * The function that gets called when Ruby initializes the prism extension. - */ -void -Init_prism_pack(void) { - rb_cPrism = rb_define_module("Prism"); - rb_cPrismPack = rb_define_module_under(rb_cPrism, "Pack"); - rb_cPrismPackDirective = rb_define_class_under(rb_cPrismPack, "Directive", rb_cObject); - rb_cPrismPackFormat = rb_define_class_under(rb_cPrismPack, "Format", rb_cObject); - rb_define_singleton_method(rb_cPrismPack, "parse", pack_parse, 3); - - v3_2_0_symbol = ID2SYM(rb_intern("v3_2_0")); - pack_symbol = ID2SYM(rb_intern("pack")); - unpack_symbol = ID2SYM(rb_intern("unpack")); -} - -#endif diff --git a/ext/prism/extension.c b/ext/prism/extension.c index c4395b1cbc..7a5dd8a984 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -1434,5 +1434,4 @@ Init_prism(void) { // Next, initialize the other APIs. Init_prism_api_node(); - Init_prism_pack(); } diff --git a/ext/prism/extension.h b/ext/prism/extension.h index a2aaa6388f..d0cbc2ff53 100644 --- a/ext/prism/extension.h +++ b/ext/prism/extension.h @@ -14,7 +14,6 @@ VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding * VALUE pm_integer_new(const pm_integer_t *integer); void Init_prism_api_node(void); -void Init_prism_pack(void); RUBY_FUNC_EXPORTED void Init_prism(void); #endif diff --git a/include/prism.h b/include/prism.h index c1ce582997..c17d759fea 100644 --- a/include/prism.h +++ b/include/prism.h @@ -17,7 +17,6 @@ #include "prism/diagnostic.h" #include "prism/node.h" #include "prism/options.h" -#include "prism/pack.h" #include "prism/parser.h" #include "prism/prettyprint.h" #include "prism/regexp.h" diff --git a/include/prism/defines.h b/include/prism/defines.h index f6bd1dbe40..f2e814fa1d 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -215,9 +215,6 @@ /** Exclude the JSON serialization API. */ #define PRISM_EXCLUDE_JSON - /** Exclude the Array#pack parser API. */ - #define PRISM_EXCLUDE_PACK - /** Exclude the prettyprint API. */ #define PRISM_EXCLUDE_PRETTYPRINT diff --git a/include/prism/pack.h b/include/prism/pack.h deleted file mode 100644 index 0b0b4b19cc..0000000000 --- a/include/prism/pack.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @file pack.h - * - * A pack template string parser. - */ -#ifndef PRISM_PACK_H -#define PRISM_PACK_H - -#include "prism/defines.h" - -// We optionally support parsing String#pack templates. For systems that don't -// want or need this functionality, it can be turned off with the -// PRISM_EXCLUDE_PACK define. -#ifdef PRISM_EXCLUDE_PACK - -void pm_pack_parse(void); - -#else - -#include -#include - -/** The version of the pack template language that we are parsing. */ -typedef enum pm_pack_version { - PM_PACK_VERSION_3_2_0 -} pm_pack_version; - -/** The type of pack template we are parsing. */ -typedef enum pm_pack_variant { - PM_PACK_VARIANT_PACK, - PM_PACK_VARIANT_UNPACK -} pm_pack_variant; - -/** A directive within the pack template. */ -typedef enum pm_pack_type { - PM_PACK_SPACE, - PM_PACK_COMMENT, - PM_PACK_INTEGER, - PM_PACK_UTF8, - PM_PACK_BER, - PM_PACK_FLOAT, - PM_PACK_STRING_SPACE_PADDED, - PM_PACK_STRING_NULL_PADDED, - PM_PACK_STRING_NULL_TERMINATED, - PM_PACK_STRING_MSB, - PM_PACK_STRING_LSB, - PM_PACK_STRING_HEX_HIGH, - PM_PACK_STRING_HEX_LOW, - PM_PACK_STRING_UU, - PM_PACK_STRING_MIME, - PM_PACK_STRING_BASE64, - PM_PACK_STRING_FIXED, - PM_PACK_STRING_POINTER, - PM_PACK_MOVE, - PM_PACK_BACK, - PM_PACK_NULL, - PM_PACK_END -} pm_pack_type; - -/** The signness of a pack directive. */ -typedef enum pm_pack_signed { - PM_PACK_UNSIGNED, - PM_PACK_SIGNED, - PM_PACK_SIGNED_NA -} pm_pack_signed; - -/** The endianness of a pack directive. */ -typedef enum pm_pack_endian { - PM_PACK_AGNOSTIC_ENDIAN, - PM_PACK_LITTLE_ENDIAN, // aka 'VAX', or 'V' - PM_PACK_BIG_ENDIAN, // aka 'network', or 'N' - PM_PACK_NATIVE_ENDIAN, - PM_PACK_ENDIAN_NA -} pm_pack_endian; - -/** The size of an integer pack directive. */ -typedef enum pm_pack_size { - PM_PACK_SIZE_SHORT, - PM_PACK_SIZE_INT, - PM_PACK_SIZE_LONG, - PM_PACK_SIZE_LONG_LONG, - PM_PACK_SIZE_8, - PM_PACK_SIZE_16, - PM_PACK_SIZE_32, - PM_PACK_SIZE_64, - PM_PACK_SIZE_P, - PM_PACK_SIZE_NA -} pm_pack_size; - -/** The type of length of a pack directive. */ -typedef enum pm_pack_length_type { - PM_PACK_LENGTH_FIXED, - PM_PACK_LENGTH_MAX, - PM_PACK_LENGTH_RELATIVE, // special case for unpack @* - PM_PACK_LENGTH_NA -} pm_pack_length_type; - -/** The type of encoding for a pack template string. */ -typedef enum pm_pack_encoding { - PM_PACK_ENCODING_START, - PM_PACK_ENCODING_ASCII_8BIT, - PM_PACK_ENCODING_US_ASCII, - PM_PACK_ENCODING_UTF_8 -} pm_pack_encoding; - -/** The result of parsing a pack template. */ -typedef enum pm_pack_result { - PM_PACK_OK, - PM_PACK_ERROR_UNSUPPORTED_DIRECTIVE, - PM_PACK_ERROR_UNKNOWN_DIRECTIVE, - PM_PACK_ERROR_LENGTH_TOO_BIG, - PM_PACK_ERROR_BANG_NOT_ALLOWED, - PM_PACK_ERROR_DOUBLE_ENDIAN -} pm_pack_result; - -/** - * Parse a single directive from a pack or unpack format string. - * - * @param variant (in) pack or unpack - * @param format (in, out) the start of the next directive to parse on calling, - * and advanced beyond the parsed directive on return, or as much of it as - * was consumed until an error was encountered - * @param format_end (in) the end of the format string - * @param type (out) the type of the directive - * @param signed_type (out) whether the value is signed - * @param endian (out) the endianness of the value - * @param size (out) the size of the value - * @param length_type (out) what kind of length is specified - * @param length (out) the length of the directive - * @param encoding (in, out) takes the current encoding of the string which - * would result from parsing the whole format string, and returns a possibly - * changed directive - the encoding should be `PM_PACK_ENCODING_START` when - * pm_pack_parse is called for the first directive in a format string - * - * @return `PM_PACK_OK` on success or `PM_PACK_ERROR_*` on error - * @note Consult Ruby documentation for the meaning of directives. - */ -PRISM_EXPORTED_FUNCTION pm_pack_result -pm_pack_parse( - pm_pack_variant variant, - const char **format, - const char *format_end, - pm_pack_type *type, - pm_pack_signed *signed_type, - pm_pack_endian *endian, - pm_pack_size *size, - pm_pack_length_type *length_type, - uint64_t *length, - pm_pack_encoding *encoding -); - -/** - * Prism abstracts sizes away from the native system - this converts an abstract - * size to a native size. - * - * @param size The abstract size to convert. - * @return The native size. - */ -PRISM_EXPORTED_FUNCTION size_t pm_size_to_native(pm_pack_size size); - -#endif - -#endif diff --git a/lib/prism.rb b/lib/prism.rb index 4fbe67a717..5b3ce8752c 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -21,7 +21,6 @@ module Prism autoload :InspectVisitor, "prism/inspect_visitor" autoload :LexCompat, "prism/lex_compat" autoload :MutationCompiler, "prism/mutation_compiler" - autoload :Pack, "prism/pack" autoload :Pattern, "prism/pattern" autoload :Reflection, "prism/reflection" autoload :Relocation, "prism/relocation" diff --git a/lib/prism/pack.rb b/lib/prism/pack.rb deleted file mode 100644 index 166c04c3c0..0000000000 --- a/lib/prism/pack.rb +++ /dev/null @@ -1,230 +0,0 @@ -# frozen_string_literal: true -# :markup: markdown -# typed: ignore - -# -module Prism - # A parser for the pack template language. - module Pack - %i[ - SPACE - COMMENT - INTEGER - UTF8 - BER - FLOAT - STRING_SPACE_PADDED - STRING_NULL_PADDED - STRING_NULL_TERMINATED - STRING_MSB - STRING_LSB - STRING_HEX_HIGH - STRING_HEX_LOW - STRING_UU - STRING_MIME - STRING_BASE64 - STRING_FIXED - STRING_POINTER - MOVE - BACK - NULL - - UNSIGNED - SIGNED - SIGNED_NA - - AGNOSTIC_ENDIAN - LITTLE_ENDIAN - BIG_ENDIAN - NATIVE_ENDIAN - ENDIAN_NA - - SIZE_SHORT - SIZE_INT - SIZE_LONG - SIZE_LONG_LONG - SIZE_8 - SIZE_16 - SIZE_32 - SIZE_64 - SIZE_P - SIZE_NA - - LENGTH_FIXED - LENGTH_MAX - LENGTH_RELATIVE - LENGTH_NA - ].each do |const| - const_set(const, const) - end - - # A directive in the pack template language. - class Directive - # A symbol representing the version of Ruby. - attr_reader :version - - # A symbol representing whether or not we are packing or unpacking. - attr_reader :variant - - # A byteslice of the source string that this directive represents. - attr_reader :source - - # The type of the directive. - attr_reader :type - - # The type of signedness of the directive. - attr_reader :signed - - # The type of endianness of the directive. - attr_reader :endian - - # The size of the directive. - attr_reader :size - - # The length type of this directive (used for integers). - attr_reader :length_type - - # The length of this directive (used for integers). - attr_reader :length - - # Initialize a new directive with the given values. - def initialize(version, variant, source, type, signed, endian, size, length_type, length) - @version = version - @variant = variant - @source = source - @type = type - @signed = signed - @endian = endian - @size = size - @length_type = length_type - @length = length - end - - # The descriptions of the various types of endianness. - ENDIAN_DESCRIPTIONS = { - AGNOSTIC_ENDIAN: "agnostic", - LITTLE_ENDIAN: "little-endian (VAX)", - BIG_ENDIAN: "big-endian (network)", - NATIVE_ENDIAN: "native-endian", - ENDIAN_NA: "n/a" - } - - # The descriptions of the various types of signedness. - SIGNED_DESCRIPTIONS = { - UNSIGNED: "unsigned", - SIGNED: "signed", - SIGNED_NA: "n/a" - } - - # The descriptions of the various types of sizes. - SIZE_DESCRIPTIONS = { - SIZE_SHORT: "short", - SIZE_INT: "int-width", - SIZE_LONG: "long", - SIZE_LONG_LONG: "long long", - SIZE_8: "8-bit", - SIZE_16: "16-bit", - SIZE_32: "32-bit", - SIZE_64: "64-bit", - SIZE_P: "pointer-width" - } - - # Provide a human-readable description of the directive. - def describe - case type - when SPACE - "whitespace" - when COMMENT - "comment" - when INTEGER - if size == SIZE_8 - base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} integer" - else - base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} integer" - end - case length_type - when LENGTH_FIXED - if length > 1 - base + ", x#{length}" - else - base - end - when LENGTH_MAX - base + ", as many as possible" - else - raise - end - when UTF8 - "UTF-8 character" - when BER - "BER-compressed integer" - when FLOAT - "#{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} float" - when STRING_SPACE_PADDED - "arbitrary binary string (space padded)" - when STRING_NULL_PADDED - "arbitrary binary string (null padded, count is width)" - when STRING_NULL_TERMINATED - "arbitrary binary string (null padded, count is width), except that null is added with *" - when STRING_MSB - "bit string (MSB first)" - when STRING_LSB - "bit string (LSB first)" - when STRING_HEX_HIGH - "hex string (high nibble first)" - when STRING_HEX_LOW - "hex string (low nibble first)" - when STRING_UU - "UU-encoded string" - when STRING_MIME - "quoted printable, MIME encoding" - when STRING_BASE64 - "base64 encoded string" - when STRING_FIXED - "pointer to a structure (fixed-length string)" - when STRING_POINTER - "pointer to a null-terminated string" - when MOVE - "move to absolute position" - when BACK - "back up a byte" - when NULL - "null byte" - else - raise - end - end - end - - # The result of parsing a pack template. - class Format - # A list of the directives in the template. - attr_reader :directives - - # The encoding of the template. - attr_reader :encoding - - # Create a new Format with the given directives and encoding. - def initialize(directives, encoding) - @directives = directives - @encoding = encoding - end - - # Provide a human-readable description of the format. - def describe - source_width = directives.map { |d| d.source.inspect.length }.max - directive_lines = directives.map do |directive| - if directive.type == SPACE - source = directive.source.inspect - else - source = directive.source - end - # @type var source_width: Integer - " #{source.ljust(source_width)} #{directive.describe}" - end - - (["Directives:"] + directive_lines + ["Encoding:", " #{encoding}"]).join("\n") - end - end - end -end diff --git a/prism.gemspec b/prism.gemspec index 20c66a562e..c5c315fc8d 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -42,7 +42,6 @@ Gem::Specification.new do |spec| "docs/serialization.md", "docs/testing.md", "ext/prism/api_node.c", - "ext/prism/api_pack.c", "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", @@ -52,7 +51,6 @@ Gem::Specification.new do |spec| "include/prism/encoding.h", "include/prism/node.h", "include/prism/options.h", - "include/prism/pack.h", "include/prism/parser.h", "include/prism/prettyprint.h", "include/prism/regexp.h", @@ -80,7 +78,6 @@ Gem::Specification.new do |spec| "lib/prism/mutation_compiler.rb", "lib/prism/node_ext.rb", "lib/prism/node.rb", - "lib/prism/pack.rb", "lib/prism/parse_result.rb", "lib/prism/parse_result/comments.rb", "lib/prism/parse_result/errors.rb", @@ -133,7 +130,6 @@ Gem::Specification.new do |spec| "sig/prism/mutation_compiler.rbs", "sig/prism/node_ext.rbs", "sig/prism/node.rbs", - "sig/prism/pack.rbs", "sig/prism/parse_result.rbs", "sig/prism/parse_result/comments.rbs", "sig/prism/pattern.rbs", @@ -146,7 +142,6 @@ Gem::Specification.new do |spec| "src/encoding.c", "src/node.c", "src/options.c", - "src/pack.c", "src/prettyprint.c", "src/prism.c", "src/regexp.c", diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 798d06d8ff..b403747ed8 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -120,7 +120,6 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_type("pm_magic_comment_t") .allowlist_type("pm_node_t") .allowlist_type("pm_node_type") - .allowlist_type("pm_pack_size") .allowlist_type("pm_parser_t") .allowlist_type("pm_string_t") .allowlist_type(r"^pm_\w+_node_t") @@ -129,19 +128,10 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .rustified_non_exhaustive_enum("pm_comment_type_t") .rustified_non_exhaustive_enum(r"pm_\w+_flags") .rustified_non_exhaustive_enum("pm_node_type") - .rustified_non_exhaustive_enum("pm_pack_encoding") - .rustified_non_exhaustive_enum("pm_pack_endian") - .rustified_non_exhaustive_enum("pm_pack_length_type") - .rustified_non_exhaustive_enum("pm_pack_result") - .rustified_non_exhaustive_enum("pm_pack_signed") - .rustified_non_exhaustive_enum("pm_pack_size") - .rustified_non_exhaustive_enum("pm_pack_type") - .rustified_non_exhaustive_enum("pm_pack_variant") // Functions .allowlist_function("pm_list_empty_p") .allowlist_function("pm_list_free") .allowlist_function("pm_node_destroy") - .allowlist_function("pm_pack_parse") .allowlist_function("pm_parse") .allowlist_function("pm_parser_free") .allowlist_function("pm_parser_init") diff --git a/rust/ruby-prism-sys/tests/pack_tests.rs b/rust/ruby-prism-sys/tests/pack_tests.rs deleted file mode 100644 index 63bc1cb1ea..0000000000 --- a/rust/ruby-prism-sys/tests/pack_tests.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::{ffi::CString, mem::MaybeUninit}; - -use ruby_prism_sys::{ - pm_pack_encoding, pm_pack_endian, pm_pack_length_type, pm_pack_parse, pm_pack_result, pm_pack_signed, pm_pack_size, - pm_pack_type, pm_pack_variant, pm_size_to_native, -}; - -#[test] -fn pack_parse_test() { - let variant_arg = pm_pack_variant::PM_PACK_VARIANT_PACK; - let first_format = CString::new("C").unwrap(); - let end_format = CString::new("").unwrap(); - let mut format = vec![first_format.as_ptr(), end_format.as_ptr()]; - - let mut type_out = MaybeUninit::::uninit(); - let mut signed_type_out = MaybeUninit::::uninit(); - let mut endian_out = MaybeUninit::::uninit(); - let mut size_out = MaybeUninit::::uninit(); - let mut length_type_out = MaybeUninit::::uninit(); - let mut length_out = 0_u64; - let mut encoding_out = MaybeUninit::::uninit(); - - unsafe { - let result = pm_pack_parse( - variant_arg, - format.as_mut_ptr(), - end_format.as_ptr(), - type_out.as_mut_ptr(), - signed_type_out.as_mut_ptr(), - endian_out.as_mut_ptr(), - size_out.as_mut_ptr(), - length_type_out.as_mut_ptr(), - &raw mut length_out, - encoding_out.as_mut_ptr(), - ); - - assert_eq!(result, pm_pack_result::PM_PACK_OK); - - let type_out = type_out.assume_init(); - let signed_type_out = signed_type_out.assume_init(); - let endian_out = endian_out.assume_init(); - let size_out = size_out.assume_init(); - let length_type_out = length_type_out.assume_init(); - let encoding_out = encoding_out.assume_init(); - - assert_eq!(type_out, pm_pack_type::PM_PACK_INTEGER); - assert_eq!(signed_type_out, pm_pack_signed::PM_PACK_UNSIGNED); - assert_eq!(endian_out, pm_pack_endian::PM_PACK_AGNOSTIC_ENDIAN); - assert_eq!(size_out, pm_pack_size::PM_PACK_SIZE_8); - assert_eq!(length_type_out, pm_pack_length_type::PM_PACK_LENGTH_FIXED); - assert_eq!(length_out, 1); - assert_eq!(encoding_out, pm_pack_encoding::PM_PACK_ENCODING_ASCII_8BIT); - - let native_size = pm_size_to_native(size_out); - assert_eq!(native_size, 1); - } -} diff --git a/sig/prism/_private/pack.rbs b/sig/prism/_private/pack.rbs deleted file mode 100644 index ef1eb43d04..0000000000 --- a/sig/prism/_private/pack.rbs +++ /dev/null @@ -1,69 +0,0 @@ -module Prism - module Pack - SPACE: :SPACE - COMMENT: :COMMENT - INTEGER: :INTEGER - UTF8: :UTF8 - BER: :BER - FLOAT: :FLOAT - STRING_SPACE_PADDED: :STRING_SPACE_PADDED - STRING_NULL_PADDED: :STRING_NULL_PADDED - STRING_NULL_TERMINATED: :STRING_NULL_TERMINATED - STRING_MSB: :STRING_MSB - STRING_LSB: :STRING_LSB - STRING_HEX_HIGH: :STRING_HEX_HIGH - STRING_HEX_LOW: :STRING_HEX_LOW - STRING_UU: :STRING_UU - STRING_MIME: :STRING_MIME - STRING_BASE64: :STRING_BASE64 - STRING_FIXED: :STRING_FIXED - STRING_POINTER: :STRING_POINTER - MOVE: :MOVE - BACK: :BACK - NULL: :NULL - UNSIGNED: :UNSIGNED - SIGNED: :SIGNED - SIGNED_NA: :SIGNED_NA - AGNOSTIC_ENDIAN: :AGNOSTIC_ENDIAN - LITTLE_ENDIAN: :LITTLE_ENDIAN - BIG_ENDIAN: :BIG_ENDIAN - NATIVE_ENDIAN: :NATIVE_ENDIAN - ENDIAN_NA: :ENDIAN_NA - SIZE_SHORT: :SIZE_SHORT - SIZE_INT: :SIZE_INT - SIZE_LONG: :SIZE_LONG - SIZE_LONG_LONG: :SIZE_LONG_LONG - SIZE_8: :SIZE_8 - SIZE_16: :SIZE_16 - SIZE_32: :SIZE_32 - SIZE_64: :SIZE_64 - SIZE_P: :SIZE_P - SIZE_NA: :SIZE_NA - LENGTH_FIXED: :LENGTH_FIXED - LENGTH_MAX: :LENGTH_MAX - LENGTH_RELATIVE: :LENGTH_RELATIVE - LENGTH_NA: :LENGTH_NA - - class Directive - ENDIAN_DESCRIPTIONS: Hash[endianness, String] - SIGNED_DESCRIPTIONS: Hash[signness, String] - SIZE_DESCRIPTIONS: Hash[size, String] - - def initialize: ( - Symbol version, - variant variant, - String source, - directive_type type, - signness signed, - endianness endian, - size size, - length_type length_type, - Integer length - ) -> void - end - - class Format - def initialize: (Array[Directive] directives, Encoding encoding) -> void - end - end -end diff --git a/sig/prism/pack.rbs b/sig/prism/pack.rbs deleted file mode 100644 index acbc92b69e..0000000000 --- a/sig/prism/pack.rbs +++ /dev/null @@ -1,43 +0,0 @@ -module Prism - module Pack - type variant = :pack | :unpack - - def self.parse: (Symbol version, variant variant, String source) -> Format - - class Directive - type directive_type = :SPACE | :COMMENT | :INTEGER | :UTF8 | :BER | :FLOAT | :STRING_SPACE_PADDED | - :STRING_NULL_PADDED | :STRING_NULL_TERMINATED | :STRING_MSB | :STRING_LSB | - :STRING_HEX_HIGH | :STRING_HEX_LOW | :STRING_UU | :STRING_MIME | :STRING_BASE64 | - :STRING_FIXED | :STRING_POINTER | :MOVE | :BACK | :NULL - - type signness = :UNSIGNED | :SIGNED | :SIGNED_NA - - type endianness = :AGNOSTIC_ENDIAN | :LITTLE_ENDIAN | :BIG_ENDIAN | :NATIVE_ENDIAN | :ENDIAN_NA - - type size = :SIZE_SHORT | :SIZE_INT | :SIZE_LONG | :SIZE_LONG_LONG | :SIZE_8 | :SIZE_16 | :SIZE_32 | - :SIZE_64 | :SIZE_P | :SIZE_NA - - type length_type = :LENGTH_FIXED | :LENGTH_MAX | :LENGTH_RELATIVE | :LENGTH_NA - - - attr_reader version: Symbol - attr_reader variant: variant - attr_reader source: String - attr_reader type: directive_type - attr_reader signed: signness - attr_reader endian: endianness - attr_reader size: size - attr_reader length_type: length_type - attr_reader length: Integer - - def describe: () -> String - end - - class Format - attr_reader directives: Array[Directive] - attr_reader encoding: Encoding - - def describe: () -> String - end - end -end diff --git a/src/pack.c b/src/pack.c deleted file mode 100644 index 1388ca8a3b..0000000000 --- a/src/pack.c +++ /dev/null @@ -1,509 +0,0 @@ -#include "prism/pack.h" - -// We optionally support parsing String#pack templates. For systems that don't -// want or need this functionality, it can be turned off with the -// PRISM_EXCLUDE_PACK define. -#ifdef PRISM_EXCLUDE_PACK - -void pm_pack_parse(void) {} - -#else - -#include -#include - -static uintmax_t -strtoumaxc(const char **format) { - uintmax_t value = 0; - while (**format >= '0' && **format <= '9') { - if (value > UINTMAX_MAX / 10) { - errno = ERANGE; - } - value = value * 10 + ((uintmax_t) (**format - '0')); - (*format)++; - } - return value; -} - -PRISM_EXPORTED_FUNCTION pm_pack_result -pm_pack_parse( - pm_pack_variant variant, - const char **format, - const char *format_end, - pm_pack_type *type, - pm_pack_signed *signed_type, - pm_pack_endian *endian, - pm_pack_size *size, - pm_pack_length_type *length_type, - uint64_t *length, - pm_pack_encoding *encoding -) { - if (*encoding == PM_PACK_ENCODING_START) { - *encoding = PM_PACK_ENCODING_US_ASCII; - } - - if (*format == format_end) { - *type = PM_PACK_END; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - *length_type = PM_PACK_LENGTH_NA; - return PM_PACK_OK; - } - - *length_type = PM_PACK_LENGTH_FIXED; - *length = 1; - bool length_changed_allowed = true; - - char directive = **format; - (*format)++; - switch (directive) { - case ' ': - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - *type = PM_PACK_SPACE; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - *length_type = PM_PACK_LENGTH_NA; - *length = 0; - return PM_PACK_OK; - case '#': - while ((*format < format_end) && (**format != '\n')) { - (*format)++; - } - *type = PM_PACK_COMMENT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - *length_type = PM_PACK_LENGTH_NA; - *length = 0; - return PM_PACK_OK; - case 'C': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_AGNOSTIC_ENDIAN; - *size = PM_PACK_SIZE_8; - break; - case 'S': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_16; - break; - case 'L': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'Q': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'J': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_P; - break; - case 'c': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_AGNOSTIC_ENDIAN; - *size = PM_PACK_SIZE_8; - break; - case 's': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_16; - break; - case 'l': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'q': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'j': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_P; - break; - case 'I': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_INT; - break; - case 'i': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_SIGNED; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_INT; - break; - case 'n': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_16; - length_changed_allowed = false; - break; - case 'N': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_32; - length_changed_allowed = false; - break; - case 'v': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_16; - length_changed_allowed = false; - break; - case 'V': - *type = PM_PACK_INTEGER; - *signed_type = PM_PACK_UNSIGNED; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_32; - length_changed_allowed = false; - break; - case 'U': - *type = PM_PACK_UTF8; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'w': - *type = PM_PACK_BER; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'D': - case 'd': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'F': - case 'f': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_NATIVE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'E': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'e': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_LITTLE_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'G': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_64; - break; - case 'g': - *type = PM_PACK_FLOAT; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_BIG_ENDIAN; - *size = PM_PACK_SIZE_32; - break; - case 'A': - *type = PM_PACK_STRING_SPACE_PADDED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'a': - *type = PM_PACK_STRING_NULL_PADDED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'Z': - *type = PM_PACK_STRING_NULL_TERMINATED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'B': - *type = PM_PACK_STRING_MSB; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'b': - *type = PM_PACK_STRING_LSB; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'H': - *type = PM_PACK_STRING_HEX_HIGH; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'h': - *type = PM_PACK_STRING_HEX_LOW; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'u': - *type = PM_PACK_STRING_UU; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'M': - *type = PM_PACK_STRING_MIME; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'm': - *type = PM_PACK_STRING_BASE64; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'P': - *type = PM_PACK_STRING_FIXED; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'p': - *type = PM_PACK_STRING_POINTER; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case '@': - *type = PM_PACK_MOVE; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'X': - *type = PM_PACK_BACK; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case 'x': - *type = PM_PACK_NULL; - *signed_type = PM_PACK_SIGNED_NA; - *endian = PM_PACK_ENDIAN_NA; - *size = PM_PACK_SIZE_NA; - break; - case '%': - return PM_PACK_ERROR_UNSUPPORTED_DIRECTIVE; - default: - return PM_PACK_ERROR_UNKNOWN_DIRECTIVE; - } - - bool explicit_endian = false; - - while (*format < format_end) { - switch (**format) { - case '_': - case '!': - (*format)++; - if (*type != PM_PACK_INTEGER || !length_changed_allowed) { - return PM_PACK_ERROR_BANG_NOT_ALLOWED; - } - switch (*size) { - case PM_PACK_SIZE_SHORT: - case PM_PACK_SIZE_INT: - case PM_PACK_SIZE_LONG: - case PM_PACK_SIZE_LONG_LONG: - break; - case PM_PACK_SIZE_16: - *size = PM_PACK_SIZE_SHORT; - break; - case PM_PACK_SIZE_32: - *size = PM_PACK_SIZE_LONG; - break; - case PM_PACK_SIZE_64: - *size = PM_PACK_SIZE_LONG_LONG; - break; - case PM_PACK_SIZE_P: - break; - default: - return PM_PACK_ERROR_BANG_NOT_ALLOWED; - } - break; - case '<': - (*format)++; - if (explicit_endian) { - return PM_PACK_ERROR_DOUBLE_ENDIAN; - } - *endian = PM_PACK_LITTLE_ENDIAN; - explicit_endian = true; - break; - case '>': - (*format)++; - if (explicit_endian) { - return PM_PACK_ERROR_DOUBLE_ENDIAN; - } - *endian = PM_PACK_BIG_ENDIAN; - explicit_endian = true; - break; - default: - goto exit_modifier_loop; - } - } - -exit_modifier_loop: - - if (variant == PM_PACK_VARIANT_UNPACK && *type == PM_PACK_MOVE) { - *length = 0; - } - - if (*format < format_end) { - if (**format == '*') { - switch (*type) { - case PM_PACK_NULL: - case PM_PACK_BACK: - switch (variant) { - case PM_PACK_VARIANT_PACK: - *length_type = PM_PACK_LENGTH_FIXED; - break; - case PM_PACK_VARIANT_UNPACK: - *length_type = PM_PACK_LENGTH_MAX; - break; - } - *length = 0; - break; - - case PM_PACK_MOVE: - switch (variant) { - case PM_PACK_VARIANT_PACK: - *length_type = PM_PACK_LENGTH_FIXED; - break; - case PM_PACK_VARIANT_UNPACK: - *length_type = PM_PACK_LENGTH_RELATIVE; - break; - } - *length = 0; - break; - - case PM_PACK_STRING_UU: - *length_type = PM_PACK_LENGTH_FIXED; - *length = 0; - break; - - case PM_PACK_STRING_FIXED: - switch (variant) { - case PM_PACK_VARIANT_PACK: - *length_type = PM_PACK_LENGTH_FIXED; - *length = 1; - break; - case PM_PACK_VARIANT_UNPACK: - *length_type = PM_PACK_LENGTH_MAX; - *length = 0; - break; - } - break; - - case PM_PACK_STRING_MIME: - case PM_PACK_STRING_BASE64: - *length_type = PM_PACK_LENGTH_FIXED; - *length = 1; - break; - - default: - *length_type = PM_PACK_LENGTH_MAX; - *length = 0; - break; - } - - (*format)++; - } else if (**format >= '0' && **format <= '9') { - errno = 0; - *length_type = PM_PACK_LENGTH_FIXED; - #if UINTMAX_MAX < UINT64_MAX - #error "prism's design assumes uintmax_t is at least as large as uint64_t" - #endif - uintmax_t length_max = strtoumaxc(format); - if (errno || length_max > UINT64_MAX) { - return PM_PACK_ERROR_LENGTH_TOO_BIG; - } - *length = (uint64_t) length_max; - } - } - - switch (*type) { - case PM_PACK_UTF8: - /* if encoding is US-ASCII, upgrade to UTF-8 */ - if (*encoding == PM_PACK_ENCODING_US_ASCII) { - *encoding = PM_PACK_ENCODING_UTF_8; - } - break; - case PM_PACK_STRING_MIME: - case PM_PACK_STRING_BASE64: - case PM_PACK_STRING_UU: - /* keep US-ASCII (do nothing) */ - break; - default: - /* fall back to BINARY */ - *encoding = PM_PACK_ENCODING_ASCII_8BIT; - break; - } - - return PM_PACK_OK; -} - -PRISM_EXPORTED_FUNCTION size_t -pm_size_to_native(pm_pack_size size) { - switch (size) { - case PM_PACK_SIZE_SHORT: - return sizeof(short); - case PM_PACK_SIZE_INT: - return sizeof(int); - case PM_PACK_SIZE_LONG: - return sizeof(long); - case PM_PACK_SIZE_LONG_LONG: - return sizeof(long long); - case PM_PACK_SIZE_8: - return 1; - case PM_PACK_SIZE_16: - return 2; - case PM_PACK_SIZE_32: - return 4; - case PM_PACK_SIZE_64: - return 8; - case PM_PACK_SIZE_P: - return sizeof(void *); - default: - return 0; - } -} - -#endif From 2ffb629d4ea771e54e22a6a520af936f25daaef0 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 12 Feb 2026 09:23:13 +0100 Subject: [PATCH 013/289] Run ruby_parser versions for ruby 3.3 It will not support newer ruby versions: https://github.com/seattlerb/ruby_parser?tab=readme-ov-file#notice This way we don't have to exclude new syntax. --- test/prism/ruby/ruby_parser_test.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/test/prism/ruby/ruby_parser_test.rb b/test/prism/ruby/ruby_parser_test.rb index 6e4ba8ce16..25107978f3 100644 --- a/test/prism/ruby/ruby_parser_test.rb +++ b/test/prism/ruby/ruby_parser_test.rb @@ -85,16 +85,11 @@ class RubyParserTest < TestCase "3.3-4.0/void_value.txt", - "3.4/circular_parameters.txt", - - "4.0/endless_methods_command_call.txt", - "4.0/leading_logical.txt", - # https://bugs.ruby-lang.org/issues/21168#note-5 "command_method_call_2.txt", ] - Fixture.each(except: failures) do |fixture| + Fixture.each_for_version(version: "3.3", except: failures) do |fixture| define_method(fixture.test_name) do assert_ruby_parser(fixture, todos.include?(fixture.path)) end From 8f35e8ef255bc045567d959156d54971dc21dcb5 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 11 Feb 2026 13:03:49 +0100 Subject: [PATCH 014/289] Fix lexing for unterminated strings/heredocs etc. When we hit EOF and still have lex modes left, it means some content was unterminated. Heredocs specifically have logic that needs to happen when the body finished lexing. If we don't reset the mode back to how it was before, it will not continue lexing at the correct place. --- src/prism.c | 9 ++++ .../unterminated_heredoc_and_embexpr.txt | 11 ++++ .../unterminated_heredoc_and_embexpr_2.txt | 9 ++++ test/prism/lex_test.rb | 53 +++++++++++++++++-- 4 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 test/prism/errors/unterminated_heredoc_and_embexpr.txt create mode 100644 test/prism/errors/unterminated_heredoc_and_embexpr_2.txt diff --git a/src/prism.c b/src/prism.c index 34e5d38b0a..097b4c7305 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9856,6 +9856,15 @@ parser_lex(pm_parser_t *parser) { // We'll check if we're at the end of the file. If we are, then we // need to return the EOF token. if (parser->current.end >= parser->end) { + // We may be missing closing tokens. We should pop modes one by one + // to do the appropriate cleanup like moving next_start for heredocs. + // Only when no mode is remaining will we actually emit the EOF token. + if (parser->lex_modes.current->mode != PM_LEX_DEFAULT) { + lex_mode_pop(parser); + parser_lex(parser); + return; + } + // If we hit EOF, but the EOF came immediately after a newline, // set the start of the token to the newline. This way any EOF // errors will be reported as happening on that line rather than diff --git a/test/prism/errors/unterminated_heredoc_and_embexpr.txt b/test/prism/errors/unterminated_heredoc_and_embexpr.txt new file mode 100644 index 0000000000..bed7fcd24e --- /dev/null +++ b/test/prism/errors/unterminated_heredoc_and_embexpr.txt @@ -0,0 +1,11 @@ +<= "3.3" - def test_lex_compare - prism = Prism.lex_compat(File.read(__FILE__), version: "current").value - ripper = Ripper.lex(File.read(__FILE__)) + def test_lex_compat + source = "foo bar" + prism = Prism.lex_compat(source, version: "current").value + ripper = Ripper.lex(source) assert_equal(ripper, prism) end end + + def test_lex_interpolation_unterminated + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN EOF], + token_types('"#{') + ) + + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN IGNORED_NEWLINE EOF], + token_types('"#{' + "\n") + ) + end + + def test_lex_interpolation_unterminated_with_content + # FIXME: Emits EOL twice. + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT EOF EOF], + token_types('"#{C') + ) + + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT NEWLINE EOF], + token_types('"#{C' + "\n") + ) + end + + def test_lex_heredoc_unterminated + code = <<~'RUBY'.strip + < Date: Wed, 11 Feb 2026 17:01:06 +0100 Subject: [PATCH 015/289] Skip missing heredoc end in ripper translator Prism inserts these to make bookkeeping easier. Ripper does not do so. --- lib/prism/lex_compat.rb | 9 ++++++--- test/prism/ruby/ripper_test.rb | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index e8d2ce1b19..3d5cbfcddc 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -768,21 +768,24 @@ def result source.byte_offset(line, column) end - # Add :on_sp tokens - tokens = insert_on_sp(tokens, source, result.data_loc, bom, eof_token) + tokens = post_process_tokens(tokens, source, result.data_loc, bom, eof_token) Result.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, source) end private - def insert_on_sp(tokens, source, data_loc, bom, eof_token) + def post_process_tokens(tokens, source, data_loc, bom, eof_token) new_tokens = [] prev_token_state = Translation::Ripper::Lexer::State[Translation::Ripper::EXPR_BEG] prev_token_end = bom ? 3 : 0 tokens.each do |token| + # Skip missing heredoc ends. + next if token[1] == :on_heredoc_end && token[2] == "" + + # Add :on_sp tokens. line, column = token[0] start_offset = source.byte_offset(line, column) diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index 15f535f3d6..39cb9395ab 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -81,6 +81,16 @@ class RipperTest < TestCase define_method("#{fixture.test_name}_lex") { assert_ripper_lex(fixture.read) } end + def test_lex_ignored_missing_heredoc_end + ["", "-", "~"].each do |type| + source = "<<#{type}FOO\n" + assert_ripper_lex(source) + + source = "<<#{type}'FOO'\n" + assert_ripper_lex(source) + end + end + module Events attr_reader :events From ed48f6dbfbb6b7447ed369224198ddc4cabf422f Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:40:54 +0100 Subject: [PATCH 016/289] Revert "Fix lexing for unterminated strings/heredocs etc." This reverts commit 8f35e8ef255bc045567d959156d54971dc21dcb5. --- src/prism.c | 9 ---- .../unterminated_heredoc_and_embexpr.txt | 11 ---- .../unterminated_heredoc_and_embexpr_2.txt | 9 ---- test/prism/lex_test.rb | 53 ++----------------- 4 files changed, 3 insertions(+), 79 deletions(-) delete mode 100644 test/prism/errors/unterminated_heredoc_and_embexpr.txt delete mode 100644 test/prism/errors/unterminated_heredoc_and_embexpr_2.txt diff --git a/src/prism.c b/src/prism.c index 097b4c7305..34e5d38b0a 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9856,15 +9856,6 @@ parser_lex(pm_parser_t *parser) { // We'll check if we're at the end of the file. If we are, then we // need to return the EOF token. if (parser->current.end >= parser->end) { - // We may be missing closing tokens. We should pop modes one by one - // to do the appropriate cleanup like moving next_start for heredocs. - // Only when no mode is remaining will we actually emit the EOF token. - if (parser->lex_modes.current->mode != PM_LEX_DEFAULT) { - lex_mode_pop(parser); - parser_lex(parser); - return; - } - // If we hit EOF, but the EOF came immediately after a newline, // set the start of the token to the newline. This way any EOF // errors will be reported as happening on that line rather than diff --git a/test/prism/errors/unterminated_heredoc_and_embexpr.txt b/test/prism/errors/unterminated_heredoc_and_embexpr.txt deleted file mode 100644 index bed7fcd24e..0000000000 --- a/test/prism/errors/unterminated_heredoc_and_embexpr.txt +++ /dev/null @@ -1,11 +0,0 @@ -<= "3.3" - def test_lex_compat - source = "foo bar" - prism = Prism.lex_compat(source, version: "current").value - ripper = Ripper.lex(source) + def test_lex_compare + prism = Prism.lex_compat(File.read(__FILE__), version: "current").value + ripper = Ripper.lex(File.read(__FILE__)) assert_equal(ripper, prism) end end - - def test_lex_interpolation_unterminated - assert_equal( - %i[STRING_BEGIN EMBEXPR_BEGIN EOF], - token_types('"#{') - ) - - assert_equal( - %i[STRING_BEGIN EMBEXPR_BEGIN IGNORED_NEWLINE EOF], - token_types('"#{' + "\n") - ) - end - - def test_lex_interpolation_unterminated_with_content - # FIXME: Emits EOL twice. - assert_equal( - %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT EOF EOF], - token_types('"#{C') - ) - - assert_equal( - %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT NEWLINE EOF], - token_types('"#{C' + "\n") - ) - end - - def test_lex_heredoc_unterminated - code = <<~'RUBY'.strip - < Date: Thu, 12 Feb 2026 18:53:12 +0100 Subject: [PATCH 017/289] Reverse-sync https://github.com/ruby/ruby/commit/dca8d9a6aa9c590a5707959d2c211a8273f7bc06 To correctly handle rdoc coverage in ruby/ruby --- templates/template.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/template.rb b/templates/template.rb index 0c695fade5..28ac475cdf 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -6,7 +6,7 @@ require "yaml" module Prism - module Template + module Template # :nodoc: all SERIALIZE_ONLY_SEMANTICS_FIELDS = ENV.fetch("PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS", false) REMOVE_ON_ERROR_TYPES = SERIALIZE_ONLY_SEMANTICS_FIELDS CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false) From 27c24fdc0d8c9d14f819f83050d573315e8474ee Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Fri, 13 Feb 2026 10:49:25 +0100 Subject: [PATCH 018/289] Fix lexing for unterminated strings/heredocs etc. When we hit EOF and still have lex modes left, it means some content was unterminated. Heredocs specifically have logic that needs to happen when the body finished lexing. If we don't reset the mode back to how it was before, it will not continue lexing at the correct place. Followup to https://github.com/ruby/prism/pull/3918. We can't call into `parser_lex` since it resets token locations. --- src/prism.c | 16 +++++- .../unterminated_heredoc_and_embexpr.txt | 11 ++++ .../unterminated_heredoc_and_embexpr_2.txt | 9 ++++ test/prism/errors_test.rb | 22 ++++++++ test/prism/lex_test.rb | 53 +++++++++++++++++-- 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 test/prism/errors/unterminated_heredoc_and_embexpr.txt create mode 100644 test/prism/errors/unterminated_heredoc_and_embexpr_2.txt diff --git a/src/prism.c b/src/prism.c index 34e5d38b0a..ca0f2a55aa 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9783,6 +9783,12 @@ parser_lex(pm_parser_t *parser) { unsigned int semantic_token_seen = parser->semantic_token_seen; parser->semantic_token_seen = true; + // We'll jump to this label when we are about to encounter an EOF. + // If we still have lex_modes on the stack, we pop them so that cleanup + // can happen. For example, we should still continue parsing after a heredoc + // identifier, even if the heredoc body was syntax invalid. + switch_lex_modes: + switch (parser->lex_modes.current->mode) { case PM_LEX_DEFAULT: case PM_LEX_EMBEXPR: @@ -9856,6 +9862,14 @@ parser_lex(pm_parser_t *parser) { // We'll check if we're at the end of the file. If we are, then we // need to return the EOF token. if (parser->current.end >= parser->end) { + // We may be missing closing tokens. We should pop modes one by one + // to do the appropriate cleanup like moving next_start for heredocs. + // Only when no mode is remaining will we actually emit the EOF token. + if (parser->lex_modes.current->mode != PM_LEX_DEFAULT) { + lex_mode_pop(parser); + goto switch_lex_modes; + } + // If we hit EOF, but the EOF came immediately after a newline, // set the start of the token to the newline. This way any EOF // errors will be reported as happening on that line rather than @@ -15433,7 +15447,7 @@ parse_string_part(pm_parser_t *parser, uint16_t depth) { pm_token_t opening = parser->previous; pm_statements_node_t *statements = NULL; - if (!match1(parser, PM_TOKEN_EMBEXPR_END)) { + if (!match3(parser, PM_TOKEN_EMBEXPR_END, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) { pm_accepts_block_stack_push(parser, true); statements = parse_statements(parser, PM_CONTEXT_EMBEXPR, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); diff --git a/test/prism/errors/unterminated_heredoc_and_embexpr.txt b/test/prism/errors/unterminated_heredoc_and_embexpr.txt new file mode 100644 index 0000000000..bed7fcd24e --- /dev/null +++ b/test/prism/errors/unterminated_heredoc_and_embexpr.txt @@ -0,0 +1,11 @@ +<= "3.3" - def test_lex_compare - prism = Prism.lex_compat(File.read(__FILE__), version: "current").value - ripper = Ripper.lex(File.read(__FILE__)) + def test_lex_compat + source = "foo bar" + prism = Prism.lex_compat(source, version: "current").value + ripper = Ripper.lex(source) assert_equal(ripper, prism) end end + + def test_lex_interpolation_unterminated + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN EOF], + token_types('"#{') + ) + + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN IGNORED_NEWLINE EOF], + token_types('"#{' + "\n") + ) + end + + def test_lex_interpolation_unterminated_with_content + # FIXME: Emits EOL twice. + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT EOF EOF], + token_types('"#{C') + ) + + assert_equal( + %i[STRING_BEGIN EMBEXPR_BEGIN CONSTANT NEWLINE EOF], + token_types('"#{C' + "\n") + ) + end + + def test_lex_heredoc_unterminated + code = <<~'RUBY'.strip + < Date: Mon, 16 Feb 2026 08:42:50 +0100 Subject: [PATCH 019/289] Reverse-sync `&nil` block handling https://github.com/ruby/ruby/pull/11065 https://bugs.ruby-lang.org/issues/19979 Co-authored-by: Ufuk Kayserilioglu --- config.yml | 16 +++++- lib/prism/node_ext.rb | 8 ++- src/prism.c | 55 ++++++++++++++------ test/prism/result/source_location_test.rb | 4 ++ test/prism/ruby/parameters_signature_test.rb | 4 ++ 5 files changed, 70 insertions(+), 17 deletions(-) diff --git a/config.yml b/config.yml index f6e99c66b1..0736f5a0bf 100644 --- a/config.yml +++ b/config.yml @@ -3920,6 +3920,18 @@ nodes: nil ^^^ + - name: NoBlockParameterNode + fields: + - name: operator_loc + type: location + - name: keyword_loc + type: location + comment: | + Represents the use of `&nil` inside method arguments. + + def a(&nil) + ^^^^ + end - name: NoKeywordsParameterNode fields: - name: operator_loc @@ -4066,7 +4078,9 @@ nodes: - NoKeywordsParameterNode - name: block type: node? - kind: BlockParameterNode + kind: + - BlockParameterNode + - NoBlockParameterNode comment: | Represents the list of parameters on a method, block, or lambda definition. diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 469e54ca0c..1bb3ebcf5f 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -316,7 +316,13 @@ def signature names << [:nokey] end - names << [:block, block.name || :&] if block + case block + when BlockParameterNode + names << [:block, block.name || :&] + when NoBlockParameterNode + names << [:noblock] + end + names end end diff --git a/src/prism.c b/src/prism.c index ca0f2a55aa..81768024f2 100644 --- a/src/prism.c +++ b/src/prism.c @@ -5558,6 +5558,24 @@ pm_nil_node_create(pm_parser_t *parser, const pm_token_t *token) { return node; } +/** + * Allocate and initialize a new NoKeywordsParameterNode node. + */ +static pm_no_block_parameter_node_t * +pm_no_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) { + assert(operator->type == PM_TOKEN_AMPERSAND || operator->type == PM_TOKEN_UAMPERSAND); + assert(keyword->type == PM_TOKEN_KEYWORD_NIL); + pm_no_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_block_parameter_node_t); + + *node = (pm_no_block_parameter_node_t) { + .base = PM_NODE_INIT(parser, PM_NO_BLOCK_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, keyword)), + .operator_loc = TOK2LOC(parser, operator), + .keyword_loc = TOK2LOC(parser, keyword) + }; + + return node; +} + /** * Allocate and initialize a new NoKeywordsParameterNode node. */ @@ -5787,9 +5805,9 @@ pm_parameters_node_keyword_rest_set(pm_parameters_node_t *params, pm_node_t *par * Set the block parameter on a ParametersNode node. */ static void -pm_parameters_node_block_set(pm_parameters_node_t *params, pm_block_parameter_node_t *param) { +pm_parameters_node_block_set(pm_parameters_node_t *params, pm_node_t *param) { assert(params->block == NULL); - pm_parameters_node_location_set(params, UP(param)); + pm_parameters_node_location_set(params, param); params->block = param; } @@ -13929,26 +13947,33 @@ parse_parameters( parser_lex(parser); pm_token_t operator = parser->previous; - pm_token_t name = { 0 }; + pm_node_t *param; - bool repeated = false; - if (accept1(parser, PM_TOKEN_IDENTIFIER)) { - name = parser->previous; - repeated = pm_parser_parameter_name_check(parser, &name); - pm_parser_local_add_token(parser, &name, 1); + if (accept1(parser, PM_TOKEN_KEYWORD_NIL)) { + param = (pm_node_t *) pm_no_block_parameter_node_create(parser, &operator, &parser->previous); } else { - parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_BLOCK; - } + pm_token_t name = {0}; - pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, NTOK2PTR(name), &operator); - if (repeated) { - pm_node_flag_set_repeated_parameter(UP(param)); + bool repeated = false; + if (accept1(parser, PM_TOKEN_IDENTIFIER)) { + name = parser->previous; + repeated = pm_parser_parameter_name_check(parser, &name); + pm_parser_local_add_token(parser, &name, 1); + } else { + parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_BLOCK; + } + + param = (pm_node_t *) pm_block_parameter_node_create(parser, NTOK2PTR(name), &operator); + if (repeated) { + pm_node_flag_set_repeated_parameter(param); + } } + if (params->block == NULL) { pm_parameters_node_block_set(params, param); } else { - pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_BLOCK_MULTI); - pm_parameters_node_posts_append(params, UP(param)); + pm_parser_err_node(parser, param, PM_ERR_PARAMETER_BLOCK_MULTI); + pm_parameters_node_posts_append(params, param); } break; diff --git a/test/prism/result/source_location_test.rb b/test/prism/result/source_location_test.rb index 993150f581..dbda848211 100644 --- a/test/prism/result/source_location_test.rb +++ b/test/prism/result/source_location_test.rb @@ -650,6 +650,10 @@ def test_NilNode assert_location(NilNode, "nil") end + def test_NoBlockParameterNode + assert_location(NoBlockParameterNode, "def foo(&nil); end", 8...12) { |node| node.parameters.block } + end + def test_NoKeywordsParameterNode assert_location(NoKeywordsParameterNode, "def foo(**nil); end", 8...13) { |node| node.parameters.keyword_rest } end diff --git a/test/prism/ruby/parameters_signature_test.rb b/test/prism/ruby/parameters_signature_test.rb index ea1eea106b..8ca4c565ac 100644 --- a/test/prism/ruby/parameters_signature_test.rb +++ b/test/prism/ruby/parameters_signature_test.rb @@ -50,6 +50,10 @@ def test_nokey assert_parameters([[:nokey]], "**nil") end + def test_noblock + assert_parameters([[:noblock]], "&nil") + end + def test_keyrest_anonymous assert_parameters([[:keyrest, :**]], "**") end From 8aad2480abe7a8ea63a7f9b2e0a91f48ed3a1431 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 16 Feb 2026 09:03:43 +0100 Subject: [PATCH 020/289] Only compare &nil syntax on rubies that support it --- test/prism/ruby/parameters_signature_test.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/prism/ruby/parameters_signature_test.rb b/test/prism/ruby/parameters_signature_test.rb index 8ca4c565ac..5a225862c3 100644 --- a/test/prism/ruby/parameters_signature_test.rb +++ b/test/prism/ruby/parameters_signature_test.rb @@ -51,7 +51,8 @@ def test_nokey end def test_noblock - assert_parameters([[:noblock]], "&nil") + # FIXME: `compare: RUBY_VERSION >= "4.1"` once builds are available + assert_parameters([[:noblock]], "&nil", compare: false) end def test_keyrest_anonymous @@ -78,10 +79,11 @@ def test_forwarding private - def assert_parameters(expected, source) + def assert_parameters(expected, source, compare: true) # Compare against our expectation. assert_equal(expected, signature(source)) + return unless compare # Compare against Ruby's expectation. object = Object.new eval("def object.m(#{source}); end") From 4ee9b1b65115a62c8b4bd5681c4e4695cd382ff5 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:43:10 +0100 Subject: [PATCH 021/289] Fix C extension docs in ruby/ruby Because ruby/ruby doesn't use our rake task it also uses the default markup (rdoc), unless specified otherwise. github.com/ruby/prism/pull/3572 already added it explicitly to ruby files. For C however, it is not so easy because of a rdoc bug: https://github.com/ruby/rdoc/issues/1597 Adding the comment would remove all documentation since it gets parsed as ruby. So, specify it for each method individually. Remove it from the template since there is only one C file relevant for rdoc. --- ext/prism/extension.c | 20 ++++++++++++++++++++ rakelib/rdoc.rake | 1 - templates/template.rb | 2 -- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 7a5dd8a984..e9e9f2ec2c 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -389,6 +389,7 @@ dump_input(pm_string_t *input, const pm_options_t *options) { } /** + * :markup: markdown * call-seq: * dump(source, **options) -> String * @@ -422,6 +423,7 @@ dump(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * dump_file(filepath, **options) -> String * @@ -794,6 +796,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod } /** + * :markup: markdown * call-seq: * lex(source, **options) -> LexResult * @@ -814,6 +817,7 @@ lex(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * lex_file(filepath, **options) -> LexResult * @@ -865,6 +869,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) { } /** + * :markup: markdown * call-seq: * parse(source, **options) -> ParseResult * @@ -933,6 +938,7 @@ parse(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * parse_file(filepath, **options) -> ParseResult * @@ -968,6 +974,7 @@ profile_input(pm_string_t *input, const pm_options_t *options) { } /** + * :markup: markdown * call-seq: * profile(source, **options) -> nil * @@ -989,6 +996,7 @@ profile(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * profile_file(filepath, **options) -> nil * @@ -1041,6 +1049,7 @@ parse_stream_fgets(char *string, int size, void *stream) { } /** + * :markup: markdown * call-seq: * parse_stream(stream, **options) -> ParseResult * @@ -1094,6 +1103,7 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { } /** + * :markup: markdown * call-seq: * parse_comments(source, **options) -> Array * @@ -1114,6 +1124,7 @@ parse_comments(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * parse_file_comments(filepath, **options) -> Array * @@ -1136,6 +1147,7 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * parse_lex(source, **options) -> ParseLexResult * @@ -1163,6 +1175,7 @@ parse_lex(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * parse_lex_file(filepath, **options) -> ParseLexResult * @@ -1209,6 +1222,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { } /** + * :markup: markdown * call-seq: * parse_success?(source, **options) -> bool * @@ -1229,6 +1243,7 @@ parse_success_p(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * parse_failure?(source, **options) -> bool * @@ -1241,6 +1256,7 @@ parse_failure_p(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * parse_file_success?(filepath, **options) -> bool * @@ -1263,6 +1279,7 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) { } /** + * :markup: markdown * call-seq: * parse_file_failure?(filepath, **options) -> bool * @@ -1297,6 +1314,7 @@ string_query(pm_string_query_t result) { } /** + * :markup: markdown * call-seq: * local?(string) -> bool * @@ -1311,6 +1329,7 @@ string_query_local_p(VALUE self, VALUE string) { } /** + * :markup: markdown * call-seq: * constant?(string) -> bool * @@ -1325,6 +1344,7 @@ string_query_constant_p(VALUE self, VALUE string) { } /** + * :markup: markdown * call-seq: * method_name?(string) -> bool * diff --git a/rakelib/rdoc.rake b/rakelib/rdoc.rake index 5bba3e3cd5..deb98b0730 100644 --- a/rakelib/rdoc.rake +++ b/rakelib/rdoc.rake @@ -9,7 +9,6 @@ end RDoc::Task.new(:rdoc) do |rdoc| rdoc.main = "README.md" - rdoc.markup = "markdown" rdoc.rdoc_dir = "doc/rb" rdoc.options.push("--all", "-x", "lib/prism/translation/ripper/shim.rb") diff --git a/templates/template.rb b/templates/template.rb index 28ac475cdf..65e6ed0381 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -660,8 +660,6 @@ def render(name, write_to: nil) HEADING else <<~HEADING - /* :markup: markdown */ - /*----------------------------------------------------------------------------*/ /* This file is generated by the templates/template.rb script and should not */ /* be modified manually. See */ From edd4212600a77275252ed0d514dd1320d41d0822 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 17:44:06 +0000 Subject: [PATCH 022/289] Bump the java-deps group in /java-wasm with 2 updates Bumps the java-deps group in /java-wasm with 2 updates: [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit-framework) and [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin). Updates `org.junit.jupiter:junit-jupiter-engine` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r6.0.2...r6.0.3) Updates `org.apache.maven.plugins:maven-compiler-plugin` from 3.14.1 to 3.15.0 - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.14.1...maven-compiler-plugin-3.15.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-engine dependency-version: 6.0.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: java-deps - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.15.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: java-deps ... Signed-off-by: dependabot[bot] --- java-wasm/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index f69028bfd8..d8a360d57b 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -16,7 +16,7 @@ 11 1.6.1 - 6.0.2 + 6.0.3 @@ -79,7 +79,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.14.1 + 3.15.0 11 From fb88c72dce6fa7b244eab9052a6e103f68d09ec5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 16 Feb 2026 11:00:47 -0500 Subject: [PATCH 023/289] Only accept noblock in Ruby 4.1+ --- bin/prism | 1 - snapshots/4.1/noblock.txt | 61 +++++++++++++++++++++++++++ src/prism.c | 2 +- test/prism/errors/3.3-4.0/noblock.txt | 6 +++ test/prism/fixtures/4.1/noblock.txt | 4 ++ test/prism/locals_test.rb | 4 +- test/prism/ruby/ripper_test.rb | 3 ++ 7 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 snapshots/4.1/noblock.txt create mode 100644 test/prism/errors/3.3-4.0/noblock.txt create mode 100644 test/prism/fixtures/4.1/noblock.txt diff --git a/bin/prism b/bin/prism index dbd0ddb174..ddf06a6d2a 100755 --- a/bin/prism +++ b/bin/prism @@ -166,7 +166,6 @@ module Prism source, filepath = read_source(argv) result = Prism.parse(source) - if result.errors.any? puts result.errors_format else diff --git a/snapshots/4.1/noblock.txt b/snapshots/4.1/noblock.txt new file mode 100644 index 0000000000..ce2827c24f --- /dev/null +++ b/snapshots/4.1/noblock.txt @@ -0,0 +1,61 @@ +@ ProgramNode (location: (1,0)-(4,12)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(4,12)) + ├── flags: ∅ + └── body: (length: 2) + ├── @ DefNode (location: (1,0)-(2,3)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (1,4)-(1,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (1,8)-(1,12)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: + │ │ @ NoBlockParameterNode (location: (1,8)-(1,12)) + │ │ ├── flags: ∅ + │ │ ├── operator_loc: (1,8)-(1,9) = "&" + │ │ └── keyword_loc: (1,9)-(1,12) = "nil" + │ ├── body: ∅ + │ ├── locals: [] + │ ├── def_keyword_loc: (1,0)-(1,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (1,7)-(1,8) = "(" + │ ├── rparen_loc: (1,12)-(1,13) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (2,0)-(2,3) = "end" + └── @ LambdaNode (location: (4,0)-(4,12)) + ├── flags: newline + ├── locals: [] + ├── operator_loc: (4,0)-(4,2) = "->" + ├── opening_loc: (4,10)-(4,11) = "{" + ├── closing_loc: (4,11)-(4,12) = "}" + ├── parameters: + │ @ BlockParametersNode (location: (4,3)-(4,9)) + │ ├── flags: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (4,4)-(4,8)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: + │ │ @ NoBlockParameterNode (location: (4,4)-(4,8)) + │ │ ├── flags: ∅ + │ │ ├── operator_loc: (4,4)-(4,5) = "&" + │ │ └── keyword_loc: (4,5)-(4,8) = "nil" + │ ├── locals: (length: 0) + │ ├── opening_loc: (4,3)-(4,4) = "(" + │ └── closing_loc: (4,8)-(4,9) = ")" + └── body: ∅ diff --git a/src/prism.c b/src/prism.c index 81768024f2..56cb9e3fb3 100644 --- a/src/prism.c +++ b/src/prism.c @@ -13949,7 +13949,7 @@ parse_parameters( pm_token_t operator = parser->previous; pm_node_t *param; - if (accept1(parser, PM_TOKEN_KEYWORD_NIL)) { + if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_1 && accept1(parser, PM_TOKEN_KEYWORD_NIL)) { param = (pm_node_t *) pm_no_block_parameter_node_create(parser, &operator, &parser->previous); } else { pm_token_t name = {0}; diff --git a/test/prism/errors/3.3-4.0/noblock.txt b/test/prism/errors/3.3-4.0/noblock.txt new file mode 100644 index 0000000000..07939041bb --- /dev/null +++ b/test/prism/errors/3.3-4.0/noblock.txt @@ -0,0 +1,6 @@ +def foo(&nil) + ^~~ unexpected 'nil'; expected a `)` to close the parameters + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it +end + diff --git a/test/prism/fixtures/4.1/noblock.txt b/test/prism/fixtures/4.1/noblock.txt new file mode 100644 index 0000000000..2395393e22 --- /dev/null +++ b/test/prism/fixtures/4.1/noblock.txt @@ -0,0 +1,4 @@ +def foo(&nil) +end + +-> (&nil) {} diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb index 4844901804..bcb964aff6 100644 --- a/test/prism/locals_test.rb +++ b/test/prism/locals_test.rb @@ -30,7 +30,7 @@ class LocalsTest < TestCase "command_method_call_2.txt", # https://bugs.ruby-lang.org/issues/21669 - "4.1/void_value.txt" + "4.1/void_value.txt", ] Fixture.each_for_current_ruby(except: except) do |fixture| @@ -207,7 +207,7 @@ def prism_locals(source) end end - if params.block + if params.block.is_a?(BlockParameterNode) sorted << (params.block.name || :&) end diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index 39cb9395ab..00cf470e0e 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -40,6 +40,9 @@ class RipperTest < TestCase # https://bugs.ruby-lang.org/issues/21669 incorrect << "4.1/void_value.txt" + # https://bugs.ruby-lang.org/issues/19979 + incorrect << "4.1/noblock.txt" + # Skip these tests that we haven't implemented yet. omitted_sexp_raw = [ "bom_leading_space.txt", From e5fb0e192b0f03f35d2d004b0387787a2b043525 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 16 Feb 2026 19:37:35 +0100 Subject: [PATCH 024/289] Add a test for multiple `&nil` blocks/mixing them --- config.yml | 3 +++ lib/prism/node_ext.rb | 4 +++- test/prism/errors/4.1/multiple_blocks.txt | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/prism/errors/4.1/multiple_blocks.txt diff --git a/config.yml b/config.yml index 0736f5a0bf..7527e01070 100644 --- a/config.yml +++ b/config.yml @@ -4065,6 +4065,9 @@ nodes: - on error: NoKeywordsParameterNode # On parsing error of `f(..., ...)`, the first forwarding parameter is moved here: - on error: ForwardingParameterNode + # On parsing error of `f(&nil, &foo)`/`f(&foo, &nil)`, the first forwarding parameter is moved here: + - on error: BlockParameterNode + - on error: NoBlockParameterNode - name: keywords type: node[] kind: diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 1bb3ebcf5f..a05123d1bb 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -286,7 +286,9 @@ def signature case param when MultiTargetNode names << [:req] - when NoKeywordsParameterNode, KeywordRestParameterNode, ForwardingParameterNode + when NoKeywordsParameterNode, KeywordRestParameterNode, + NoBlockParameterNode, BlockParameterNode, + ForwardingParameterNode # Invalid syntax, e.g. "def f(**nil, ...)" moves the NoKeywordsParameterNode to posts raise "Invalid syntax" else diff --git a/test/prism/errors/4.1/multiple_blocks.txt b/test/prism/errors/4.1/multiple_blocks.txt new file mode 100644 index 0000000000..7e8433cf82 --- /dev/null +++ b/test/prism/errors/4.1/multiple_blocks.txt @@ -0,0 +1,12 @@ +def foo(&nil, &nil); end + ^ unexpected parameter order + ^~~~ multiple block parameters; only one block is allowed + +def foo(&foo, &nil); end + ^ unexpected parameter order + ^~~~ multiple block parameters; only one block is allowed + +def foo(&nil, &foo); end + ^ unexpected parameter order + ^~~~ multiple block parameters; only one block is allowed + From 675f9c3be7e48eea9112df171cbb5c20dad6e185 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 16 Feb 2026 11:16:16 -0500 Subject: [PATCH 025/289] Parser support for no block parameter syntax --- bin/prism | 6 +++--- lib/prism/translation/parser/builder.rb | 12 ++++++++++-- lib/prism/translation/parser/compiler.rb | 6 ++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/bin/prism b/bin/prism index ddf06a6d2a..e3bb0a32d9 100755 --- a/bin/prism +++ b/bin/prism @@ -269,17 +269,17 @@ module Prism # bin/prism parser [source] def parser(argv) - require "parser/ruby34" + require "parser/current" source, filepath = read_source(argv) buffer = Parser::Source::Buffer.new(filepath, 1) buffer.source = source puts "Parser:" - parser_parse(Parser::Ruby34.new, buffer) + parser_parse(Parser::CurrentRuby.new, buffer) puts "Prism:" - parser_parse(Prism::Translation::Parser34.new, buffer) + parser_parse(Prism::Translation::ParserCurrent.new, buffer) end # bin/prism ripper [source] diff --git a/lib/prism/translation/parser/builder.rb b/lib/prism/translation/parser/builder.rb index 6b620c25bc..7fc3bba6b7 100644 --- a/lib/prism/translation/parser/builder.rb +++ b/lib/prism/translation/parser/builder.rb @@ -7,12 +7,14 @@ class Parser # A builder that knows how to convert more modern Ruby syntax # into whitequark/parser gem's syntax tree. class Builder < ::Parser::Builders::Default - # It represents the `it` block argument, which is not yet implemented in the Parser gem. + # It represents the `it` block argument, which is not yet implemented in + # the Parser gem. def itarg n(:itarg, [:it], nil) end - # The following three lines have been added to support the `it` block parameter syntax in the source code below. + # The following three lines have been added to support the `it` block + # parameter syntax in the source code below. # # if args.type == :itarg # block_type = :itblock @@ -56,6 +58,12 @@ def block(method_call, begin_t, args, body, end_t) method_call.loc.with_expression(join_exprs(method_call, block))) end end + + # def foo(&nil); end + # ^^^^ + def blocknilarg(amper_t, nil_t) + n0(:blocknilarg, arg_prefix_map(amper_t, nil_t)) + end end end end diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index 37951a1d40..21aa7796c3 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -1390,6 +1390,12 @@ def visit_nil_node(node) builder.nil(token(node.location)) end + # def foo(&nil); end + # ^^^^ + def visit_no_block_parameter_node(node) + builder.blocknilarg(token(node.operator_loc), token(node.keyword_loc)) + end + # def foo(**nil); end # ^^^^^ def visit_no_keywords_parameter_node(node) From 02e0dadcc9ac5adaccbf58033ca19bcd93d8e775 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sat, 31 Jan 2026 20:12:13 -0500 Subject: [PATCH 026/289] rename `pm_newline_list.h` --- include/prism/util/{pm_newline_list.h => pm_line_offset_list.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename include/prism/util/{pm_newline_list.h => pm_line_offset_list.h} (100%) diff --git a/include/prism/util/pm_newline_list.h b/include/prism/util/pm_line_offset_list.h similarity index 100% rename from include/prism/util/pm_newline_list.h rename to include/prism/util/pm_line_offset_list.h From 295047413b9008944eb4bfab265e2f7ab2fdbd69 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sat, 31 Jan 2026 20:15:02 -0500 Subject: [PATCH 027/289] `fd -e h -e c . |xargs perl -p -i -e s/pm_newline_list.h/pm_line_offset_list.h/` --- include/prism/parser.h | 2 +- include/prism/static_literals.h | 2 +- include/prism/util/pm_char.h | 2 +- include/prism/util/pm_line_offset_list.h | 2 +- prism.gemspec | 2 +- src/util/pm_newline_list.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index a8d840d3bf..3e748e4e7a 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -13,7 +13,7 @@ #include "prism/static_literals.h" #include "prism/util/pm_constant_pool.h" #include "prism/util/pm_list.h" -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" #include "prism/util/pm_string.h" #include diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index 0f8eb43bfa..f52440b6f1 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -8,7 +8,7 @@ #include "prism/defines.h" #include "prism/ast.h" -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" #include #include diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index b213e8edee..58dcc75272 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -7,7 +7,7 @@ #define PRISM_CHAR_H #include "prism/defines.h" -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" #include #include diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index dd3e625089..83f8ad4ead 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -1,5 +1,5 @@ /** - * @file pm_newline_list.h + * @file pm_line_offset_list.h * * A list of byte offsets of newlines in a string. * diff --git a/prism.gemspec b/prism.gemspec index c5c315fc8d..c8fb2e0a0d 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -61,7 +61,7 @@ Gem::Specification.new do |spec| "include/prism/util/pm_integer.h", "include/prism/util/pm_list.h", "include/prism/util/pm_memchr.h", - "include/prism/util/pm_newline_list.h", + "include/prism/util/pm_line_offset_list.h", "include/prism/util/pm_strncasecmp.h", "include/prism/util/pm_string.h", "include/prism/util/pm_strpbrk.h", diff --git a/src/util/pm_newline_list.c b/src/util/pm_newline_list.c index 89c294a6d7..099a74c5f3 100644 --- a/src/util/pm_newline_list.c +++ b/src/util/pm_newline_list.c @@ -1,4 +1,4 @@ -#include "prism/util/pm_newline_list.h" +#include "prism/util/pm_line_offset_list.h" /** * Initialize a new newline list with the given capacity. Returns true if the From a55dbf30065006d8207ccd2d913ff9173da013fc Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sat, 31 Jan 2026 20:17:06 -0500 Subject: [PATCH 028/289] fix include guards --- include/prism/util/pm_line_offset_list.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index 83f8ad4ead..d17c6fe51c 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -11,8 +11,8 @@ * end column on every node in addition to the offsets that we already store, * but that would be quite a lot of memory overhead. */ -#ifndef PRISM_NEWLINE_LIST_H -#define PRISM_NEWLINE_LIST_H +#ifndef PRISM_LINE_OFFSET_LIST_H +#define PRISM_LINE_OFFSET_LIST_H #include "prism/defines.h" From 74ddb891114b8b2d165fc5debbe8ca599d959d71 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sat, 31 Jan 2026 20:19:51 -0500 Subject: [PATCH 029/289] rename the C type everywhere --- include/prism/parser.h | 2 +- include/prism/static_literals.h | 4 ++-- include/prism/util/pm_char.h | 2 +- include/prism/util/pm_line_offset_list.h | 14 +++++++------- src/static_literals.c | 6 +++--- src/util/pm_char.c | 2 +- src/util/pm_newline_list.c | 12 ++++++------ templates/src/serialize.c.erb | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index 3e748e4e7a..5324d3f894 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -783,7 +783,7 @@ struct pm_parser { pm_constant_pool_t constant_pool; /** This is the list of newline offsets in the source file. */ - pm_newline_list_t newline_list; + pm_line_offset_list_t newline_list; /** * We want to add a flag to integer nodes that indicates their base. We only diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index f52440b6f1..a8a185c145 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -99,7 +99,7 @@ typedef struct { * @param replace Whether to replace the previous node if one already exists. * @return A pointer to the node that is being overwritten, if there is one. */ -pm_node_t * pm_static_literals_add(const pm_newline_list_t *newline_list, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); +pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); /** * Free the internal memory associated with the given static literals set. @@ -118,6 +118,6 @@ void pm_static_literals_free(pm_static_literals_t *literals); * @param encoding_name The name of the encoding of the source being parsed. * @param node The node to create a string representation of. */ -void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); +void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); #endif diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index 58dcc75272..2800c448cf 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -36,7 +36,7 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); * @return The number of characters at the start of the string that are * whitespace. */ -size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newline_list_t *newline_list, uint32_t start_offset); +size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *newline_list, uint32_t start_offset); /** * Returns the number of characters at the start of the string that are inline diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index d17c6fe51c..950210e6a4 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -34,7 +34,7 @@ typedef struct { /** The list of offsets. */ uint32_t *offsets; -} pm_newline_list_t; +} pm_line_offset_list_t; /** * A line and column in a string. @@ -55,14 +55,14 @@ typedef struct { * @param capacity The initial capacity of the list. * @return True if the allocation of the offsets succeeds, otherwise false. */ -bool pm_newline_list_init(pm_newline_list_t *list, size_t capacity); +bool pm_newline_list_init(pm_line_offset_list_t *list, size_t capacity); /** * Clear out the newlines that have been appended to the list. * * @param list The list to clear. */ -void pm_newline_list_clear(pm_newline_list_t *list); +void pm_newline_list_clear(pm_line_offset_list_t *list); /** * Append a new offset to the newline list. Returns true if the reallocation of @@ -73,7 +73,7 @@ void pm_newline_list_clear(pm_newline_list_t *list); * @return True if the reallocation of the offsets succeeds (if one was * necessary), otherwise false. */ -bool pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor); +bool pm_newline_list_append(pm_line_offset_list_t *list, uint32_t cursor); /** * Returns the line of the given offset. If the offset is not in the list, the @@ -84,7 +84,7 @@ bool pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor); * @param start_line The line to start counting from. * @return The line of the given offset. */ -int32_t pm_newline_list_line(const pm_newline_list_t *list, uint32_t cursor, int32_t start_line); +int32_t pm_newline_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** * Returns the line and column of the given offset. If the offset is not in the @@ -96,13 +96,13 @@ int32_t pm_newline_list_line(const pm_newline_list_t *list, uint32_t cursor, int * @param start_line The line to start counting from. * @return The line and column of the given offset. */ -pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, uint32_t cursor, int32_t start_line); +pm_line_column_t pm_newline_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** * Free the internal memory allocated for the newline list. * * @param list The list to free. */ -void pm_newline_list_free(pm_newline_list_t *list); +void pm_newline_list_free(pm_line_offset_list_t *list); #endif diff --git a/src/static_literals.c b/src/static_literals.c index 13a52378dd..e54b50c02f 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -7,7 +7,7 @@ */ typedef struct { /** The list of newline offsets to use to calculate line numbers. */ - const pm_newline_list_t *newline_list; + const pm_line_offset_list_t *newline_list; /** The start of the source being parsed. */ const uint8_t *start; @@ -356,7 +356,7 @@ pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_liter * Add a node to the set of static literals. */ pm_node_t * -pm_static_literals_add(const pm_newline_list_t *newline_list, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace) { +pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace) { switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: case PM_SOURCE_LINE_NODE: @@ -613,7 +613,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met * Create a string-based representation of the given static literal. */ void -pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node) { +pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node) { pm_static_literal_inspect_node( buffer, &(pm_static_literals_metadata_t) { diff --git a/src/util/pm_char.c b/src/util/pm_char.c index 748582b7fe..80ae63441c 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -83,7 +83,7 @@ pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length) { * searching past the given maximum number of characters. */ size_t -pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_newline_list_t *newline_list, uint32_t start_offset) { +pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *newline_list, uint32_t start_offset) { if (length <= 0) return 0; uint32_t size = 0; diff --git a/src/util/pm_newline_list.c b/src/util/pm_newline_list.c index 099a74c5f3..ad00a1db50 100644 --- a/src/util/pm_newline_list.c +++ b/src/util/pm_newline_list.c @@ -5,7 +5,7 @@ * allocation of the offsets succeeds, otherwise returns false. */ bool -pm_newline_list_init(pm_newline_list_t *list, size_t capacity) { +pm_newline_list_init(pm_line_offset_list_t *list, size_t capacity) { list->offsets = (uint32_t *) xcalloc(capacity, sizeof(uint32_t)); if (list->offsets == NULL) return false; @@ -21,7 +21,7 @@ pm_newline_list_init(pm_newline_list_t *list, size_t capacity) { * Clear out the newlines that have been appended to the list. */ void -pm_newline_list_clear(pm_newline_list_t *list) { +pm_newline_list_clear(pm_line_offset_list_t *list) { list->size = 1; } @@ -30,7 +30,7 @@ pm_newline_list_clear(pm_newline_list_t *list) { * the offsets succeeds (if one was necessary), otherwise returns false. */ bool -pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor) { +pm_newline_list_append(pm_line_offset_list_t *list, uint32_t cursor) { if (list->size == list->capacity) { uint32_t *original_offsets = list->offsets; @@ -53,7 +53,7 @@ pm_newline_list_append(pm_newline_list_t *list, uint32_t cursor) { * line of the closest offset less than the given offset is returned. */ int32_t -pm_newline_list_line(const pm_newline_list_t *list, uint32_t cursor, int32_t start_line) { +pm_newline_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { size_t left = 0; size_t right = list->size - 1; @@ -80,7 +80,7 @@ pm_newline_list_line(const pm_newline_list_t *list, uint32_t cursor, int32_t sta * are returned. */ pm_line_column_t -pm_newline_list_line_column(const pm_newline_list_t *list, uint32_t cursor, int32_t start_line) { +pm_newline_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { size_t left = 0; size_t right = list->size - 1; @@ -108,6 +108,6 @@ pm_newline_list_line_column(const pm_newline_list_t *list, uint32_t cursor, int3 * Free the internal memory allocated for the newline list. */ void -pm_newline_list_free(pm_newline_list_t *list) { +pm_newline_list_free(pm_line_offset_list_t *list) { xfree(list->offsets); } diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 958b0fd7cf..b9dde28786 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -154,7 +154,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } static void -pm_serialize_newline_list(pm_newline_list_t *list, pm_buffer_t *buffer) { +pm_serialize_newline_list(pm_line_offset_list_t *list, pm_buffer_t *buffer) { uint32_t size = pm_sizet_to_u32(list->size); pm_buffer_append_varuint(buffer, size); From 320bddc4d6e869e9f8788414fda9230bc261a5f4 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sat, 31 Jan 2026 20:21:20 -0500 Subject: [PATCH 030/289] rename the C functions --- include/prism/util/pm_line_offset_list.h | 12 +++--- src/prism.c | 54 ++++++++++++------------ src/static_literals.c | 6 +-- src/util/pm_char.c | 2 +- src/util/pm_newline_list.c | 12 +++--- templates/src/prettyprint.c.erb | 4 +- 6 files changed, 45 insertions(+), 45 deletions(-) diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index 950210e6a4..00176bc0d8 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -55,14 +55,14 @@ typedef struct { * @param capacity The initial capacity of the list. * @return True if the allocation of the offsets succeeds, otherwise false. */ -bool pm_newline_list_init(pm_line_offset_list_t *list, size_t capacity); +bool pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity); /** * Clear out the newlines that have been appended to the list. * * @param list The list to clear. */ -void pm_newline_list_clear(pm_line_offset_list_t *list); +void pm_line_offset_list_clear(pm_line_offset_list_t *list); /** * Append a new offset to the newline list. Returns true if the reallocation of @@ -73,7 +73,7 @@ void pm_newline_list_clear(pm_line_offset_list_t *list); * @return True if the reallocation of the offsets succeeds (if one was * necessary), otherwise false. */ -bool pm_newline_list_append(pm_line_offset_list_t *list, uint32_t cursor); +bool pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor); /** * Returns the line of the given offset. If the offset is not in the list, the @@ -84,7 +84,7 @@ bool pm_newline_list_append(pm_line_offset_list_t *list, uint32_t cursor); * @param start_line The line to start counting from. * @return The line of the given offset. */ -int32_t pm_newline_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); +int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** * Returns the line and column of the given offset. If the offset is not in the @@ -96,13 +96,13 @@ int32_t pm_newline_list_line(const pm_line_offset_list_t *list, uint32_t cursor, * @param start_line The line to start counting from. * @return The line and column of the given offset. */ -pm_line_column_t pm_newline_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); +pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** * Free the internal memory allocated for the newline list. * * @param list The list to free. */ -void pm_newline_list_free(pm_line_offset_list_t *list); +void pm_line_offset_list_free(pm_line_offset_list_t *list); #endif diff --git a/src/prism.c b/src/prism.c index 56cb9e3fb3..7aaa0cf47f 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1000,7 +1000,7 @@ pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, if (local->name != PM_CONSTANT_ID_UNSET) { pm_constant_id_list_insert(list, (size_t) local->index, local->name); - if (warn_unused && local->reads == 0 && ((parser->start_line >= 0) || (pm_newline_list_line(&parser->newline_list, local->location.start, parser->start_line) >= 0))) { + if (warn_unused && local->reads == 0 && ((parser->start_line >= 0) || (pm_line_offset_list_line(&parser->newline_list, local->location.start, parser->start_line) >= 0))) { pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, local->name); if (constant->length >= 1 && *constant->start != '_') { @@ -9385,7 +9385,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9419,7 +9419,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9439,7 +9439,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9753,7 +9753,7 @@ pm_lex_percent_delimiter(pm_parser_t *parser) { parser_flush_heredoc_end(parser); } else { // Otherwise, we'll add the newline to the list of newlines. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); } uint8_t delimiter = *parser->current.end; @@ -9857,7 +9857,7 @@ parser_lex(pm_parser_t *parser) { parser->heredoc_end = NULL; } else { parser->current.end += eol_length + 1; - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); space_seen = true; } } else if (pm_char_is_inline_whitespace(*parser->current.end)) { @@ -9959,7 +9959,7 @@ parser_lex(pm_parser_t *parser) { } if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); } } @@ -10468,7 +10468,7 @@ parser_lex(pm_parser_t *parser) { } else { // Otherwise, we want to indicate that the body of the // heredoc starts on the character after the next newline. - pm_newline_list_append(&parser->newline_list, U32(body_start - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(body_start - parser->start + 1)); body_start++; } @@ -11109,7 +11109,7 @@ parser_lex(pm_parser_t *parser) { // correct column information for it. const uint8_t *cursor = parser->current.end; while ((cursor = next_newline(cursor, parser->end - cursor)) != NULL) { - pm_newline_list_append(&parser->newline_list, U32(++cursor - parser->start)); + pm_line_offset_list_append(&parser->newline_list, U32(++cursor - parser->start)); } parser->current.end = parser->end; @@ -11285,7 +11285,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11423,7 +11423,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11470,7 +11470,7 @@ parser_lex(pm_parser_t *parser) { // If we've hit a newline, then we need to track that in // the list of newlines. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false); break; @@ -11518,7 +11518,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11683,7 +11683,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11735,7 +11735,7 @@ parser_lex(pm_parser_t *parser) { // for the terminator in case the terminator is a // newline character. if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true); break; @@ -11789,7 +11789,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_newline_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11918,7 +11918,7 @@ parser_lex(pm_parser_t *parser) { (memcmp(terminator_start, ident_start, ident_length) == 0) ) { if (newline != NULL) { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); } parser->current.end = terminator_end; @@ -11990,7 +11990,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } - pm_newline_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); // If we have a - or ~ heredoc, then we can match after // some leading whitespace. @@ -12110,7 +12110,7 @@ parser_lex(pm_parser_t *parser) { const uint8_t *end = parser->current.end; if (parser->heredoc_end == NULL) { - pm_newline_list_append(&parser->newline_list, U32(end - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(end - parser->start + 1)); } // Here we want the buffer to only @@ -13347,7 +13347,7 @@ pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *liter PM_WARN_DUPLICATED_HASH_KEY, (int) pm_buffer_length(&buffer), pm_buffer_value(&buffer), - pm_newline_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line + pm_line_offset_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line ); pm_buffer_free(&buffer); @@ -13368,8 +13368,8 @@ pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *li PM_NODE_START(node), PM_NODE_LENGTH(node), PM_WARN_DUPLICATED_WHEN_CLAUSE, - pm_newline_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line, - pm_newline_list_line_column(&parser->newline_list, PM_NODE_START(previous), parser->start_line).line + pm_line_offset_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line, + pm_line_offset_list_line_column(&parser->newline_list, PM_NODE_START(previous), parser->start_line).line ); } } @@ -14324,7 +14324,7 @@ token_newline_index(const pm_parser_t *parser) { // start of a heredoc, so we cannot rely on looking at the previous // offset of the newline list, and instead must go through the whole // process of a binary search for the line number. - return (size_t) pm_newline_list_line(&parser->newline_list, PM_TOKEN_START(parser, &parser->current), 0); + return (size_t) pm_line_offset_list_line(&parser->newline_list, PM_TOKEN_START(parser, &parser->current), 0); } } @@ -22015,7 +22015,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // guess at the number of newlines that we'll need based on the size of the // input. size_t newline_size = size / 22; - pm_newline_list_init(&parser->newline_list, newline_size < 4 ? 4 : newline_size); + pm_line_offset_list_init(&parser->newline_list, newline_size < 4 ? 4 : newline_size); // If options were provided to this parse, establish them here. if (options != NULL) { @@ -22154,7 +22154,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm const uint8_t *newline = next_newline(cursor, parser->end - cursor); while (newline != NULL) { - pm_newline_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); cursor = newline + 1; newline = next_newline(cursor, parser->end - cursor); @@ -22184,7 +22184,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm parser->current = (pm_token_t) { .type = PM_TOKEN_EOF, .start = cursor, .end = cursor }; } else { pm_parser_err(parser, 0, 0, PM_ERR_SCRIPT_NOT_FOUND); - pm_newline_list_clear(&parser->newline_list); + pm_line_offset_list_clear(&parser->newline_list); } } @@ -22244,7 +22244,7 @@ pm_parser_free(pm_parser_t *parser) { pm_comment_list_free(&parser->comment_list); pm_magic_comment_list_free(&parser->magic_comment_list); pm_constant_pool_free(&parser->constant_pool); - pm_newline_list_free(&parser->newline_list); + pm_line_offset_list_free(&parser->newline_list); while (parser->current_scope != NULL) { // Normally, popping the scope doesn't free the locals since it is diff --git a/src/static_literals.c b/src/static_literals.c index e54b50c02f..64bf1740c9 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -95,7 +95,7 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) } case PM_SOURCE_LINE_NODE: { // Source lines hash their line number. - const pm_line_column_t line_column = pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line); + const pm_line_column_t line_column = pm_line_offset_list_line_column(metadata->newline_list, node->location.start, metadata->start_line); const int32_t *value = &line_column.line; return murmur_hash((const uint8_t *) value, sizeof(int32_t)); } @@ -243,7 +243,7 @@ pm_int64_value(const pm_static_literals_metadata_t *metadata, const pm_node_t *n return integer->negative ? -value : value; } case PM_SOURCE_LINE_NODE: - return (int64_t) pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line; + return (int64_t) pm_line_offset_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line; default: assert(false && "unreachable"); return 0; @@ -585,7 +585,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met break; } case PM_SOURCE_LINE_NODE: - pm_buffer_append_format(buffer, "%d", pm_newline_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line); + pm_buffer_append_format(buffer, "%d", pm_line_offset_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line); break; case PM_STRING_NODE: { const pm_string_t *unescaped = &((const pm_string_node_t *) node)->unescaped; diff --git a/src/util/pm_char.c b/src/util/pm_char.c index 80ae63441c..1b4493ef7f 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -91,7 +91,7 @@ pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_o while (size < maximum && (pm_byte_table[string[size]] & PRISM_CHAR_BIT_WHITESPACE)) { if (string[size] == '\n') { - pm_newline_list_append(newline_list, start_offset + size + 1); + pm_line_offset_list_append(newline_list, start_offset + size + 1); } size++; diff --git a/src/util/pm_newline_list.c b/src/util/pm_newline_list.c index ad00a1db50..710fa4b788 100644 --- a/src/util/pm_newline_list.c +++ b/src/util/pm_newline_list.c @@ -5,7 +5,7 @@ * allocation of the offsets succeeds, otherwise returns false. */ bool -pm_newline_list_init(pm_line_offset_list_t *list, size_t capacity) { +pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity) { list->offsets = (uint32_t *) xcalloc(capacity, sizeof(uint32_t)); if (list->offsets == NULL) return false; @@ -21,7 +21,7 @@ pm_newline_list_init(pm_line_offset_list_t *list, size_t capacity) { * Clear out the newlines that have been appended to the list. */ void -pm_newline_list_clear(pm_line_offset_list_t *list) { +pm_line_offset_list_clear(pm_line_offset_list_t *list) { list->size = 1; } @@ -30,7 +30,7 @@ pm_newline_list_clear(pm_line_offset_list_t *list) { * the offsets succeeds (if one was necessary), otherwise returns false. */ bool -pm_newline_list_append(pm_line_offset_list_t *list, uint32_t cursor) { +pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor) { if (list->size == list->capacity) { uint32_t *original_offsets = list->offsets; @@ -53,7 +53,7 @@ pm_newline_list_append(pm_line_offset_list_t *list, uint32_t cursor) { * line of the closest offset less than the given offset is returned. */ int32_t -pm_newline_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { +pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { size_t left = 0; size_t right = list->size - 1; @@ -80,7 +80,7 @@ pm_newline_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t * are returned. */ pm_line_column_t -pm_newline_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { +pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) { size_t left = 0; size_t right = list->size - 1; @@ -108,6 +108,6 @@ pm_newline_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, * Free the internal memory allocated for the newline list. */ void -pm_newline_list_free(pm_line_offset_list_t *list) { +pm_line_offset_list_free(pm_line_offset_list_t *list) { xfree(list->offsets); } diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 74c0f6dbdf..5e849f3557 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -12,8 +12,8 @@ void pm_prettyprint(void) {} static inline void prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) { - pm_line_column_t start = pm_newline_list_line_column(&parser->newline_list, location->start, parser->start_line); - pm_line_column_t end = pm_newline_list_line_column(&parser->newline_list, location->start + location->length, parser->start_line); + pm_line_column_t start = pm_line_offset_list_line_column(&parser->newline_list, location->start, parser->start_line); + pm_line_column_t end = pm_line_offset_list_line_column(&parser->newline_list, location->start + location->length, parser->start_line); pm_buffer_append_format(output_buffer, "(%" PRIi32 ",%" PRIu32 ")-(%" PRIi32 ",%" PRIu32 ")", start.line, start.column, end.line, end.column); } From 29ca94abf7493b134c746be6714143b65b2565d8 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 15 Feb 2026 16:47:17 -0500 Subject: [PATCH 031/289] rename struct fields in `pm_parser_t` and `pm_static_literals_metadata_t` --- ext/prism/extension.c | 6 +-- include/prism/parser.h | 2 +- src/prism.c | 70 +++++++++++++++--------------- src/static_literals.c | 22 +++++----- templates/ext/prism/api_node.c.erb | 6 +-- templates/src/prettyprint.c.erb | 4 +- templates/src/serialize.c.erb | 2 +- 7 files changed, 56 insertions(+), 56 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index e9e9f2ec2c..03182c1a57 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -741,7 +741,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback); VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input)); - VALUE offsets = rb_ary_new_capa(parser.newline_list.size); + VALUE offsets = rb_ary_new_capa(parser.line_offsets.size); VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser.start_line), offsets); parse_lex_data_t parse_lex_data = { @@ -767,8 +767,8 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod rb_encoding *encoding = rb_enc_find(parser.encoding->name); rb_enc_associate(source_string, encoding); - for (size_t index = 0; index < parser.newline_list.size; index++) { - rb_ary_push(offsets, ULONG2NUM(parser.newline_list.offsets[index])); + for (size_t index = 0; index < parser.line_offsets.size; index++) { + rb_ary_push(offsets, ULONG2NUM(parser.line_offsets.offsets[index])); } if (options->freeze) { diff --git a/include/prism/parser.h b/include/prism/parser.h index 5324d3f894..aad0d985a3 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -783,7 +783,7 @@ struct pm_parser { pm_constant_pool_t constant_pool; /** This is the list of newline offsets in the source file. */ - pm_line_offset_list_t newline_list; + pm_line_offset_list_t line_offsets; /** * We want to add a flag to integer nodes that indicates their base. We only diff --git a/src/prism.c b/src/prism.c index 7aaa0cf47f..4465b4982e 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1000,7 +1000,7 @@ pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, if (local->name != PM_CONSTANT_ID_UNSET) { pm_constant_id_list_insert(list, (size_t) local->index, local->name); - if (warn_unused && local->reads == 0 && ((parser->start_line >= 0) || (pm_line_offset_list_line(&parser->newline_list, local->location.start, parser->start_line) >= 0))) { + if (warn_unused && local->reads == 0 && ((parser->start_line >= 0) || (pm_line_offset_list_line(&parser->line_offsets, local->location.start, parser->start_line) >= 0))) { pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, local->name); if (constant->length >= 1 && *constant->start != '_') { @@ -9385,7 +9385,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9419,7 +9419,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9439,7 +9439,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9753,7 +9753,7 @@ pm_lex_percent_delimiter(pm_parser_t *parser) { parser_flush_heredoc_end(parser); } else { // Otherwise, we'll add the newline to the list of newlines. - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); } uint8_t delimiter = *parser->current.end; @@ -9857,7 +9857,7 @@ parser_lex(pm_parser_t *parser) { parser->heredoc_end = NULL; } else { parser->current.end += eol_length + 1; - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); space_seen = true; } } else if (pm_char_is_inline_whitespace(*parser->current.end)) { @@ -9959,7 +9959,7 @@ parser_lex(pm_parser_t *parser) { } if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } @@ -10468,7 +10468,7 @@ parser_lex(pm_parser_t *parser) { } else { // Otherwise, we want to indicate that the body of the // heredoc starts on the character after the next newline. - pm_line_offset_list_append(&parser->newline_list, U32(body_start - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(body_start - parser->start + 1)); body_start++; } @@ -11109,7 +11109,7 @@ parser_lex(pm_parser_t *parser) { // correct column information for it. const uint8_t *cursor = parser->current.end; while ((cursor = next_newline(cursor, parser->end - cursor)) != NULL) { - pm_line_offset_list_append(&parser->newline_list, U32(++cursor - parser->start)); + pm_line_offset_list_append(&parser->line_offsets, U32(++cursor - parser->start)); } parser->current.end = parser->end; @@ -11170,7 +11170,7 @@ parser_lex(pm_parser_t *parser) { whitespace += 1; } } else { - whitespace = pm_strspn_whitespace_newlines(parser->current.end, parser->end - parser->current.end, &parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + whitespace = pm_strspn_whitespace_newlines(parser->current.end, parser->end - parser->current.end, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } if (whitespace > 0) { @@ -11285,7 +11285,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11423,7 +11423,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11470,7 +11470,7 @@ parser_lex(pm_parser_t *parser) { // If we've hit a newline, then we need to track that in // the list of newlines. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false); break; @@ -11518,7 +11518,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11683,7 +11683,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11735,7 +11735,7 @@ parser_lex(pm_parser_t *parser) { // for the terminator in case the terminator is a // newline character. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true); break; @@ -11789,7 +11789,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_line_offset_list_append(&parser->newline_list, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11918,7 +11918,7 @@ parser_lex(pm_parser_t *parser) { (memcmp(terminator_start, ident_start, ident_length) == 0) ) { if (newline != NULL) { - pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); } parser->current.end = terminator_end; @@ -11990,7 +11990,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } - pm_line_offset_list_append(&parser->newline_list, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); // If we have a - or ~ heredoc, then we can match after // some leading whitespace. @@ -12110,7 +12110,7 @@ parser_lex(pm_parser_t *parser) { const uint8_t *end = parser->current.end; if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->newline_list, U32(end - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(end - parser->start + 1)); } // Here we want the buffer to only @@ -13334,11 +13334,11 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { */ static void pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { - const pm_node_t *duplicated = pm_static_literals_add(&parser->newline_list, parser->start, parser->start_line, literals, node, true); + const pm_node_t *duplicated = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, literals, node, true); if (duplicated != NULL) { pm_buffer_t buffer = { 0 }; - pm_static_literal_inspect(&buffer, &parser->newline_list, parser->start, parser->start_line, parser->encoding->name, duplicated); + pm_static_literal_inspect(&buffer, &parser->line_offsets, parser->start, parser->start_line, parser->encoding->name, duplicated); pm_diagnostic_list_append_format( &parser->warning_list, @@ -13347,7 +13347,7 @@ pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *liter PM_WARN_DUPLICATED_HASH_KEY, (int) pm_buffer_length(&buffer), pm_buffer_value(&buffer), - pm_line_offset_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line + pm_line_offset_list_line_column(&parser->line_offsets, PM_NODE_START(node), parser->start_line).line ); pm_buffer_free(&buffer); @@ -13362,14 +13362,14 @@ static void pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { pm_node_t *previous; - if ((previous = pm_static_literals_add(&parser->newline_list, parser->start, parser->start_line, literals, node, false)) != NULL) { + if ((previous = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, literals, node, false)) != NULL) { pm_diagnostic_list_append_format( &parser->warning_list, PM_NODE_START(node), PM_NODE_LENGTH(node), PM_WARN_DUPLICATED_WHEN_CLAUSE, - pm_line_offset_list_line_column(&parser->newline_list, PM_NODE_START(node), parser->start_line).line, - pm_line_offset_list_line_column(&parser->newline_list, PM_NODE_START(previous), parser->start_line).line + pm_line_offset_list_line_column(&parser->line_offsets, PM_NODE_START(node), parser->start_line).line, + pm_line_offset_list_line_column(&parser->line_offsets, PM_NODE_START(previous), parser->start_line).line ); } } @@ -14318,13 +14318,13 @@ token_newline_index(const pm_parser_t *parser) { // This is the common case. In this case we can look at the previously // recorded newline in the newline list and subtract from the current // offset. - return parser->newline_list.size - 1; + return parser->line_offsets.size - 1; } else { // This is unlikely. This is the case that we have already parsed the // start of a heredoc, so we cannot rely on looking at the previous // offset of the newline list, and instead must go through the whole // process of a binary search for the line number. - return (size_t) pm_line_offset_list_line(&parser->newline_list, PM_TOKEN_START(parser, &parser->current), 0); + return (size_t) pm_line_offset_list_line(&parser->line_offsets, PM_TOKEN_START(parser, &parser->current), 0); } } @@ -14334,7 +14334,7 @@ token_newline_index(const pm_parser_t *parser) { */ static int64_t token_column(const pm_parser_t *parser, size_t newline_index, const pm_token_t *token, bool break_on_non_space) { - const uint8_t *cursor = parser->start + parser->newline_list.offsets[newline_index]; + const uint8_t *cursor = parser->start + parser->line_offsets.offsets[newline_index]; const uint8_t *end = token->start; // Skip over the BOM if it is present. @@ -16483,7 +16483,7 @@ parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_list_t *ca */ static void parse_pattern_hash_key(pm_parser_t *parser, pm_static_literals_t *keys, pm_node_t *node) { - if (pm_static_literals_add(&parser->newline_list, parser->start, parser->start_line, keys, node, true) != NULL) { + if (pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, keys, node, true) != NULL) { pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_KEY_DUPLICATE); } } @@ -21973,7 +21973,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm .lex_callback = NULL, .filepath = { 0 }, .constant_pool = { 0 }, - .newline_list = { 0 }, + .line_offsets = { 0 }, .integer_base = 0, .current_string = PM_STRING_EMPTY, .start_line = 1, @@ -22015,7 +22015,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // guess at the number of newlines that we'll need based on the size of the // input. size_t newline_size = size / 22; - pm_line_offset_list_init(&parser->newline_list, newline_size < 4 ? 4 : newline_size); + pm_line_offset_list_init(&parser->line_offsets, newline_size < 4 ? 4 : newline_size); // If options were provided to this parse, establish them here. if (options != NULL) { @@ -22154,7 +22154,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm const uint8_t *newline = next_newline(cursor, parser->end - cursor); while (newline != NULL) { - pm_line_offset_list_append(&parser->newline_list, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); cursor = newline + 1; newline = next_newline(cursor, parser->end - cursor); @@ -22184,7 +22184,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm parser->current = (pm_token_t) { .type = PM_TOKEN_EOF, .start = cursor, .end = cursor }; } else { pm_parser_err(parser, 0, 0, PM_ERR_SCRIPT_NOT_FOUND); - pm_line_offset_list_clear(&parser->newline_list); + pm_line_offset_list_clear(&parser->line_offsets); } } @@ -22244,7 +22244,7 @@ pm_parser_free(pm_parser_t *parser) { pm_comment_list_free(&parser->comment_list); pm_magic_comment_list_free(&parser->magic_comment_list); pm_constant_pool_free(&parser->constant_pool); - pm_line_offset_list_free(&parser->newline_list); + pm_line_offset_list_free(&parser->line_offsets); while (parser->current_scope != NULL) { // Normally, popping the scope doesn't free the locals since it is diff --git a/src/static_literals.c b/src/static_literals.c index 64bf1740c9..ef2d2436a9 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -7,7 +7,7 @@ */ typedef struct { /** The list of newline offsets to use to calculate line numbers. */ - const pm_line_offset_list_t *newline_list; + const pm_line_offset_list_t *line_offsets; /** The start of the source being parsed. */ const uint8_t *start; @@ -95,7 +95,7 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) } case PM_SOURCE_LINE_NODE: { // Source lines hash their line number. - const pm_line_column_t line_column = pm_line_offset_list_line_column(metadata->newline_list, node->location.start, metadata->start_line); + const pm_line_column_t line_column = pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line); const int32_t *value = &line_column.line; return murmur_hash((const uint8_t *) value, sizeof(int32_t)); } @@ -243,7 +243,7 @@ pm_int64_value(const pm_static_literals_metadata_t *metadata, const pm_node_t *n return integer->negative ? -value : value; } case PM_SOURCE_LINE_NODE: - return (int64_t) pm_line_offset_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line; + return (int64_t) pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line).line; default: assert(false && "unreachable"); return 0; @@ -363,7 +363,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->integer_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = newline_list, .start = start, .start_line = start_line, .encoding_name = NULL @@ -376,7 +376,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->float_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = newline_list, .start = start, .start_line = start_line, .encoding_name = NULL @@ -390,7 +390,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->number_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = newline_list, .start = start, .start_line = start_line, .encoding_name = NULL @@ -404,7 +404,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->string_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = newline_list, .start = start, .start_line = start_line, .encoding_name = NULL @@ -417,7 +417,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->regexp_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = newline_list, .start = start, .start_line = start_line, .encoding_name = NULL @@ -430,7 +430,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->symbol_nodes, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = newline_list, .start = start, .start_line = start_line, .encoding_name = NULL @@ -585,7 +585,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met break; } case PM_SOURCE_LINE_NODE: - pm_buffer_append_format(buffer, "%d", pm_line_offset_list_line_column(metadata->newline_list, node->location.start, metadata->start_line).line); + pm_buffer_append_format(buffer, "%d", pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line).line); break; case PM_STRING_NODE: { const pm_string_t *unescaped = &((const pm_string_node_t *) node)->unescaped; @@ -617,7 +617,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *newl pm_static_literal_inspect_node( buffer, &(pm_static_literals_metadata_t) { - .newline_list = newline_list, + .line_offsets = newline_list, .start = start, .start_line = start_line, .encoding_name = encoding_name diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index e9c3742085..69f70240f8 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -76,9 +76,9 @@ VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) { VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding); - VALUE offsets = rb_ary_new_capa(parser->newline_list.size); - for (size_t index = 0; index < parser->newline_list.size; index++) { - rb_ary_push(offsets, ULONG2NUM(parser->newline_list.offsets[index])); + VALUE offsets = rb_ary_new_capa(parser->line_offsets.size); + for (size_t index = 0; index < parser->line_offsets.size; index++) { + rb_ary_push(offsets, ULONG2NUM(parser->line_offsets.offsets[index])); } if (freeze) { diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 5e849f3557..44423ca42b 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -12,8 +12,8 @@ void pm_prettyprint(void) {} static inline void prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) { - pm_line_column_t start = pm_line_offset_list_line_column(&parser->newline_list, location->start, parser->start_line); - pm_line_column_t end = pm_line_offset_list_line_column(&parser->newline_list, location->start + location->length, parser->start_line); + pm_line_column_t start = pm_line_offset_list_line_column(&parser->line_offsets, location->start, parser->start_line); + pm_line_column_t end = pm_line_offset_list_line_column(&parser->line_offsets, location->start + location->length, parser->start_line); pm_buffer_append_format(output_buffer, "(%" PRIi32 ",%" PRIu32 ")-(%" PRIi32 ",%" PRIu32 ")", start.line, start.column, end.line, end.column); } diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index b9dde28786..33389345a8 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -257,7 +257,7 @@ static void pm_serialize_metadata(pm_parser_t *parser, pm_buffer_t *buffer) { pm_serialize_encoding(parser->encoding, buffer); pm_buffer_append_varsint(buffer, parser->start_line); - pm_serialize_newline_list(&parser->newline_list, buffer); + pm_serialize_newline_list(&parser->line_offsets, buffer); <%- unless Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS -%> pm_serialize_comment_list(&parser->comment_list, buffer); <%- end -%> From 7406704c998171fa7368b068b772ceac483cfe7a Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 15 Feb 2026 16:48:40 -0500 Subject: [PATCH 032/289] rename function parameters in `static_literals.c` --- src/static_literals.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/static_literals.c b/src/static_literals.c index ef2d2436a9..58a08a8c03 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -356,14 +356,14 @@ pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_liter * Add a node to the set of static literals. */ pm_node_t * -pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace) { +pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace) { switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: case PM_SOURCE_LINE_NODE: return pm_node_hash_insert( &literals->integer_nodes, &(pm_static_literals_metadata_t) { - .line_offsets = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -376,7 +376,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->float_nodes, &(pm_static_literals_metadata_t) { - .line_offsets = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -390,7 +390,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->number_nodes, &(pm_static_literals_metadata_t) { - .line_offsets = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -404,7 +404,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->string_nodes, &(pm_static_literals_metadata_t) { - .line_offsets = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -417,7 +417,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->regexp_nodes, &(pm_static_literals_metadata_t) { - .line_offsets = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -430,7 +430,7 @@ pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t return pm_node_hash_insert( &literals->symbol_nodes, &(pm_static_literals_metadata_t) { - .line_offsets = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = NULL @@ -613,11 +613,11 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met * Create a string-based representation of the given static literal. */ void -pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node) { +pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node) { pm_static_literal_inspect_node( buffer, &(pm_static_literals_metadata_t) { - .line_offsets = newline_list, + .line_offsets = line_offsets, .start = start, .start_line = start_line, .encoding_name = encoding_name From 28d7bc35797a4da80880245e216606346514ee0b Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 15 Feb 2026 16:50:49 -0500 Subject: [PATCH 033/289] rename function parameters and docs --- include/prism/static_literals.h | 8 ++++---- include/prism/util/pm_char.h | 4 ++-- src/util/pm_char.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index a8a185c145..6d73e5d04f 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -91,7 +91,7 @@ typedef struct { /** * Add a node to the set of static literals. * - * @param newline_list The list of newline offsets to use to calculate lines. + * @param line_offsets The list of newline offsets to use to calculate lines. * @param start The start of the source being parsed. * @param start_line The line number that the parser starts on. * @param literals The set of static literals to add the node to. @@ -99,7 +99,7 @@ typedef struct { * @param replace Whether to replace the previous node if one already exists. * @return A pointer to the node that is being overwritten, if there is one. */ -pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); +pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); /** * Free the internal memory associated with the given static literals set. @@ -112,12 +112,12 @@ void pm_static_literals_free(pm_static_literals_t *literals); * Create a string-based representation of the given static literal. * * @param buffer The buffer to write the string to. - * @param newline_list The list of newline offsets to use to calculate lines. + * @param line_offsets The list of newline offsets to use to calculate lines. * @param start The start of the source being parsed. * @param start_line The line number that the parser starts on. * @param encoding_name The name of the encoding of the source being parsed. * @param node The node to create a string representation of. */ -void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *newline_list, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); +void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); #endif diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index 2800c448cf..ab1f513a66 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -30,13 +30,13 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); * * @param string The string to search. * @param length The maximum number of characters to search. - * @param newline_list The list of newlines to populate. + * @param line_offsets The list of newlines to populate. * @param start_offset The offset at which the string occurs in the source, for * the purpose of tracking newlines. * @return The number of characters at the start of the string that are * whitespace. */ -size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *newline_list, uint32_t start_offset); +size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset); /** * Returns the number of characters at the start of the string that are inline diff --git a/src/util/pm_char.c b/src/util/pm_char.c index 1b4493ef7f..f0baf47784 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -83,7 +83,7 @@ pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length) { * searching past the given maximum number of characters. */ size_t -pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *newline_list, uint32_t start_offset) { +pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset) { if (length <= 0) return 0; uint32_t size = 0; @@ -91,7 +91,7 @@ pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_o while (size < maximum && (pm_byte_table[string[size]] & PRISM_CHAR_BIT_WHITESPACE)) { if (string[size] == '\n') { - pm_line_offset_list_append(newline_list, start_offset + size + 1); + pm_line_offset_list_append(line_offsets, start_offset + size + 1); } size++; From 702b58a614f4bead11d4bcd4e6ef7cbd850701c2 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 15 Feb 2026 16:51:00 -0500 Subject: [PATCH 034/289] rename in serialization code --- templates/src/serialize.c.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 33389345a8..54a499d8bb 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -154,7 +154,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { } static void -pm_serialize_newline_list(pm_line_offset_list_t *list, pm_buffer_t *buffer) { +pm_serialize_line_offset_list(pm_line_offset_list_t *list, pm_buffer_t *buffer) { uint32_t size = pm_sizet_to_u32(list->size); pm_buffer_append_varuint(buffer, size); @@ -257,7 +257,7 @@ static void pm_serialize_metadata(pm_parser_t *parser, pm_buffer_t *buffer) { pm_serialize_encoding(parser->encoding, buffer); pm_buffer_append_varsint(buffer, parser->start_line); - pm_serialize_newline_list(&parser->line_offsets, buffer); + pm_serialize_line_offset_list(&parser->line_offsets, buffer); <%- unless Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS -%> pm_serialize_comment_list(&parser->comment_list, buffer); <%- end -%> From 6db9037fa39ae39bc3c34fdf3ea105dc4bc9e570 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 15 Feb 2026 16:53:45 -0500 Subject: [PATCH 035/289] fixup docs for the list header itself --- include/prism/util/pm_line_offset_list.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index 00176bc0d8..fe16e0b034 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -22,8 +22,8 @@ #include /** - * A list of offsets of newlines in a string. The offsets are assumed to be - * sorted/inserted in ascending order. + * A list of offsets of the start of lines in a string. The offsets are assumed + * to be sorted/inserted in ascending order. */ typedef struct { /** The number of offsets in the list. */ @@ -48,8 +48,8 @@ typedef struct { } pm_line_column_t; /** - * Initialize a new newline list with the given capacity. Returns true if the - * allocation of the offsets succeeds, otherwise returns false. + * Initialize a new line offset list with the given capacity. Returns true if + * the allocation of the offsets succeeds, otherwise returns false. * * @param list The list to initialize. * @param capacity The initial capacity of the list. @@ -58,15 +58,15 @@ typedef struct { bool pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity); /** - * Clear out the newlines that have been appended to the list. + * Clear out the offsets that have been appended to the list. * * @param list The list to clear. */ void pm_line_offset_list_clear(pm_line_offset_list_t *list); /** - * Append a new offset to the newline list. Returns true if the reallocation of - * the offsets succeeds (if one was necessary), otherwise returns false. + * Append a new offset to the list. Returns true if the reallocation of the + * offsets succeeds (if one was necessary), otherwise returns false. * * @param list The list to append to. * @param cursor The offset to append. @@ -99,7 +99,7 @@ int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cur pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** - * Free the internal memory allocated for the newline list. + * Free the internal memory allocated for the list. * * @param list The list to free. */ From 094e28a483005e36e03bb0a4c620e649c6e1f082 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 15 Feb 2026 16:54:10 -0500 Subject: [PATCH 036/289] fixup docs in `parser.h` --- include/prism/parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index aad0d985a3..b4e3038439 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -782,7 +782,7 @@ struct pm_parser { */ pm_constant_pool_t constant_pool; - /** This is the list of newline offsets in the source file. */ + /** This is the list of line offsets in the source file. */ pm_line_offset_list_t line_offsets; /** From e5b0c295544d8a1036fb4795078471cd022d5437 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 15 Feb 2026 16:56:10 -0500 Subject: [PATCH 037/289] rename `pm_newline_list.c` --- prism.gemspec | 2 +- src/util/{pm_newline_list.c => pm_line_offset_list.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/util/{pm_newline_list.c => pm_line_offset_list.c} (100%) diff --git a/prism.gemspec b/prism.gemspec index c8fb2e0a0d..d7f31716ce 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -154,7 +154,7 @@ Gem::Specification.new do |spec| "src/util/pm_integer.c", "src/util/pm_list.c", "src/util/pm_memchr.c", - "src/util/pm_newline_list.c", + "src/util/pm_line_offset_list.c", "src/util/pm_string.c", "src/util/pm_strncasecmp.c", "src/util/pm_strpbrk.c" diff --git a/src/util/pm_newline_list.c b/src/util/pm_line_offset_list.c similarity index 100% rename from src/util/pm_newline_list.c rename to src/util/pm_line_offset_list.c From ffe8f7a6e236790858e089d10bbc91f9ef9de6cb Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 17 Feb 2026 14:51:05 +0100 Subject: [PATCH 038/289] Recompile when config.yml changes * Fixes https://github.com/ruby/prism/issues/3931. * The first line is the default one, we want to keep that default dependency too. * Some docs about this: https://docs.ruby-lang.org/en/4.0/MakeMakefile.html --- ext/prism/depend | 2 ++ prism.gemspec | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 ext/prism/depend diff --git a/ext/prism/depend b/ext/prism/depend new file mode 100644 index 0000000000..ac0e7a9bb3 --- /dev/null +++ b/ext/prism/depend @@ -0,0 +1,2 @@ +$(OBJS): $(HDRS) $(ruby_headers) +$(OBJS): $(srcdir)/../../config.yml diff --git a/prism.gemspec b/prism.gemspec index d7f31716ce..a155dc3da4 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -42,6 +42,8 @@ Gem::Specification.new do |spec| "docs/serialization.md", "docs/testing.md", "ext/prism/api_node.c", + "ext/prism/depend", + "ext/prism/extconf.rb", "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", From 003ff5341d556d436f442122ebedcf8be8aaffe5 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Wed, 18 Feb 2026 16:59:13 -0500 Subject: [PATCH 039/289] add `extern "C"` wrappers to `prism.h` when using C++ --- include/prism.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/prism.h b/include/prism.h index c17d759fea..a71ccfef36 100644 --- a/include/prism.h +++ b/include/prism.h @@ -6,6 +6,10 @@ #ifndef PRISM_H #define PRISM_H +#ifdef __cplusplus +extern "C" { +#endif + #include "prism/defines.h" #include "prism/util/pm_buffer.h" #include "prism/util/pm_char.h" @@ -403,4 +407,8 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * ``` */ +#ifdef __cplusplus +} +#endif + #endif From 6fb4c42637a209ad33e42e1653992f8ea8970b98 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 19 Feb 2026 10:03:55 +0100 Subject: [PATCH 040/289] Revert "[DOC] Add code fences" (#3936) This reverts commit 641775e5fea6dc818f8183a0f3eb7336023d17c9. There is no need, they are not documented. --- lib/prism/translation/ruby_parser.rb | 282 --------------------------- 1 file changed, 282 deletions(-) diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb index 5f4a8cab92..3ba892634f 100644 --- a/lib/prism/translation/ruby_parser.rb +++ b/lib/prism/translation/ruby_parser.rb @@ -40,34 +40,26 @@ def initialize(file, in_def: false, in_pattern: false) @in_pattern = in_pattern end - # ``` # alias foo bar # ^^^^^^^^^^^^^ - # ``` def visit_alias_method_node(node) s(node, :alias, visit(node.new_name), visit(node.old_name)) end - # ``` # alias $foo $bar # ^^^^^^^^^^^^^^^ - # ``` def visit_alias_global_variable_node(node) s(node, :valias, node.new_name.name, node.old_name.name) end - # ``` # foo => bar | baz # ^^^^^^^^^ - # ``` def visit_alternation_pattern_node(node) s(node, :or, visit(node.left), visit(node.right)) end - # ``` # a and b # ^^^^^^^ - # ``` def visit_and_node(node) left = visit(node.left) @@ -84,10 +76,8 @@ def visit_and_node(node) end end - # ``` # [] # ^^ - # ``` def visit_array_node(node) if in_pattern s(node, :array_pat, nil).concat(visit_all(node.elements)) @@ -96,10 +86,8 @@ def visit_array_node(node) end end - # ``` # foo => [bar] # ^^^^^ - # ``` def visit_array_pattern_node(node) if node.constant.nil? && node.requireds.empty? && node.rest.nil? && node.posts.empty? s(node, :array_pat) @@ -121,29 +109,23 @@ def visit_array_pattern_node(node) end end - # ``` # foo(bar) # ^^^ - # ``` def visit_arguments_node(node) raise "Cannot visit arguments directly" end - # ``` # { a: 1 } # ^^^^ - # ``` def visit_assoc_node(node) [visit(node.key), visit(node.value)] end - # ``` # def foo(**); bar(**); end # ^^ # # { **foo } # ^^^^^ - # ``` def visit_assoc_splat_node(node) if node.value.nil? [s(node, :kwsplat)] @@ -152,18 +134,14 @@ def visit_assoc_splat_node(node) end end - # ``` # $+ # ^^ - # ``` def visit_back_reference_read_node(node) s(node, :back_ref, node.name.to_s.delete_prefix("$").to_sym) end - # ``` # begin end # ^^^^^^^^^ - # ``` def visit_begin_node(node) result = node.statements.nil? ? s(node, :nil) : visit(node.statements) @@ -195,20 +173,16 @@ def visit_begin_node(node) result end - # ``` # foo(&bar) # ^^^^ - # ``` def visit_block_argument_node(node) s(node, :block_pass).tap do |result| result << visit(node.expression) unless node.expression.nil? end end - # ``` # foo { |; bar| } # ^^^ - # ``` def visit_block_local_variable_node(node) node.name end @@ -218,10 +192,8 @@ def visit_block_node(node) s(node, :block_pass, visit(node.expression)) end - # ``` # def foo(&bar); end # ^^^^ - # ``` def visit_block_parameter_node(node) :"&#{node.name}" end @@ -262,13 +234,11 @@ def visit_block_parameters_node(node) result end - # ``` # break # ^^^^^ # # break foo # ^^^^^^^^^ - # ``` def visit_break_node(node) if node.arguments.nil? s(node, :break) @@ -279,7 +249,6 @@ def visit_break_node(node) end end - # ``` # foo # ^^^ # @@ -288,7 +257,6 @@ def visit_break_node(node) # # foo.bar() {} # ^^^^^^^^^^^^ - # ``` def visit_call_node(node) case node.name when :!~ @@ -327,10 +295,8 @@ def visit_call_node(node) visit_block(node, result, block) end - # ``` # foo.bar += baz # ^^^^^^^^^^^^^^^ - # ``` def visit_call_operator_write_node(node) if op_asgn?(node) s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.binary_operator) @@ -339,10 +305,8 @@ def visit_call_operator_write_node(node) end end - # ``` # foo.bar &&= baz # ^^^^^^^^^^^^^^^ - # ``` def visit_call_and_write_node(node) if op_asgn?(node) s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"&&") @@ -351,10 +315,8 @@ def visit_call_and_write_node(node) end end - # ``` # foo.bar ||= baz # ^^^^^^^^^^^^^^^ - # ``` def visit_call_or_write_node(node) if op_asgn?(node) s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"||") @@ -376,42 +338,32 @@ def visit_call_or_write_node(node) node.safe_navigation? ? :"safe_#{type}" : type end - # ``` # foo.bar, = 1 # ^^^^^^^ - # ``` def visit_call_target_node(node) s(node, :attrasgn, visit(node.receiver), node.name) end - # ``` # foo => bar => baz # ^^^^^^^^^^ - # ``` def visit_capture_pattern_node(node) visit(node.target) << visit(node.value) end - # ``` # case foo; when bar; end # ^^^^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_case_node(node) s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause) end - # ``` # case foo; in bar; end # ^^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_case_match_node(node) s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause) end - # ``` # class Foo; end # ^^^^^^^^^^^^^^ - # ``` def visit_class_node(node) name = if node.constant_path.is_a?(ConstantReadNode) @@ -434,53 +386,41 @@ def visit_class_node(node) result end - # ``` # @@foo # ^^^^^ - # ``` def visit_class_variable_read_node(node) s(node, :cvar, node.name) end - # ``` # @@foo = 1 # ^^^^^^^^^ # # @@foo, @@bar = 1 # ^^^^^ ^^^^^ - # ``` def visit_class_variable_write_node(node) s(node, class_variable_write_type, node.name, visit_write_value(node.value)) end - # ``` # @@foo += bar # ^^^^^^^^^^^^ - # ``` def visit_class_variable_operator_write_node(node) s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.binary_operator, visit_write_value(node.value))) end - # ``` # @@foo &&= bar # ^^^^^^^^^^^^^ - # ``` def visit_class_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value))) end - # ``` # @@foo ||= bar # ^^^^^^^^^^^^^ - # ``` def visit_class_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value))) end - # ``` # @@foo, = bar # ^^^^^ - # ``` def visit_class_variable_target_node(node) s(node, class_variable_write_type, node.name) end @@ -491,61 +431,47 @@ def visit_class_variable_target_node(node) in_def ? :cvasgn : :cvdecl end - # ``` # Foo # ^^^ - # ``` def visit_constant_read_node(node) s(node, :const, node.name) end - # ``` # Foo = 1 # ^^^^^^^ # # Foo, Bar = 1 # ^^^ ^^^ - # ``` def visit_constant_write_node(node) s(node, :cdecl, node.name, visit_write_value(node.value)) end - # ``` # Foo += bar # ^^^^^^^^^^^ - # ``` def visit_constant_operator_write_node(node) s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value))) end - # ``` # Foo &&= bar # ^^^^^^^^^^^^ - # ``` def visit_constant_and_write_node(node) s(node, :op_asgn_and, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value))) end - # ``` # Foo ||= bar # ^^^^^^^^^^^^ - # ``` def visit_constant_or_write_node(node) s(node, :op_asgn_or, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value))) end - # ``` # Foo, = bar # ^^^ - # ``` def visit_constant_target_node(node) s(node, :cdecl, node.name) end - # ``` # Foo::Bar # ^^^^^^^^ - # ``` def visit_constant_path_node(node) if node.parent.nil? s(node, :colon3, node.name) @@ -554,45 +480,35 @@ def visit_constant_path_node(node) end end - # ``` # Foo::Bar = 1 # ^^^^^^^^^^^^ # # Foo::Foo, Bar::Bar = 1 # ^^^^^^^^ ^^^^^^^^ - # ``` def visit_constant_path_write_node(node) s(node, :cdecl, visit(node.target), visit_write_value(node.value)) end - # ``` # Foo::Bar += baz # ^^^^^^^^^^^^^^^ - # ``` def visit_constant_path_operator_write_node(node) s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value)) end - # ``` # Foo::Bar &&= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_constant_path_and_write_node(node) s(node, :op_asgn_and, visit(node.target), visit_write_value(node.value)) end - # ``` # Foo::Bar ||= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_constant_path_or_write_node(node) s(node, :op_asgn_or, visit(node.target), visit_write_value(node.value)) end - # ``` # Foo::Bar, = baz # ^^^^^^^^ - # ``` def visit_constant_path_target_node(node) inner = if node.parent.nil? @@ -604,13 +520,11 @@ def visit_constant_path_target_node(node) s(node, :const, inner) end - # ``` # def foo; end # ^^^^^^^^^^^^ # # def self.foo; end # ^^^^^^^^^^^^^^^^^ - # ``` def visit_def_node(node) name = node.name_loc.slice.to_sym result = @@ -639,71 +553,55 @@ def visit_def_node(node) end end - # ``` # defined? a # ^^^^^^^^^^ # # defined?(a) # ^^^^^^^^^^^ - # ``` def visit_defined_node(node) s(node, :defined, visit(node.value)) end - # ``` # if foo then bar else baz end # ^^^^^^^^^^^^ - # ``` def visit_else_node(node) visit(node.statements) end - # ``` # "foo #{bar}" # ^^^^^^ - # ``` def visit_embedded_statements_node(node) result = s(node, :evstr) result << visit(node.statements) unless node.statements.nil? result end - # ``` # "foo #@bar" # ^^^^^ - # ``` def visit_embedded_variable_node(node) s(node, :evstr, visit(node.variable)) end - # ``` # begin; foo; ensure; bar; end # ^^^^^^^^^^^^ - # ``` def visit_ensure_node(node) node.statements.nil? ? s(node, :nil) : visit(node.statements) end - # ``` # false # ^^^^^ - # ``` def visit_false_node(node) s(node, :false) end - # ``` # foo => [*, bar, *] # ^^^^^^^^^^^ - # ``` def visit_find_pattern_node(node) s(node, :find_pat, visit_pattern_constant(node.constant), :"*#{node.left.expression&.name}", *visit_all(node.requireds), :"*#{node.right.expression&.name}") end - # ``` # if foo .. bar; end # ^^^^^^^^^^ - # ``` def visit_flip_flop_node(node) if node.left.is_a?(IntegerNode) && node.right.is_a?(IntegerNode) s(node, :lit, Range.new(node.left.value, node.right.value, node.exclude_end?)) @@ -712,112 +610,86 @@ def visit_flip_flop_node(node) end end - # ``` # 1.0 # ^^^ - # ``` def visit_float_node(node) s(node, :lit, node.value) end - # ``` # for foo in bar do end # ^^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_for_node(node) s(node, :for, visit(node.collection), visit(node.index), visit(node.statements)) end - # ``` # def foo(...); bar(...); end # ^^^ - # ``` def visit_forwarding_arguments_node(node) s(node, :forward_args) end - # ``` # def foo(...); end # ^^^ - # ``` def visit_forwarding_parameter_node(node) s(node, :forward_args) end - # ``` # super # ^^^^^ # # super {} # ^^^^^^^^ - # ``` def visit_forwarding_super_node(node) visit_block(node, s(node, :zsuper), node.block) end - # ``` # $foo # ^^^^ - # ``` def visit_global_variable_read_node(node) s(node, :gvar, node.name) end - # ``` # $foo = 1 # ^^^^^^^^ # # $foo, $bar = 1 # ^^^^ ^^^^ - # ``` def visit_global_variable_write_node(node) s(node, :gasgn, node.name, visit_write_value(node.value)) end - # ``` # $foo += bar # ^^^^^^^^^^^ - # ``` def visit_global_variable_operator_write_node(node) s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value))) end - # ``` # $foo &&= bar # ^^^^^^^^^^^^ - # ``` def visit_global_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value))) end - # ``` # $foo ||= bar # ^^^^^^^^^^^^ - # ``` def visit_global_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value))) end - # ``` # $foo, = bar # ^^^^ - # ``` def visit_global_variable_target_node(node) s(node, :gasgn, node.name) end - # ``` # {} # ^^ - # ``` def visit_hash_node(node) s(node, :hash).concat(node.elements.flat_map { |element| visit(element) }) end - # ``` # foo => {} # ^^ - # ``` def visit_hash_pattern_node(node) result = s(node, :hash_pat, visit_pattern_constant(node.constant)).concat(node.elements.flat_map { |element| visit(element) }) @@ -831,7 +703,6 @@ def visit_hash_pattern_node(node) result end - # ``` # if foo then bar end # ^^^^^^^^^^^^^^^^^^^ # @@ -840,7 +711,6 @@ def visit_hash_pattern_node(node) # # foo ? bar : baz # ^^^^^^^^^^^^^^^ - # ``` def visit_if_node(node) s(node, :if, visit(node.predicate), visit(node.statements), visit(node.subsequent)) end @@ -850,24 +720,18 @@ def visit_imaginary_node(node) s(node, :lit, node.value) end - # ``` # { foo: } # ^^^^ - # ``` def visit_implicit_node(node) end - # ``` # foo { |bar,| } # ^ - # ``` def visit_implicit_rest_node(node) end - # ``` # case foo; in bar; end # ^^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_in_node(node) pattern = if node.pattern.is_a?(ConstantPathNode) @@ -879,10 +743,8 @@ def visit_in_node(node) s(node, :in, pattern).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) end - # ``` # foo[bar] += baz # ^^^^^^^^^^^^^^^ - # ``` def visit_index_operator_write_node(node) arglist = nil @@ -894,10 +756,8 @@ def visit_index_operator_write_node(node) s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value)) end - # ``` # foo[bar] &&= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_index_and_write_node(node) arglist = nil @@ -909,10 +769,8 @@ def visit_index_and_write_node(node) s(node, :op_asgn1, visit(node.receiver), arglist, :"&&", visit_write_value(node.value)) end - # ``` # foo[bar] ||= baz # ^^^^^^^^^^^^^^^^ - # ``` def visit_index_or_write_node(node) arglist = nil @@ -924,10 +782,8 @@ def visit_index_or_write_node(node) s(node, :op_asgn1, visit(node.receiver), arglist, :"||", visit_write_value(node.value)) end - # ``` # foo[bar], = 1 # ^^^^^^^^ - # ``` def visit_index_target_node(node) arguments = visit_all(node.arguments&.arguments || []) arguments << visit(node.block) unless node.block.nil? @@ -935,69 +791,53 @@ def visit_index_target_node(node) s(node, :attrasgn, visit(node.receiver), :[]=).concat(arguments) end - # ``` # @foo # ^^^^ - # ``` def visit_instance_variable_read_node(node) s(node, :ivar, node.name) end - # ``` # @foo = 1 # ^^^^^^^^ # # @foo, @bar = 1 # ^^^^ ^^^^ - # ``` def visit_instance_variable_write_node(node) s(node, :iasgn, node.name, visit_write_value(node.value)) end - # ``` # @foo += bar # ^^^^^^^^^^^ - # ``` def visit_instance_variable_operator_write_node(node) s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value))) end - # ``` # @foo &&= bar # ^^^^^^^^^^^^ - # ``` def visit_instance_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value))) end - # ``` # @foo ||= bar # ^^^^^^^^^^^^ - # ``` def visit_instance_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value))) end - # ``` # @foo, = bar # ^^^^ - # ``` def visit_instance_variable_target_node(node) s(node, :iasgn, node.name) end - # ``` # 1 # ^ - # ``` def visit_integer_node(node) s(node, :lit, node.value) end - # ``` # if /foo #{bar}/ then end # ^^^^^^^^^^^^ - # ``` def visit_interpolated_match_last_line_node(node) parts = visit_interpolated_parts(node.parts) regexp = @@ -1013,10 +853,8 @@ def visit_interpolated_match_last_line_node(node) s(node, :match, regexp) end - # ``` # /foo #{bar}/ # ^^^^^^^^^^^^ - # ``` def visit_interpolated_regular_expression_node(node) parts = visit_interpolated_parts(node.parts) @@ -1030,28 +868,22 @@ def visit_interpolated_regular_expression_node(node) end end - # ``` # "foo #{bar}" # ^^^^^^^^^^^^ - # ``` def visit_interpolated_string_node(node) parts = visit_interpolated_parts(node.parts) parts.length == 1 ? s(node, :str, parts.first) : s(node, :dstr).concat(parts) end - # ``` # :"foo #{bar}" # ^^^^^^^^^^^^^ - # ``` def visit_interpolated_symbol_node(node) parts = visit_interpolated_parts(node.parts) parts.length == 1 ? s(node, :lit, parts.first.to_sym) : s(node, :dsym).concat(parts) end - # ``` # `foo #{bar}` # ^^^^^^^^^^^^ - # ``` def visit_interpolated_x_string_node(node) source = node.heredoc? ? node.parts.first : node parts = visit_interpolated_parts(node.parts) @@ -1131,29 +963,23 @@ def visit_interpolated_x_string_node(node) results end - # ``` # -> { it } # ^^ - # ``` def visit_it_local_variable_read_node(node) s(node, :call, nil, :it) end - # ``` # foo(bar: baz) # ^^^^^^^^ - # ``` def visit_keyword_hash_node(node) s(node, :hash).concat(node.elements.flat_map { |element| visit(element) }) end - # ``` # def foo(**bar); end # ^^^^^ # # def foo(**); end # ^^ - # ``` def visit_keyword_rest_parameter_node(node) :"**#{node.name}" end @@ -1175,10 +1001,8 @@ def visit_lambda_node(node) end end - # ``` # foo # ^^^ - # ``` def visit_local_variable_read_node(node) if node.name.match?(/^_\d$/) s(node, :call, nil, node.name) @@ -1187,77 +1011,59 @@ def visit_local_variable_read_node(node) end end - # ``` # foo = 1 # ^^^^^^^ # # foo, bar = 1 # ^^^ ^^^ - # ``` def visit_local_variable_write_node(node) s(node, :lasgn, node.name, visit_write_value(node.value)) end - # ``` # foo += bar # ^^^^^^^^^^ - # ``` def visit_local_variable_operator_write_node(node) s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value))) end - # ``` # foo &&= bar # ^^^^^^^^^^^ - # ``` def visit_local_variable_and_write_node(node) s(node, :op_asgn_and, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value))) end - # ``` # foo ||= bar # ^^^^^^^^^^^ - # ``` def visit_local_variable_or_write_node(node) s(node, :op_asgn_or, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value))) end - # ``` # foo, = bar # ^^^ - # ``` def visit_local_variable_target_node(node) s(node, :lasgn, node.name) end - # ``` # if /foo/ then end # ^^^^^ - # ``` def visit_match_last_line_node(node) s(node, :match, s(node, :lit, Regexp.new(node.unescaped, node.options))) end - # ``` # foo in bar # ^^^^^^^^^^ - # ``` def visit_match_predicate_node(node) s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil) end - # ``` # foo => bar # ^^^^^^^^^^ - # ``` def visit_match_required_node(node) s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil) end - # ``` # /(?foo)/ =~ bar # ^^^^^^^^^^^^^^^^^^^^ - # ``` def visit_match_write_node(node) s(node, :match2, visit(node.call.receiver), visit(node.call.arguments.arguments.first)) end @@ -1269,10 +1075,8 @@ def visit_missing_node(node) raise "Cannot visit missing node directly" end - # ``` # module Foo; end # ^^^^^^^^^^^^^^^ - # ``` def visit_module_node(node) name = if node.constant_path.is_a?(ConstantReadNode) @@ -1295,10 +1099,8 @@ def visit_module_node(node) result end - # ``` # foo, bar = baz # ^^^^^^^^ - # ``` def visit_multi_target_node(node) targets = [*node.lefts] targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) @@ -1307,10 +1109,8 @@ def visit_multi_target_node(node) s(node, :masgn, s(node, :array).concat(visit_all(targets))) end - # ``` # foo, bar = baz # ^^^^^^^^^^^^^^ - # ``` def visit_multi_write_node(node) targets = [*node.lefts] targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) @@ -1330,13 +1130,11 @@ def visit_multi_write_node(node) s(node, :masgn, s(node, :array).concat(visit_all(targets)), value) end - # ``` # next # ^^^^ # # next foo # ^^^^^^^^ - # ``` def visit_next_node(node) if node.arguments.nil? s(node, :next) @@ -1348,58 +1146,44 @@ def visit_next_node(node) end end - # ``` # nil # ^^^ - # ``` def visit_nil_node(node) s(node, :nil) end - # ``` # def foo(**nil); end # ^^^^^ - # ``` def visit_no_keywords_parameter_node(node) in_pattern ? s(node, :kwrest, :"**nil") : :"**nil" end - # ``` # -> { _1 + _2 } # ^^^^^^^^^^^^^^ - # ``` def visit_numbered_parameters_node(node) raise "Cannot visit numbered parameters directly" end - # ``` # $1 # ^^ - # ``` def visit_numbered_reference_read_node(node) s(node, :nth_ref, node.number) end - # ``` # def foo(bar: baz); end # ^^^^^^^^ - # ``` def visit_optional_keyword_parameter_node(node) s(node, :kwarg, node.name, visit(node.value)) end - # ``` # def foo(bar = 1); end # ^^^^^^^ - # ``` def visit_optional_parameter_node(node) s(node, :lasgn, node.name, visit(node.value)) end - # ``` # a or b # ^^^^^^ - # ``` def visit_or_node(node) left = visit(node.left) @@ -1416,10 +1200,8 @@ def visit_or_node(node) end end - # ``` # def foo(bar, *baz); end # ^^^^^^^^^ - # ``` def visit_parameters_node(node) children = node.each_child_node.map do |element| @@ -1433,10 +1215,8 @@ def visit_parameters_node(node) s(node, :args).concat(children) end - # ``` # def foo((bar, baz)); end # ^^^^^^^^^^ - # ``` private def visit_destructured_parameter(node) children = [*node.lefts, *node.rest, *node.rights].map do |child| @@ -1455,13 +1235,11 @@ def visit_parameters_node(node) s(node, :masgn).concat(children) end - # ``` # () # ^^ # # (1) # ^^^ - # ``` def visit_parentheses_node(node) if node.body.nil? s(node, :nil) @@ -1470,18 +1248,14 @@ def visit_parentheses_node(node) end end - # ``` # foo => ^(bar) # ^^^^^^ - # ``` def visit_pinned_expression_node(node) node.expression.accept(copy_compiler(in_pattern: false)) end - # ``` # foo = 1 and bar => ^foo # ^^^^ - # ``` def visit_pinned_variable_node(node) if node.variable.is_a?(LocalVariableReadNode) && node.variable.name.match?(/^_\d$/) s(node, :lvar, node.variable.name) @@ -1505,10 +1279,8 @@ def visit_program_node(node) visit(node.statements) end - # ``` # 0..5 # ^^^^ - # ``` def visit_range_node(node) if !in_pattern && !node.left.nil? && !node.right.nil? && ([node.left.type, node.right.type] - %i[nil_node integer_node]).empty? left = node.left.value if node.left.is_a?(IntegerNode) @@ -1529,58 +1301,44 @@ def visit_range_node(node) end end - # ``` # 1r # ^^ - # ``` def visit_rational_node(node) s(node, :lit, node.value) end - # ``` # redo # ^^^^ - # ``` def visit_redo_node(node) s(node, :redo) end - # ``` # /foo/ # ^^^^^ - # ``` def visit_regular_expression_node(node) s(node, :lit, Regexp.new(node.unescaped, node.options)) end - # ``` # def foo(bar:); end # ^^^^ - # ``` def visit_required_keyword_parameter_node(node) s(node, :kwarg, node.name) end - # ``` # def foo(bar); end # ^^^ - # ``` def visit_required_parameter_node(node) node.name end - # ``` # foo rescue bar # ^^^^^^^^^^^^^^ - # ``` def visit_rescue_modifier_node(node) s(node, :rescue, visit(node.expression), s(node.rescue_expression, :resbody, s(node.rescue_expression, :array), visit(node.rescue_expression))) end - # ``` # begin; rescue; end # ^^^^^^^ - # ``` def visit_rescue_node(node) exceptions = if node.exceptions.length == 1 && node.exceptions.first.is_a?(SplatNode) @@ -1596,32 +1354,26 @@ def visit_rescue_node(node) s(node, :resbody, exceptions).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) end - # ``` # def foo(*bar); end # ^^^^ # # def foo(*); end # ^ - # ``` def visit_rest_parameter_node(node) :"*#{node.name}" end - # ``` # retry # ^^^^^ - # ``` def visit_retry_node(node) s(node, :retry) end - # ``` # return # ^^^^^^ # # return 1 # ^^^^^^^^ - # ``` def visit_return_node(node) if node.arguments.nil? s(node, :return) @@ -1633,10 +1385,8 @@ def visit_return_node(node) end end - # ``` # self # ^^^^ - # ``` def visit_self_node(node) s(node, :self) end @@ -1646,42 +1396,33 @@ def visit_shareable_constant_node(node) visit(node.write) end - # ``` # class << self; end # ^^^^^^^^^^^^^^^^^^ - # ``` def visit_singleton_class_node(node) s(node, :sclass, visit(node.expression)).tap do |sexp| sexp << node.body.accept(copy_compiler(in_def: false)) unless node.body.nil? end end - # ``` # __ENCODING__ # ^^^^^^^^^^^^ - # ``` def visit_source_encoding_node(node) # TODO s(node, :colon2, s(node, :const, :Encoding), :UTF_8) end - # ``` # __FILE__ # ^^^^^^^^ - # ``` def visit_source_file_node(node) s(node, :str, node.filepath) end - # ``` # __LINE__ # ^^^^^^^^ - # ``` def visit_source_line_node(node) s(node, :lit, node.location.start_line) end - # ``` # foo(*bar) # ^^^^ # @@ -1690,7 +1431,6 @@ def visit_source_line_node(node) # # def foo(*); bar(*); end # ^ - # ``` def visit_splat_node(node) if node.expression.nil? s(node, :splat) @@ -1710,10 +1450,8 @@ def visit_statements_node(node) end end - # ``` # "foo" # ^^^^^ - # ``` def visit_string_node(node) unescaped = node.unescaped @@ -1725,10 +1463,8 @@ def visit_string_node(node) s(node, :str, unescaped) end - # ``` # super(foo) # ^^^^^^^^^^ - # ``` def visit_super_node(node) arguments = node.arguments&.arguments || [] block = node.block @@ -1741,76 +1477,60 @@ def visit_super_node(node) visit_block(node, s(node, :super).concat(visit_all(arguments)), block) end - # ``` # :foo # ^^^^ - # ``` def visit_symbol_node(node) node.value == "!@" ? s(node, :lit, :"!@") : s(node, :lit, node.unescaped.to_sym) end - # ``` # true # ^^^^ - # ``` def visit_true_node(node) s(node, :true) end - # ``` # undef foo # ^^^^^^^^^ - # ``` def visit_undef_node(node) names = node.names.map { |name| s(node, :undef, visit(name)) } names.length == 1 ? names.first : s(node, :block).concat(names) end - # ``` # unless foo; bar end # ^^^^^^^^^^^^^^^^^^^ # # bar unless foo # ^^^^^^^^^^^^^^ - # ``` def visit_unless_node(node) s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements)) end - # ``` # until foo; bar end # ^^^^^^^^^^^^^^^^^ # # bar until foo # ^^^^^^^^^^^^^ - # ``` def visit_until_node(node) s(node, :until, visit(node.predicate), visit(node.statements), !node.begin_modifier?) end - # ``` # case foo; when bar; end # ^^^^^^^^^^^^^ - # ``` def visit_when_node(node) s(node, :when, s(node, :array).concat(visit_all(node.conditions))).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) end - # ``` # while foo; bar end # ^^^^^^^^^^^^^^^^^^ # # bar while foo # ^^^^^^^^^^^^^ - # ``` def visit_while_node(node) s(node, :while, visit(node.predicate), visit(node.statements), !node.begin_modifier?) end - # ``` # `foo` # ^^^^^ - # ``` def visit_x_string_node(node) result = s(node, :xstr, node.unescaped) @@ -1822,13 +1542,11 @@ def visit_x_string_node(node) result end - # ``` # yield # ^^^^^ # # yield 1 # ^^^^^^^ - # ``` def visit_yield_node(node) s(node, :yield).concat(visit_all(node.arguments&.arguments || [])) end From 7f5782392ee98cf2ce6f43e3521b826f89ea0ba0 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 19 Feb 2026 10:31:26 +0100 Subject: [PATCH 041/289] Implement noblock for the ripper/ruby_parser translator In ripper, compared to `**nil` it is not a new event --- lib/prism/translation/ripper.rb | 7 ++++++ lib/prism/translation/ruby_parser.rb | 6 +++++ test/prism/ruby/parser_test.rb | 33 ++++++++++++++++++++-------- test/prism/ruby/ripper_test.rb | 3 --- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index 2a3eaa4001..d1c28a2401 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -2623,6 +2623,13 @@ def visit_nil_node(node) on_var_ref(on_kw("nil")) end + # def foo(&nil); end + # ^^^^ + def visit_no_block_parameter_node(node) + bounds(node.location) + on_blockarg(:nil) + end + # def foo(**nil); end # ^^^^^ def visit_no_keywords_parameter_node(node) diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb index 3ba892634f..c1fb8adfc1 100644 --- a/lib/prism/translation/ruby_parser.rb +++ b/lib/prism/translation/ruby_parser.rb @@ -1152,6 +1152,12 @@ def visit_nil_node(node) s(node, :nil) end + # def foo(&nil); end + # ^^^^ + def visit_no_block_parameter_node(node) + :"&nil" + end + # def foo(**nil); end # ^^^^^ def visit_no_keywords_parameter_node(node) diff --git a/test/prism/ruby/parser_test.rb b/test/prism/ruby/parser_test.rb index 55c12cab6f..ad9fa0c92c 100644 --- a/test/prism/ruby/parser_test.rb +++ b/test/prism/ruby/parser_test.rb @@ -187,13 +187,7 @@ def test_invalid_syntax end def test_it_block_parameter_syntax - it_fixture_path = Pathname(__dir__).join("../../../test/prism/fixtures/3.4/it.txt") - - buffer = Parser::Source::Buffer.new(it_fixture_path) - buffer.source = it_fixture_path.read - actual_ast = Prism::Translation::Parser34.new.tokenize(buffer)[0] - - it_block_parameter_sexp = parse_sexp { + assert_new_syntax("3.4/it.txt", Prism::Translation::Parser34) do s(:begin, s(:itblock, s(:send, nil, :x), :it, @@ -201,9 +195,20 @@ def test_it_block_parameter_syntax s(:itblock, s(:lambda), :it, s(:lvar, :it))) - } + end + end - assert_equal(it_block_parameter_sexp, actual_ast.to_sexp) + def test_nil_block_parameter_syntax + assert_new_syntax("4.1/noblock.txt", Prism::Translation::Parser41) do + s(:begin, + s(:def, :foo, + s(:args, + s(:blocknilarg)), nil), + s(:block, + s(:lambda), + s(:args, + s(:blocknilarg)), nil)) + end end private @@ -301,6 +306,16 @@ def assert_equal_comments(expected_comments, actual_comments) } end + def assert_new_syntax(path, parser, &sexp) + fixture_path = Pathname(__dir__).join("../../../test/prism/fixtures", path) + + buffer = Parser::Source::Buffer.new(fixture_path) + buffer.source = fixture_path.read + actual_ast = parser.new.tokenize(buffer)[0] + + assert_equal(parse_sexp(&sexp), actual_ast.to_sexp) + end + def parse_sexp(&block) Class.new { extend AST::Sexp }.instance_eval(&block).to_sexp end diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index 00cf470e0e..39cb9395ab 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -40,9 +40,6 @@ class RipperTest < TestCase # https://bugs.ruby-lang.org/issues/21669 incorrect << "4.1/void_value.txt" - # https://bugs.ruby-lang.org/issues/19979 - incorrect << "4.1/noblock.txt" - # Skip these tests that we haven't implemented yet. omitted_sexp_raw = [ "bom_leading_space.txt", From 4ba7fb604e077d65cd7d99ceb05dca305a75d647 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:31:40 +0100 Subject: [PATCH 042/289] remove `ruby_memcheck` from version gemfiles It's not used, it's already present in the main gemfile. Also remove minitest dep from typechecking. --- gemfiles/3.0/Gemfile | 1 - gemfiles/3.0/Gemfile.lock | 7 ------- gemfiles/3.1/Gemfile | 1 - gemfiles/3.1/Gemfile.lock | 7 ------- gemfiles/3.2/Gemfile | 1 - gemfiles/3.2/Gemfile.lock | 7 ------- gemfiles/3.3/Gemfile | 1 - gemfiles/3.3/Gemfile.lock | 7 ------- gemfiles/3.4/Gemfile | 1 - gemfiles/3.4/Gemfile.lock | 7 ------- gemfiles/4.0/Gemfile | 2 -- gemfiles/4.0/Gemfile.lock | 9 --------- gemfiles/4.1/Gemfile | 1 - gemfiles/4.1/Gemfile.lock | 7 ------- gemfiles/typecheck/Gemfile | 1 - gemfiles/typecheck/Gemfile.lock | 1 - 16 files changed, 61 deletions(-) diff --git a/gemfiles/3.0/Gemfile b/gemfiles/3.0/Gemfile index 4000b519d1..c5600d20f0 100644 --- a/gemfiles/3.0/Gemfile +++ b/gemfiles/3.0/Gemfile @@ -10,6 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.0/Gemfile.lock b/gemfiles/3.0/Gemfile.lock index 5a50ce8765..532d7e61f7 100644 --- a/gemfiles/3.0/Gemfile.lock +++ b/gemfiles/3.0/Gemfile.lock @@ -7,10 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - mini_portile2 (2.8.9) - nokogiri (1.17.2) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) parser (3.3.10.1) ast (~> 2.4.1) @@ -20,8 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.21.1) racc (~> 1.5) sexp_processor (~> 4.16) @@ -38,7 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.1/Gemfile b/gemfiles/3.1/Gemfile index b88e0925f1..6f7e7b6a28 100644 --- a/gemfiles/3.1/Gemfile +++ b/gemfiles/3.1/Gemfile @@ -10,6 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.1/Gemfile.lock b/gemfiles/3.1/Gemfile.lock index 31f225440a..ed479ba08d 100644 --- a/gemfiles/3.1/Gemfile.lock +++ b/gemfiles/3.1/Gemfile.lock @@ -7,10 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - mini_portile2 (2.8.9) - nokogiri (1.18.10) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) parser (3.3.10.1) ast (~> 2.4.1) @@ -20,8 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.21.1) racc (~> 1.5) sexp_processor (~> 4.16) @@ -38,7 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.2/Gemfile b/gemfiles/3.2/Gemfile index 527f61bd5c..7d82c2b76a 100644 --- a/gemfiles/3.2/Gemfile +++ b/gemfiles/3.2/Gemfile @@ -10,6 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.2/Gemfile.lock b/gemfiles/3.2/Gemfile.lock index e76d556607..b1b1a89735 100644 --- a/gemfiles/3.2/Gemfile.lock +++ b/gemfiles/3.2/Gemfile.lock @@ -7,10 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) parser (3.3.10.1) ast (~> 2.4.1) @@ -20,8 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -38,7 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.3/Gemfile b/gemfiles/3.3/Gemfile index 557302757f..f78c4cc9a2 100644 --- a/gemfiles/3.3/Gemfile +++ b/gemfiles/3.3/Gemfile @@ -10,6 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.3/Gemfile.lock b/gemfiles/3.3/Gemfile.lock index cd6f04e894..7227459626 100644 --- a/gemfiles/3.3/Gemfile.lock +++ b/gemfiles/3.3/Gemfile.lock @@ -7,10 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) parser (3.3.10.1) ast (~> 2.4.1) @@ -20,8 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -38,7 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/3.4/Gemfile b/gemfiles/3.4/Gemfile index 260ced90ac..c1b19d7d53 100644 --- a/gemfiles/3.4/Gemfile +++ b/gemfiles/3.4/Gemfile @@ -10,6 +10,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/3.4/Gemfile.lock b/gemfiles/3.4/Gemfile.lock index 715b6ade14..56910904e1 100644 --- a/gemfiles/3.4/Gemfile.lock +++ b/gemfiles/3.4/Gemfile.lock @@ -7,10 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) parser (3.3.10.1) ast (~> 2.4.1) @@ -20,8 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -38,7 +32,6 @@ DEPENDENCIES prism! rake rake-compiler - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/4.0/Gemfile b/gemfiles/4.0/Gemfile index 660d3ce929..538073fb0e 100644 --- a/gemfiles/4.0/Gemfile +++ b/gemfiles/4.0/Gemfile @@ -6,11 +6,9 @@ ruby "~> 4.0.0" gemspec path: "../.." -gem "ffi" gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/4.0/Gemfile.lock b/gemfiles/4.0/Gemfile.lock index 34273e8ff4..3cf2bf99ab 100644 --- a/gemfiles/4.0/Gemfile.lock +++ b/gemfiles/4.0/Gemfile.lock @@ -7,11 +7,6 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.3) - ffi (1.17.3) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) parser (3.3.10.1) ast (~> 2.4.1) @@ -21,8 +16,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -34,13 +27,11 @@ PLATFORMS ruby DEPENDENCIES - ffi onigmo parser prism! rake rake-compiler - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/4.1/Gemfile b/gemfiles/4.1/Gemfile index 3ad947d147..8beda3da54 100644 --- a/gemfiles/4.1/Gemfile +++ b/gemfiles/4.1/Gemfile @@ -11,6 +11,5 @@ gem "onigmo", platforms: :ruby gem "parser" gem "rake-compiler" gem "rake" -gem "ruby_memcheck" gem "ruby_parser" gem "test-unit" diff --git a/gemfiles/4.1/Gemfile.lock b/gemfiles/4.1/Gemfile.lock index 4dd58fb002..62a55c4f79 100644 --- a/gemfiles/4.1/Gemfile.lock +++ b/gemfiles/4.1/Gemfile.lock @@ -8,10 +8,6 @@ GEM specs: ast (2.4.3) ffi (1.17.3) - mini_portile2 (2.8.9) - nokogiri (1.19.0) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) onigmo (0.1.0) parser (3.3.10.1) ast (~> 2.4.1) @@ -21,8 +17,6 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - ruby_memcheck (3.0.1) - nokogiri ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) @@ -40,7 +34,6 @@ DEPENDENCIES prism! rake rake-compiler - ruby_memcheck ruby_parser test-unit diff --git a/gemfiles/typecheck/Gemfile b/gemfiles/typecheck/Gemfile index 7d552d2404..951dc83e3d 100644 --- a/gemfiles/typecheck/Gemfile +++ b/gemfiles/typecheck/Gemfile @@ -2,7 +2,6 @@ source "https://rubygems.org" -gem "minitest" gem "parser" gem "rake-compiler" gem "rake" diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index d880e049a5..8ebb8670e7 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -127,7 +127,6 @@ PLATFORMS x86_64-linux DEPENDENCIES - minitest parser rake rake-compiler From bd0a4e734c2d68f41fae83e96c378988ca67af15 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 21 Jan 2026 17:00:41 -0600 Subject: [PATCH 043/289] Update group and artifact for publishing org.jruby:chicory-prism --- java-wasm/pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index d8a360d57b..e8941738c1 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -2,11 +2,11 @@ 4.0.0 - com.prism - java-prism - 999-SNAPSHOT + org.jruby + chicory-prism + 0.0.1-SNAPSHOT Java Prism - Pure Java Prism interpreting WASM + Pure Java Prism using Chicory WASM runtime From e8fd0a44493e05f61bec08e008e734a6e59c8227 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 21 Jan 2026 17:01:28 -0600 Subject: [PATCH 044/289] Add JRuby dependency for building parser API Nodes need access to RubySymbol and support APIs at least. --- java-wasm/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index e8941738c1..6bdb4981bf 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -59,6 +59,11 @@ annotations provided + + org.jruby + jruby-base + 10.0.2.0 + From 380b0804ff6d2c0d1b9bef7b9d85329b116d3198 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 21 Jan 2026 19:24:17 -0600 Subject: [PATCH 045/289] Move java_wasm output to src/main/resources * It is a resource used as source code (in wasm) that is compiled for the project artifact. * Added to Rake CLOBBER --- .github/workflows/java-wasm-bindings.yml | 2 +- Makefile | 5 +++-- Rakefile | 1 + java-wasm/pom.xml | 4 ++-- .../src/main/java-templates/org/prism/WasmResource.java | 2 +- java-wasm/src/{test => main}/resources/.gitignore | 0 6 files changed, 8 insertions(+), 6 deletions(-) rename java-wasm/src/{test => main}/resources/.gitignore (100%) diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 3a0a066334..5d130c07e1 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -48,4 +48,4 @@ jobs: - uses: actions/upload-artifact@v6 with: name: prism.wasm - path: java-wasm/src/test/resources/prism.wasm + path: java-wasm/src/main/resources/prism.wasm diff --git a/Makefile b/Makefile index da6b96a000..cefc199a52 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ all: shared static shared: build/libprism.$(SOEXT) static: build/libprism.a wasm: javascript/src/prism.wasm -java-wasm: java-wasm/src/test/resources/prism.wasm +java-wasm: java-wasm/src/main/resources/prism.wasm build/libprism.$(SOEXT): $(SHARED_OBJECTS) $(ECHO) "linking $@ with $(CC)" @@ -51,8 +51,9 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) -Oz -g0 -flto -fdata-sections -ffunction-sections \ -o $@ $(SOURCES) -java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) +java-wasm/src/main/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) $(ECHO) "building $@" + $(Q) $(MAKEDIRS) $(@D) $(Q) $(WASI_SDK_PATH)/bin/clang $(DEBUG_FLAGS) -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(JAVA_WASM_CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi -o $@ $(SOURCES) build/shared/%.o: src/%.c Makefile $(HEADERS) diff --git a/Rakefile b/Rakefile index b06877107e..6e79e08b7f 100644 --- a/Rakefile +++ b/Rakefile @@ -55,6 +55,7 @@ end CLOBBER.concat(Prism::Template::TEMPLATES) CLOBBER.concat(["build"]) CLOBBER << "lib/prism/prism.#{RbConfig::CONFIG["DLEXT"]}" +CLOBBER << "java-wasm/src/main/resources/prism.wasm" Prism::Template::TEMPLATES.each do |filepath| desc "Generate #{filepath}" diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 6bdb4981bf..c5d7b3e030 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -130,8 +130,8 @@ compile - org.prism.PrismModule - src/test/resources/prism.wasm + org.prism.Prism + src/main/resources/prism.wasm diff --git a/java-wasm/src/main/java-templates/org/prism/WasmResource.java b/java-wasm/src/main/java-templates/org/prism/WasmResource.java index 48f2671714..ccf1d0bcdd 100644 --- a/java-wasm/src/main/java-templates/org/prism/WasmResource.java +++ b/java-wasm/src/main/java-templates/org/prism/WasmResource.java @@ -1,7 +1,7 @@ package org.prism; public final class WasmResource { - public static final String absoluteFile = "file://${project.basedir}/src/test/resources/prism.wasm"; + public static final String absoluteFile = "file://${project.basedir}/src/main/resources/prism.wasm"; private WasmResource() {} } diff --git a/java-wasm/src/test/resources/.gitignore b/java-wasm/src/main/resources/.gitignore similarity index 100% rename from java-wasm/src/test/resources/.gitignore rename to java-wasm/src/main/resources/.gitignore From cd5f68a83fbe82f01ef18e94e2e09958e0735992 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 21 Jan 2026 19:26:47 -0600 Subject: [PATCH 046/289] Add basic bootstrapping instructions --- java-wasm/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 java-wasm/README.md diff --git a/java-wasm/README.md b/java-wasm/README.md new file mode 100644 index 0000000000..2ff93a66d7 --- /dev/null +++ b/java-wasm/README.md @@ -0,0 +1,23 @@ +This dir contains the chicory-prism artifact, a version of prism compiled to WASM and then AOT compiled to JVM bytecode by the Chicory project. + +Generate the templated sources: + +``` +PRISM_EXCLUDE_PRETTYPRINT=1 PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 PRISM_JAVA_BACKEND=jruby bundle exec rake templates +``` + +Compile to WASM using WASI SDK version 25: + +``` +make java-wasm WASI_SDK_PATH=.../wasi-sdk-25.0-arm64-macos +``` + +Build the AOT-compiled machine and wrapper library: + +``` +mvn -f java-wasm/pom.xml clean package +``` + +This should build the chicory-wasm jar file and pass some basic tests. + +The jar will be under `java-wasm/target/chicory-prism-#####-SNAPSHOT.jar` or can be installed by using `install` instead of `pacakge` in the `mvn` command line above. From 340c6ed5e44e82b37812cbb978e8bddc42eec54b Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 22 Jan 2026 01:17:12 -0600 Subject: [PATCH 047/289] Upgrade to chicory 1.6.1 --- java-wasm/pom.xml | 2 +- java-wasm/src/main/java/org/prism/Prism.java | 9 ++++++--- java-wasm/src/test/resources/prism.wasm | Bin 0 -> 668333 bytes 3 files changed, 7 insertions(+), 4 deletions(-) create mode 100755 java-wasm/src/test/resources/prism.wasm diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index c5d7b3e030..45f5eb71fc 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -130,7 +130,7 @@ compile - org.prism.Prism + org.prism.PrismParser src/main/resources/prism.wasm diff --git a/java-wasm/src/main/java/org/prism/Prism.java b/java-wasm/src/main/java/org/prism/Prism.java index 9578a441a1..ba13f18aed 100644 --- a/java-wasm/src/main/java/org/prism/Prism.java +++ b/java-wasm/src/main/java/org/prism/Prism.java @@ -1,11 +1,12 @@ package org.prism; -import com.dylibso.chicory.runtime.ByteArrayMemory; import com.dylibso.chicory.annotations.WasmModuleInterface; +import com.dylibso.chicory.runtime.ByteArrayMemory; import com.dylibso.chicory.runtime.ImportValues; import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasi.WasiOptions; import com.dylibso.chicory.wasi.WasiPreview1; +import com.dylibso.chicory.wasm.WasmModule; import com.dylibso.chicory.wasm.types.MemoryLimits; import java.nio.charset.StandardCharsets; @@ -21,9 +22,11 @@ public Prism() { } public Prism(WasiOptions wasiOpts) { wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - instance = Instance.builder(PrismModule.load()) + WasmModule module = PrismParser.load(); + PrismParser parser = new PrismParser(); + instance = Instance.builder(module) .withMemoryFactory(limits -> new ByteArrayMemory(new MemoryLimits(10, MemoryLimits.MAX_PAGES))) - .withMachineFactory(PrismModule::create) + .withMachineFactory(parser.machineFactory()) .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) .build(); exports = new Prism_ModuleExports(instance); diff --git a/java-wasm/src/test/resources/prism.wasm b/java-wasm/src/test/resources/prism.wasm new file mode 100755 index 0000000000000000000000000000000000000000..6d712590fc3e6c7c539131271e344beb0aafda18 GIT binary patch literal 668333 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�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%0Dh+gqo?7SnR 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 AxBvhE literal 0 HcmV?d00001 From 26d1597bda21b88a83feb146a2a5ebd9e2152d95 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Sun, 25 Jan 2026 17:25:27 -0600 Subject: [PATCH 048/289] Simplify setup and teardown Allow the buffer functions to manage the internal pointer and use consistent argument order for calloc. --- java-wasm/src/main/java/org/prism/Prism.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/java-wasm/src/main/java/org/prism/Prism.java b/java-wasm/src/main/java/org/prism/Prism.java index ba13f18aed..51552569e6 100644 --- a/java-wasm/src/main/java/org/prism/Prism.java +++ b/java-wasm/src/main/java/org/prism/Prism.java @@ -40,10 +40,9 @@ public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { int sourcePointer = 0; int optionsPointer = 0; int bufferPointer = 0; - int resultPointer = 0; byte[] result; try { - sourcePointer = exports.calloc(1, sourceLength); + sourcePointer = exports.calloc(sourceLength, 1); exports.memory().write(sourcePointer, source); optionsPointer = exports.calloc(1, packedOptions.length); @@ -54,10 +53,8 @@ public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { exports.pmSerializeParse(bufferPointer, sourcePointer, sourceLength, optionsPointer); - resultPointer = exports.pmBufferValue(bufferPointer); - result = instance.memory().readBytes( - resultPointer, + exports.pmBufferValue(bufferPointer), exports.pmBufferLength(bufferPointer)); } finally { if (sourcePointer != 0) { @@ -67,11 +64,9 @@ public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { exports.free(optionsPointer); } if (bufferPointer != 0) { + exports.pmBufferFree(bufferPointer); exports.free(bufferPointer); } - if (resultPointer != 0) { - exports.free(resultPointer); - } } return result; From a5e744586408e931db68e57b05c3180e8e84c4b3 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 26 Jan 2026 12:31:20 -0600 Subject: [PATCH 049/289] Support AOT and interp WASM Primarily for testing purposes. --- java-wasm/src/main/java/org/prism/Prism.java | 76 +++------------- .../src/main/java/org/prism/PrismAOT.java | 79 +++++++++++++++++ .../src/main/java/org/prism/PrismWASM.java | 70 +++++++++++++++ .../src/test/java/org/prism/DummyTest.java | 86 +++---------------- .../src/test/java/org/prism/JRubyTest.java | 4 + 5 files changed, 175 insertions(+), 140 deletions(-) create mode 100644 java-wasm/src/main/java/org/prism/PrismAOT.java create mode 100644 java-wasm/src/main/java/org/prism/PrismWASM.java create mode 100644 java-wasm/src/test/java/org/prism/JRubyTest.java diff --git a/java-wasm/src/main/java/org/prism/Prism.java b/java-wasm/src/main/java/org/prism/Prism.java index 51552569e6..8bb9c63365 100644 --- a/java-wasm/src/main/java/org/prism/Prism.java +++ b/java-wasm/src/main/java/org/prism/Prism.java @@ -1,89 +1,37 @@ package org.prism; import com.dylibso.chicory.annotations.WasmModuleInterface; -import com.dylibso.chicory.runtime.ByteArrayMemory; -import com.dylibso.chicory.runtime.ImportValues; -import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasi.WasiOptions; import com.dylibso.chicory.wasi.WasiPreview1; -import com.dylibso.chicory.wasm.WasmModule; -import com.dylibso.chicory.wasm.types.MemoryLimits; import java.nio.charset.StandardCharsets; @WasmModuleInterface(WasmResource.absoluteFile) -public class Prism implements AutoCloseable { - private final WasiPreview1 wasi; - private final Instance instance; - private final Prism_ModuleExports exports; +public abstract class Prism implements AutoCloseable { + protected final WasiPreview1 wasi; - public Prism() { + Prism() { this(WasiOptions.builder().build()); } - public Prism(WasiOptions wasiOpts) { - wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - WasmModule module = PrismParser.load(); - PrismParser parser = new PrismParser(); - instance = Instance.builder(module) - .withMemoryFactory(limits -> new ByteArrayMemory(new MemoryLimits(10, MemoryLimits.MAX_PAGES))) - .withMachineFactory(parser.machineFactory()) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - exports = new Prism_ModuleExports(instance); - } - public Prism_ModuleExports exports() { - return exports; + Prism(WasiOptions wasiOpts) { + wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); } - public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { - int sourcePointer = 0; - int optionsPointer = 0; - int bufferPointer = 0; - byte[] result; - try { - sourcePointer = exports.calloc(sourceLength, 1); - exports.memory().write(sourcePointer, source); - - optionsPointer = exports.calloc(1, packedOptions.length); - exports.memory().write(optionsPointer, packedOptions); - - bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); - exports.pmBufferInit(bufferPointer); - - exports.pmSerializeParse(bufferPointer, sourcePointer, sourceLength, optionsPointer); + public static Prism newInstance(boolean aot) { + if (aot) return new PrismAOT(); - result = instance.memory().readBytes( - exports.pmBufferValue(bufferPointer), - exports.pmBufferLength(bufferPointer)); - } finally { - if (sourcePointer != 0) { - exports.free(sourcePointer); - } - if (optionsPointer != 0) { - exports.free(optionsPointer); - } - if (bufferPointer != 0) { - exports.pmBufferFree(bufferPointer); - exports.free(bufferPointer); - } - } - - return result; + return new PrismWASM(); } - public ParseResult serializeParse(byte[] packedOptions, String source) { - var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); + public abstract byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength); + public ParseResult serializeParse(byte[] packedOptions, String source) { + var sourceBytes = source.getBytes(StandardCharsets.ISO_8859_1); byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length); - return Loader.load(result, sourceBytes); } @Override - public void close() { - if (wasi != null) { - wasi.close(); - } - } + public abstract void close(); } diff --git a/java-wasm/src/main/java/org/prism/PrismAOT.java b/java-wasm/src/main/java/org/prism/PrismAOT.java new file mode 100644 index 0000000000..2637e12646 --- /dev/null +++ b/java-wasm/src/main/java/org/prism/PrismAOT.java @@ -0,0 +1,79 @@ +package org.prism; + +import com.dylibso.chicory.annotations.WasmModuleInterface; +import com.dylibso.chicory.runtime.ByteArrayMemory; +import com.dylibso.chicory.runtime.ImportValues; +import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.wasm.WasmModule; +import com.dylibso.chicory.wasm.types.MemoryLimits; + +import java.nio.charset.StandardCharsets; + +@WasmModuleInterface(WasmResource.absoluteFile) +public class PrismAOT extends Prism { + private final Instance instance; + private final Prism_ModuleExports exports; + + public PrismAOT() { + super(); + WasmModule module = PrismParser.load(); + PrismParser parser = new PrismParser(); + instance = Instance.builder(module) + .withMemoryFactory(limits -> new ByteArrayMemory(new MemoryLimits(10, MemoryLimits.MAX_PAGES))) + .withMachineFactory(parser.machineFactory()) + .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) + .build(); + exports = new Prism_ModuleExports(instance); + } + + public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { + int sourcePointer = 0; + int optionsPointer = 0; + int bufferPointer = 0; + byte[] result; + try { + sourcePointer = exports.calloc(sourceLength, 1); + exports.memory().write(sourcePointer, source); + + optionsPointer = exports.calloc(1, packedOptions.length); + exports.memory().write(optionsPointer, packedOptions); + + bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); + exports.pmBufferInit(bufferPointer); + + exports.pmSerializeParse(bufferPointer, sourcePointer, sourceLength, optionsPointer); + + result = instance.memory().readBytes( + exports.pmBufferValue(bufferPointer), + exports.pmBufferLength(bufferPointer)); + } finally { + if (sourcePointer != 0) { + exports.free(sourcePointer); + } + if (optionsPointer != 0) { + exports.free(optionsPointer); + } + if (bufferPointer != 0) { + exports.pmBufferFree(bufferPointer); + exports.free(bufferPointer); + } + } + + return result; + } + + public ParseResult serializeParse(byte[] packedOptions, String source) { + var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); + + byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length); + + return Loader.load(result, sourceBytes); + } + + @Override + public void close() { + if (wasi != null) { + wasi.close(); + } + } +} diff --git a/java-wasm/src/main/java/org/prism/PrismWASM.java b/java-wasm/src/main/java/org/prism/PrismWASM.java new file mode 100644 index 0000000000..235bfb54cc --- /dev/null +++ b/java-wasm/src/main/java/org/prism/PrismWASM.java @@ -0,0 +1,70 @@ +package org.prism; + +import com.dylibso.chicory.annotations.WasmModuleInterface; +import com.dylibso.chicory.runtime.ByteArrayMemory; +import com.dylibso.chicory.runtime.ExportFunction; +import com.dylibso.chicory.runtime.ImportValues; +import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.runtime.WasmRuntimeException; +import com.dylibso.chicory.wasi.WasiOptions; +import com.dylibso.chicory.wasi.WasiPreview1; +import com.dylibso.chicory.wasm.WasmModule; +import com.dylibso.chicory.wasm.types.MemoryLimits; + +import java.nio.charset.StandardCharsets; + +@WasmModuleInterface(WasmResource.absoluteFile) +public class PrismWASM extends Prism { + private final ExportFunction calloc; + private final ExportFunction pmSerializeParse; + private final ExportFunction pmBufferInit; + private final ExportFunction pmBufferSizeof; + private final ExportFunction pmBufferValue; + private final ExportFunction pmBufferLength; + + private final Instance instance; + + public PrismWASM() { + super(); + instance = Instance.builder(PrismParser.load()) + .withMemoryFactory(ByteArrayMemory::new) + .withMachineFactory(PrismParser::create) + .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) + .build(); + + calloc = instance.exports().function("calloc"); + pmSerializeParse = instance.exports().function("pm_serialize_parse"); + pmBufferInit = instance.exports().function("pm_buffer_init"); + pmBufferSizeof = instance.exports().function("pm_buffer_sizeof"); + pmBufferValue = instance.exports().function("pm_buffer_value"); + pmBufferLength = instance.exports().function("pm_buffer_length"); + } + + @Override + public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { + var sourcePointer = calloc.apply(1, sourceLength); + instance.memory().write((int) sourcePointer[0], sourceBytes, 0, sourceLength); + + var optionsPointer = calloc.apply(1, packedOptions.length); + instance.memory().write((int) optionsPointer[0], packedOptions); + + var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1); + pmBufferInit.apply(bufferPointer); + + pmSerializeParse.apply( + bufferPointer[0], sourcePointer[0], sourceLength, optionsPointer[0]); + + var result = instance.memory().readBytes( + (int) pmBufferValue.apply(bufferPointer[0])[0], + (int) pmBufferLength.apply(bufferPointer[0])[0]); + + return result; + } + + @Override + public void close() { + if (wasi != null) { + wasi.close(); + } + } +} diff --git a/java-wasm/src/test/java/org/prism/DummyTest.java b/java-wasm/src/test/java/org/prism/DummyTest.java index 9e49f1afdd..fe6d87d2e7 100644 --- a/java-wasm/src/test/java/org/prism/DummyTest.java +++ b/java-wasm/src/test/java/org/prism/DummyTest.java @@ -1,14 +1,7 @@ package org.prism; -import com.dylibso.chicory.runtime.ImportValues; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasi.WasiOptions; -import com.dylibso.chicory.wasi.WasiPreview1; -import com.dylibso.chicory.wasm.Parser; -import com.dylibso.chicory.wasm.types.Value; import org.junit.jupiter.api.Test; -import java.nio.charset.StandardCharsets; import java.util.EnumSet; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -31,42 +24,13 @@ public class DummyTest { @Test public void test1() { - WasiOptions wasiOpts = WasiOptions.builder().build(); - WasiPreview1 wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - var wasmPrism = Instance.builder(Parser.parse(DummyTest.class.getResourceAsStream("/prism.wasm"))) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - var memory = wasmPrism.memory(); - var calloc = wasmPrism.export("calloc"); - var pmSerializeParse = wasmPrism.export("pm_serialize_parse"); - var pmBufferInit = wasmPrism.export("pm_buffer_init"); - var pmBufferSizeof = wasmPrism.export("pm_buffer_sizeof"); - var pmBufferValue = wasmPrism.export("pm_buffer_value"); - var pmBufferLength = wasmPrism.export("pm_buffer_length"); - // The Ruby source code to be processed var source = "1 + 1"; - var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); - - var sourcePointer = calloc.apply(1, source.length()); - memory.writeString((int) sourcePointer[0], source); - - var optionsPointer = calloc.apply(1, packedOptions.length); - memory.write((int) optionsPointer[0], packedOptions); - - var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1); - pmBufferInit.apply(bufferPointer); - - pmSerializeParse.apply( - bufferPointer[0], sourcePointer[0], source.length(), optionsPointer[0]); - - var result = memory.readBytes( - (int) pmBufferValue.apply(bufferPointer[0])[0], - (int) pmBufferLength.apply(bufferPointer[0])[0]); - System.out.println("RESULT: " + new String(result)); - - ParseResult pr = Loader.load(result, sourceBytes); + ParseResult pr = null; + try (Prism prism = new PrismWASM()) { + pr = prism.serializeParse(packedOptions, source); + } assertEquals(1, pr.value.childNodes().length); System.out.println("Nodes:"); @@ -80,7 +44,7 @@ public void test1Aot() { var source = "1 + 1"; ParseResult pr = null; - try (Prism prism = new Prism()) { + try (Prism prism = new PrismAOT()) { pr = prism.serializeParse(packedOptions, source); } @@ -92,45 +56,15 @@ public void test1Aot() { @Test public void test2() { - WasiOptions wasiOpts = WasiOptions.builder().build(); - WasiPreview1 wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - var wasmPrism = Instance.builder(Parser.parse(DummyTest.class.getResourceAsStream("/prism.wasm"))) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - var memory = wasmPrism.memory(); - var calloc = wasmPrism.export("calloc"); - var pmSerializeParse = wasmPrism.export("pm_serialize_parse"); - var pmBufferInit = wasmPrism.export("pm_buffer_init"); - var pmBufferSizeof = wasmPrism.export("pm_buffer_sizeof"); - var pmBufferValue = wasmPrism.export("pm_buffer_value"); - var pmBufferLength = wasmPrism.export("pm_buffer_length"); - // The Ruby source code to be processed var source = "puts \"h\ne\nl\nl\no\n\""; - var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); - var sourcePointer = calloc.apply(1, source.length()); - memory.writeString((int) sourcePointer[0], source); - - var optionsPointer = calloc.apply(1, packedOptions.length); - memory.write((int) optionsPointer[0], packedOptions); - - var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1); - pmBufferInit.apply(bufferPointer); - - pmSerializeParse.apply( - bufferPointer[0], sourcePointer[0], source.length(), optionsPointer[0]); - - var result = memory.readBytes( - (int) pmBufferValue.apply(bufferPointer[0])[0], - (int) pmBufferLength.apply(bufferPointer[0])[0]); - - System.out.println("RESULT: " + new String(result)); - - ParseResult pr = Loader.load(result, sourceBytes); + ParseResult pr = null; + try (Prism prism = new PrismWASM()) { + pr = prism.serializeParse(packedOptions, source); + } assertEquals(1, pr.value.childNodes().length); - System.out.println("Nodes:"); System.out.println(pr.value.childNodes()[0]); assertTrue(pr.value.childNodes()[0].toString().contains("CallNode")); @@ -142,7 +76,7 @@ public void test2Aot() { var source = "puts \"h\ne\nl\nl\no\n\""; ParseResult pr = null; - try (Prism prism = new Prism()) { + try (Prism prism = new PrismAOT()) { pr = prism.serializeParse(packedOptions, source); } diff --git a/java-wasm/src/test/java/org/prism/JRubyTest.java b/java-wasm/src/test/java/org/prism/JRubyTest.java new file mode 100644 index 0000000000..1308f33b4c --- /dev/null +++ b/java-wasm/src/test/java/org/prism/JRubyTest.java @@ -0,0 +1,4 @@ +package org.prism; + +public class JRubyTest { +} From 4701c7eeda136ba3fe9f7e510b7003c1fb5cbc1f Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 26 Jan 2026 12:32:08 -0600 Subject: [PATCH 050/289] Add test that parses JRuby's boot files This is not all of the boot files but is sufficient to demonstrate a memory fault in the AOT WASM parser. --- java-wasm/pom.xml | 2 +- .../src/test/java/org/prism/JRubyTest.java | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 45f5eb71fc..1592c12174 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -61,7 +61,7 @@ org.jruby - jruby-base + jruby-complete 10.0.2.0 diff --git a/java-wasm/src/test/java/org/prism/JRubyTest.java b/java-wasm/src/test/java/org/prism/JRubyTest.java index 1308f33b4c..634d651592 100644 --- a/java-wasm/src/test/java/org/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/prism/JRubyTest.java @@ -1,4 +1,82 @@ package org.prism; +import org.jruby.Ruby; +import org.junit.jupiter.api.Test; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.EnumSet; + public class JRubyTest { + final static String[] JRUBY_BOOT_FILES = { + "jruby/java.rb", + "jruby/java/core_ext.rb", + "jruby/java/core_ext/object.rb", + "jruby/java/java_ext.rb", + "jruby/kernel.rb", + "jruby/kernel/signal.rb", + "jruby/kernel/kernel.rb", + "jruby/kernel/proc.rb", + "jruby/kernel/process.rb", + "jruby/kernel/enumerator.rb", + "jruby/kernel/enumerable.rb", + "jruby/kernel/io.rb", + "jruby/kernel/gc.rb", + "jruby/kernel/range.rb", + "jruby/kernel/file.rb", + "jruby/kernel/method.rb", + "jruby/kernel/thread.rb", + "jruby/kernel/integer.rb", + "jruby/kernel/time.rb", + "jruby/preludes.rb", + "jruby/kernel/prelude.rb", + "jruby/kernel/enc_prelude.rb", + "META-INF/jruby.home/lib/ruby/stdlib/unicode_normalize.rb", + "jruby/kernel/gem_prelude.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rbconfig.rb", + "jruby/kernel/rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/compatibility.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/deprecate.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/errors.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/target_rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/exceptions.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/unknown_command_spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/basic_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/stub_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/platform.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification_record.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/util/list.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/requirement.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/version.rb", + }; + + @Test + public void basicJRubyTest() throws Throwable{ + Prism prism = new PrismWASM(); + byte[] src = new byte[1024*1024]; + + for (var file : JRUBY_BOOT_FILES) { + byte[] options = ParsingOptions.serialize( + file.getBytes(StandardCharsets.UTF_8), + 1, + "UTF-8".getBytes(StandardCharsets.UTF_8), + false, + EnumSet.noneOf(ParsingOptions.CommandLine.class), + ParsingOptions.SyntaxVersion.LATEST, + false, + false, + false, + new byte[][][]{} + ); + try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { + DataInputStream dis = new DataInputStream(fileIn); + int read = dis.read(src); + prism.serialize(options, src, read); + } + } + } } From 7feae0d07aa0fed6c7bd6b28a920f178b859f86e Mon Sep 17 00:00:00 2001 From: andreatp Date: Tue, 27 Jan 2026 14:07:03 +0000 Subject: [PATCH 051/289] Fix the memory leak --- java-wasm/src/main/java/org/prism/Prism.java | 6 +- .../src/main/java/org/prism/PrismAOT.java | 41 ++++------ .../src/main/java/org/prism/PrismWASM.java | 82 +++++++++---------- .../src/test/java/org/prism/JRubyTest.java | 26 +++++- 4 files changed, 85 insertions(+), 70 deletions(-) diff --git a/java-wasm/src/main/java/org/prism/Prism.java b/java-wasm/src/main/java/org/prism/Prism.java index 8bb9c63365..8c40c6dce5 100644 --- a/java-wasm/src/main/java/org/prism/Prism.java +++ b/java-wasm/src/main/java/org/prism/Prism.java @@ -33,5 +33,9 @@ public ParseResult serializeParse(byte[] packedOptions, String source) { } @Override - public abstract void close(); + public void close() { + if (wasi != null) { + wasi.close(); + } + } } diff --git a/java-wasm/src/main/java/org/prism/PrismAOT.java b/java-wasm/src/main/java/org/prism/PrismAOT.java index 2637e12646..fce4bd7168 100644 --- a/java-wasm/src/main/java/org/prism/PrismAOT.java +++ b/java-wasm/src/main/java/org/prism/PrismAOT.java @@ -9,45 +9,46 @@ import java.nio.charset.StandardCharsets; -@WasmModuleInterface(WasmResource.absoluteFile) public class PrismAOT extends Prism { - private final Instance instance; private final Prism_ModuleExports exports; + private final Instance instance; public PrismAOT() { super(); - WasmModule module = PrismParser.load(); - PrismParser parser = new PrismParser(); - instance = Instance.builder(module) - .withMemoryFactory(limits -> new ByteArrayMemory(new MemoryLimits(10, MemoryLimits.MAX_PAGES))) - .withMachineFactory(parser.machineFactory()) + instance = Instance.builder(PrismParser.load()) + .withMemoryFactory(ByteArrayMemory::new) + .withMachineFactory(PrismParser::create) .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) .build(); exports = new Prism_ModuleExports(instance); } - public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { + @Override + public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { int sourcePointer = 0; int optionsPointer = 0; int bufferPointer = 0; byte[] result; try { - sourcePointer = exports.calloc(sourceLength, 1); - exports.memory().write(sourcePointer, source); + sourcePointer = exports.calloc(1, sourceLength + 1); + instance.memory().write(sourcePointer, sourceBytes, 0, sourceLength); + instance.memory().writeByte(sourcePointer + sourceLength, (byte) 0); optionsPointer = exports.calloc(1, packedOptions.length); - exports.memory().write(optionsPointer, packedOptions); + instance.memory().write(optionsPointer, packedOptions); bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); exports.pmBufferInit(bufferPointer); - exports.pmSerializeParse(bufferPointer, sourcePointer, sourceLength, optionsPointer); + exports.pmSerializeParse( + bufferPointer, sourcePointer, sourceLength, optionsPointer); result = instance.memory().readBytes( exports.pmBufferValue(bufferPointer), exports.pmBufferLength(bufferPointer)); } finally { if (sourcePointer != 0) { + exports.pmStringFree(sourcePointer); exports.free(sourcePointer); } if (optionsPointer != 0) { @@ -62,18 +63,8 @@ public byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength) { return result; } - public ParseResult serializeParse(byte[] packedOptions, String source) { - var sourceBytes = source.getBytes(StandardCharsets.US_ASCII); - - byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length); - - return Loader.load(result, sourceBytes); - } - - @Override - public void close() { - if (wasi != null) { - wasi.close(); - } + // DEBUG CHECK + public int memorySize() { + return instance.memory().pages(); } } diff --git a/java-wasm/src/main/java/org/prism/PrismWASM.java b/java-wasm/src/main/java/org/prism/PrismWASM.java index 235bfb54cc..a1b7c374e4 100644 --- a/java-wasm/src/main/java/org/prism/PrismWASM.java +++ b/java-wasm/src/main/java/org/prism/PrismWASM.java @@ -1,70 +1,70 @@ package org.prism; -import com.dylibso.chicory.annotations.WasmModuleInterface; import com.dylibso.chicory.runtime.ByteArrayMemory; -import com.dylibso.chicory.runtime.ExportFunction; import com.dylibso.chicory.runtime.ImportValues; import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.WasmRuntimeException; -import com.dylibso.chicory.wasi.WasiOptions; -import com.dylibso.chicory.wasi.WasiPreview1; +import com.dylibso.chicory.runtime.InterpreterMachine; +import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.wasm.WasmModule; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import java.nio.charset.StandardCharsets; - -@WasmModuleInterface(WasmResource.absoluteFile) public class PrismWASM extends Prism { - private final ExportFunction calloc; - private final ExportFunction pmSerializeParse; - private final ExportFunction pmBufferInit; - private final ExportFunction pmBufferSizeof; - private final ExportFunction pmBufferValue; - private final ExportFunction pmBufferLength; - + private final Prism_ModuleExports exports; private final Instance instance; public PrismWASM() { super(); - instance = Instance.builder(PrismParser.load()) + WasmModule module = Parser.parse( + PrismWASM.class.getResourceAsStream("/prism.wasm")); + instance = Instance.builder(module) .withMemoryFactory(ByteArrayMemory::new) - .withMachineFactory(PrismParser::create) + .withMachineFactory(InterpreterMachine::new) .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) .build(); - - calloc = instance.exports().function("calloc"); - pmSerializeParse = instance.exports().function("pm_serialize_parse"); - pmBufferInit = instance.exports().function("pm_buffer_init"); - pmBufferSizeof = instance.exports().function("pm_buffer_sizeof"); - pmBufferValue = instance.exports().function("pm_buffer_value"); - pmBufferLength = instance.exports().function("pm_buffer_length"); + exports = new Prism_ModuleExports(instance); } @Override public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { - var sourcePointer = calloc.apply(1, sourceLength); - instance.memory().write((int) sourcePointer[0], sourceBytes, 0, sourceLength); + int sourcePointer = 0; + int optionsPointer = 0; + int bufferPointer = 0; + byte[] result; + try { + sourcePointer = exports.calloc(1, sourceLength + 1); + instance.memory().write(sourcePointer, sourceBytes, 0, sourceLength); + instance.memory().writeByte(sourcePointer + sourceLength, (byte) 0); - var optionsPointer = calloc.apply(1, packedOptions.length); - instance.memory().write((int) optionsPointer[0], packedOptions); + optionsPointer = exports.calloc(1, packedOptions.length); + instance.memory().write(optionsPointer, packedOptions); - var bufferPointer = calloc.apply(pmBufferSizeof.apply()[0], 1); - pmBufferInit.apply(bufferPointer); + bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); + exports.pmBufferInit(bufferPointer); - pmSerializeParse.apply( - bufferPointer[0], sourcePointer[0], sourceLength, optionsPointer[0]); + exports.pmSerializeParse( + bufferPointer, sourcePointer, sourceLength, optionsPointer); - var result = instance.memory().readBytes( - (int) pmBufferValue.apply(bufferPointer[0])[0], - (int) pmBufferLength.apply(bufferPointer[0])[0]); + result = instance.memory().readBytes( + exports.pmBufferValue(bufferPointer), + exports.pmBufferLength(bufferPointer)); + } finally { + if (sourcePointer != 0) { + exports.pmStringFree(sourcePointer); + exports.free(sourcePointer); + } + if (optionsPointer != 0) { + exports.free(optionsPointer); + } + if (bufferPointer != 0) { + exports.pmBufferFree(bufferPointer); + exports.free(bufferPointer); + } + } return result; } - @Override - public void close() { - if (wasi != null) { - wasi.close(); - } + // DEBUG + public int memorySize() { + return instance.memory().pages(); } } diff --git a/java-wasm/src/test/java/org/prism/JRubyTest.java b/java-wasm/src/test/java/org/prism/JRubyTest.java index 634d651592..7dc265c983 100644 --- a/java-wasm/src/test/java/org/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/prism/JRubyTest.java @@ -8,6 +8,8 @@ import java.nio.charset.StandardCharsets; import java.util.EnumSet; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class JRubyTest { final static String[] JRUBY_BOOT_FILES = { "jruby/java.rb", @@ -55,9 +57,27 @@ public class JRubyTest { }; @Test - public void basicJRubyTest() throws Throwable{ - Prism prism = new PrismWASM(); - byte[] src = new byte[1024*1024]; + public void jrubyAOT() throws Exception { + var prismAot = new PrismAOT(); + + for (int i = 0; i < 3; i++) { + basicJRubyTest(prismAot); + } + var memoryPagesBefore = prismAot.memorySize(); + for (int i = 0; i < 100; i++) { + basicJRubyTest(prismAot); + } + var memoryPagesAfter = prismAot.memorySize(); + assertEquals(memoryPagesBefore, memoryPagesAfter); + } + + @Test + public void jrubyWASM() throws Exception { + basicJRubyTest(new PrismWASM()); + } + + private static void basicJRubyTest(Prism prism) throws Exception { + byte[] src = new byte[1024 * 1024]; for (var file : JRUBY_BOOT_FILES) { byte[] options = ParsingOptions.serialize( From fb707f5d398d354053f74f7b0fc8160ef858f96a Mon Sep 17 00:00:00 2001 From: andreatp Date: Tue, 27 Jan 2026 15:52:21 +0000 Subject: [PATCH 052/289] rem string free --- java-wasm/src/main/java/org/prism/PrismAOT.java | 1 - java-wasm/src/main/java/org/prism/PrismWASM.java | 1 - 2 files changed, 2 deletions(-) diff --git a/java-wasm/src/main/java/org/prism/PrismAOT.java b/java-wasm/src/main/java/org/prism/PrismAOT.java index fce4bd7168..f669c1ab07 100644 --- a/java-wasm/src/main/java/org/prism/PrismAOT.java +++ b/java-wasm/src/main/java/org/prism/PrismAOT.java @@ -48,7 +48,6 @@ public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLeng exports.pmBufferLength(bufferPointer)); } finally { if (sourcePointer != 0) { - exports.pmStringFree(sourcePointer); exports.free(sourcePointer); } if (optionsPointer != 0) { diff --git a/java-wasm/src/main/java/org/prism/PrismWASM.java b/java-wasm/src/main/java/org/prism/PrismWASM.java index a1b7c374e4..63afd5495e 100644 --- a/java-wasm/src/main/java/org/prism/PrismWASM.java +++ b/java-wasm/src/main/java/org/prism/PrismWASM.java @@ -48,7 +48,6 @@ public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLeng exports.pmBufferLength(bufferPointer)); } finally { if (sourcePointer != 0) { - exports.pmStringFree(sourcePointer); exports.free(sourcePointer); } if (optionsPointer != 0) { From 1d10ae22c3eae42cbdf50017566f1868c78aca1b Mon Sep 17 00:00:00 2001 From: andreatp Date: Wed, 28 Jan 2026 10:39:04 +0000 Subject: [PATCH 053/289] Cleanup and improvements --- .github/workflows/java-wasm-bindings.yml | 2 +- .gitignore | 2 + Makefile | 6 +- java-wasm/perf-test/.gitignore | 1 + java-wasm/perf-test/bench.sh | 6 ++ java-wasm/perf-test/test | 97 +++++++++++++++++++ java-wasm/pom.xml | 2 +- .../org/prism/WasmResource.java | 2 +- java-wasm/src/main/java/org/prism/Prism.java | 70 +++++++++++-- .../src/main/java/org/prism/PrismAOT.java | 69 ------------- .../src/main/java/org/prism/PrismWASM.java | 69 ------------- .../src/test/java/org/prism/DummyTest.java | 8 +- .../src/test/java/org/prism/JRubyTest.java | 33 ++++--- .../src/{main => test}/resources/.gitignore | 0 14 files changed, 199 insertions(+), 168 deletions(-) create mode 100644 java-wasm/perf-test/.gitignore create mode 100755 java-wasm/perf-test/bench.sh create mode 100755 java-wasm/perf-test/test delete mode 100644 java-wasm/src/main/java/org/prism/PrismAOT.java delete mode 100644 java-wasm/src/main/java/org/prism/PrismWASM.java rename java-wasm/src/{main => test}/resources/.gitignore (100%) diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 5d130c07e1..3a0a066334 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -48,4 +48,4 @@ jobs: - uses: actions/upload-artifact@v6 with: name: prism.wasm - path: java-wasm/src/main/resources/prism.wasm + path: java-wasm/src/test/resources/prism.wasm diff --git a/.gitignore b/.gitignore index 6706482b64..b00333f107 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,5 @@ compile_commands.json .vscode/ tags + +wasi-sdk* diff --git a/Makefile b/Makefile index cefc199a52..7f61f753fa 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ SOEXT ?= $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]') CPPFLAGS := -Iinclude $(CPPFLAGS) CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(CFLAGS) -JAVA_WASM_CFLAGS := -g -Oz -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(JAVA_WASM_CFLAGS) +JAVA_WASM_CFLAGS := -g0 -O2 -Oz -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -Wno-missing-braces -fno-sanitize=all -fno-stack-protector -fPIC -fvisibility=hidden -Wimplicit-fallthrough $(JAVA_WASM_CFLAGS) CC ?= cc AR ?= ar ARFLAGS ?= -r$(V0:1=v) @@ -31,7 +31,7 @@ all: shared static shared: build/libprism.$(SOEXT) static: build/libprism.a wasm: javascript/src/prism.wasm -java-wasm: java-wasm/src/main/resources/prism.wasm +java-wasm: java-wasm/src/test/resources/prism.wasm build/libprism.$(SOEXT): $(SHARED_OBJECTS) $(ECHO) "linking $@ with $(CC)" @@ -51,7 +51,7 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) -Oz -g0 -flto -fdata-sections -ffunction-sections \ -o $@ $(SOURCES) -java-wasm/src/main/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) +java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) $(ECHO) "building $@" $(Q) $(MAKEDIRS) $(@D) $(Q) $(WASI_SDK_PATH)/bin/clang $(DEBUG_FLAGS) -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(JAVA_WASM_CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi -o $@ $(SOURCES) diff --git a/java-wasm/perf-test/.gitignore b/java-wasm/perf-test/.gitignore new file mode 100644 index 0000000000..60286da241 --- /dev/null +++ b/java-wasm/perf-test/.gitignore @@ -0,0 +1 @@ +profile.html diff --git a/java-wasm/perf-test/bench.sh b/java-wasm/perf-test/bench.sh new file mode 100755 index 0000000000..1ad69239b1 --- /dev/null +++ b/java-wasm/perf-test/bench.sh @@ -0,0 +1,6 @@ +#! /bin/bash +set -euxo pipefail + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +jbang --fresh --deps org.openjdk.jmh:jmh-generator-annprocess:1.36 --javaagent=ap-loader@jvm-profiling-tools/ap-loader=start,event=cpu,file=${SCRIPT_DIR}/profile.html ${SCRIPT_DIR}/test \ No newline at end of file diff --git a/java-wasm/perf-test/test b/java-wasm/perf-test/test new file mode 100755 index 0000000000..e3aed8347c --- /dev/null +++ b/java-wasm/perf-test/test @@ -0,0 +1,97 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +//DEPS org.jruby:chicory-prism:0.0.1-SNAPSHOT +//DEPS org.jruby:jruby-complete:10.0.2.0 + +import static java.lang.System.*; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.EnumSet; + +import org.jruby.Ruby; + +import org.prism.Prism; +import org.prism.ParsingOptions; + +public class test { + + final static String[] JRUBY_BOOT_FILES = { + "jruby/java.rb", + "jruby/java/core_ext.rb", + "jruby/java/core_ext/object.rb", + "jruby/java/java_ext.rb", + "jruby/kernel.rb", + "jruby/kernel/signal.rb", + "jruby/kernel/kernel.rb", + "jruby/kernel/proc.rb", + "jruby/kernel/process.rb", + "jruby/kernel/enumerator.rb", + "jruby/kernel/enumerable.rb", + "jruby/kernel/io.rb", + "jruby/kernel/gc.rb", + "jruby/kernel/range.rb", + "jruby/kernel/file.rb", + "jruby/kernel/method.rb", + "jruby/kernel/thread.rb", + "jruby/kernel/integer.rb", + "jruby/kernel/time.rb", + "jruby/preludes.rb", + "jruby/kernel/prelude.rb", + "jruby/kernel/enc_prelude.rb", + "META-INF/jruby.home/lib/ruby/stdlib/unicode_normalize.rb", + "jruby/kernel/gem_prelude.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rbconfig.rb", + "jruby/kernel/rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/compatibility.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/deprecate.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/errors.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/target_rbconfig.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/exceptions.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/unknown_command_spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/basic_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/stub_specification.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/platform.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/specification_record.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/util/list.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/requirement.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/version.rb", + }; + + public static void main(String... args) throws Exception { + out.println("Starting"); + var count = 100; + + var prism = new Prism(); + byte[] src = new byte[1024 * 1024]; + + for (int i = 0; i < count; i++) { + for (var file : JRUBY_BOOT_FILES) { + byte[] options = ParsingOptions.serialize( + file.getBytes(StandardCharsets.UTF_8), + 1, + "UTF-8".getBytes(StandardCharsets.UTF_8), + false, + EnumSet.noneOf(ParsingOptions.CommandLine.class), + ParsingOptions.SyntaxVersion.LATEST, + false, + false, + false, + new byte[][][]{} + ); + + try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { + DataInputStream dis = new DataInputStream(fileIn); + int read = dis.read(src); + prism.serialize(options, src, read); + } + } + } + + out.println("End"); + } +} diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 1592c12174..0e0ed2fb96 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -131,7 +131,7 @@ org.prism.PrismParser - src/main/resources/prism.wasm + src/test/resources/prism.wasm diff --git a/java-wasm/src/main/java-templates/org/prism/WasmResource.java b/java-wasm/src/main/java-templates/org/prism/WasmResource.java index ccf1d0bcdd..48f2671714 100644 --- a/java-wasm/src/main/java-templates/org/prism/WasmResource.java +++ b/java-wasm/src/main/java-templates/org/prism/WasmResource.java @@ -1,7 +1,7 @@ package org.prism; public final class WasmResource { - public static final String absoluteFile = "file://${project.basedir}/src/main/resources/prism.wasm"; + public static final String absoluteFile = "file://${project.basedir}/src/test/resources/prism.wasm"; private WasmResource() {} } diff --git a/java-wasm/src/main/java/org/prism/Prism.java b/java-wasm/src/main/java/org/prism/Prism.java index 8c40c6dce5..a92709f932 100644 --- a/java-wasm/src/main/java/org/prism/Prism.java +++ b/java-wasm/src/main/java/org/prism/Prism.java @@ -1,30 +1,82 @@ package org.prism; import com.dylibso.chicory.annotations.WasmModuleInterface; +import com.dylibso.chicory.runtime.ByteArrayMemory; +import com.dylibso.chicory.runtime.ImportValues; +import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasi.WasiOptions; import com.dylibso.chicory.wasi.WasiPreview1; import java.nio.charset.StandardCharsets; @WasmModuleInterface(WasmResource.absoluteFile) -public abstract class Prism implements AutoCloseable { - protected final WasiPreview1 wasi; +public class Prism implements AutoCloseable { + private final WasiPreview1 wasi; + protected final Prism_ModuleExports exports; + private final Instance instance; - Prism() { + private int bufferPointer; + private int preSourcePointer; + private int preOptionsPointer; + + private final int SOURCE_SIZE = 2 * 1024 * 1024; // 2 MiB + private final int PACKED_OPTIONS_BUFFER_SIZE = 1024; + + public Prism() { this(WasiOptions.builder().build()); } - Prism(WasiOptions wasiOpts) { + public Prism(WasiOptions wasiOpts) { wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - } + instance = Instance.builder(PrismParser.load()) + .withMemoryFactory(ByteArrayMemory::new) + .withMachineFactory(PrismParser::create) + .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) + .build(); + exports = new Prism_ModuleExports(instance); - public static Prism newInstance(boolean aot) { - if (aot) return new PrismAOT(); + preOptionsPointer = exports.calloc(1, PACKED_OPTIONS_BUFFER_SIZE); + preSourcePointer = exports.calloc(1, SOURCE_SIZE); - return new PrismWASM(); + bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); + exports.pmBufferInit(bufferPointer); } - public abstract byte[] serialize(byte[] packedOptions, byte[] source, int sourceLength); + public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { + int sourcePointer = 0; + boolean useDefaultSourcePointer = sourceLength + 1 > SOURCE_SIZE; + int optionsPointer = 0; + boolean useDefaultOptionsPointer = packedOptions.length > PACKED_OPTIONS_BUFFER_SIZE; + byte[] result; + try { + sourcePointer = (!useDefaultSourcePointer) ? + exports.calloc(1, sourceLength + 1) : preSourcePointer; + instance.memory().write(sourcePointer, sourceBytes, 0, sourceLength); + instance.memory().writeByte(sourcePointer + sourceLength, (byte) 0); + + optionsPointer = (!useDefaultOptionsPointer) ? + exports.calloc(1, packedOptions.length) : preOptionsPointer; + instance.memory().write(optionsPointer, packedOptions); + + exports.pmBufferClear(bufferPointer); + + exports.pmSerializeParse( + bufferPointer, sourcePointer, sourceLength, optionsPointer); + + result = instance.memory().readBytes( + exports.pmBufferValue(bufferPointer), + exports.pmBufferLength(bufferPointer)); + } finally { + if (!useDefaultSourcePointer) { + exports.free(sourcePointer); + } + if (!useDefaultOptionsPointer) { + exports.free(optionsPointer); + } + } + + return result; + } public ParseResult serializeParse(byte[] packedOptions, String source) { var sourceBytes = source.getBytes(StandardCharsets.ISO_8859_1); diff --git a/java-wasm/src/main/java/org/prism/PrismAOT.java b/java-wasm/src/main/java/org/prism/PrismAOT.java deleted file mode 100644 index f669c1ab07..0000000000 --- a/java-wasm/src/main/java/org/prism/PrismAOT.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.prism; - -import com.dylibso.chicory.annotations.WasmModuleInterface; -import com.dylibso.chicory.runtime.ByteArrayMemory; -import com.dylibso.chicory.runtime.ImportValues; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.WasmModule; -import com.dylibso.chicory.wasm.types.MemoryLimits; - -import java.nio.charset.StandardCharsets; - -public class PrismAOT extends Prism { - private final Prism_ModuleExports exports; - private final Instance instance; - - public PrismAOT() { - super(); - instance = Instance.builder(PrismParser.load()) - .withMemoryFactory(ByteArrayMemory::new) - .withMachineFactory(PrismParser::create) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - exports = new Prism_ModuleExports(instance); - } - - @Override - public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { - int sourcePointer = 0; - int optionsPointer = 0; - int bufferPointer = 0; - byte[] result; - try { - sourcePointer = exports.calloc(1, sourceLength + 1); - instance.memory().write(sourcePointer, sourceBytes, 0, sourceLength); - instance.memory().writeByte(sourcePointer + sourceLength, (byte) 0); - - optionsPointer = exports.calloc(1, packedOptions.length); - instance.memory().write(optionsPointer, packedOptions); - - bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); - exports.pmBufferInit(bufferPointer); - - exports.pmSerializeParse( - bufferPointer, sourcePointer, sourceLength, optionsPointer); - - result = instance.memory().readBytes( - exports.pmBufferValue(bufferPointer), - exports.pmBufferLength(bufferPointer)); - } finally { - if (sourcePointer != 0) { - exports.free(sourcePointer); - } - if (optionsPointer != 0) { - exports.free(optionsPointer); - } - if (bufferPointer != 0) { - exports.pmBufferFree(bufferPointer); - exports.free(bufferPointer); - } - } - - return result; - } - - // DEBUG CHECK - public int memorySize() { - return instance.memory().pages(); - } -} diff --git a/java-wasm/src/main/java/org/prism/PrismWASM.java b/java-wasm/src/main/java/org/prism/PrismWASM.java deleted file mode 100644 index 63afd5495e..0000000000 --- a/java-wasm/src/main/java/org/prism/PrismWASM.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.prism; - -import com.dylibso.chicory.runtime.ByteArrayMemory; -import com.dylibso.chicory.runtime.ImportValues; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.InterpreterMachine; -import com.dylibso.chicory.wasm.Parser; -import com.dylibso.chicory.wasm.WasmModule; - -public class PrismWASM extends Prism { - private final Prism_ModuleExports exports; - private final Instance instance; - - public PrismWASM() { - super(); - WasmModule module = Parser.parse( - PrismWASM.class.getResourceAsStream("/prism.wasm")); - instance = Instance.builder(module) - .withMemoryFactory(ByteArrayMemory::new) - .withMachineFactory(InterpreterMachine::new) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - exports = new Prism_ModuleExports(instance); - } - - @Override - public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { - int sourcePointer = 0; - int optionsPointer = 0; - int bufferPointer = 0; - byte[] result; - try { - sourcePointer = exports.calloc(1, sourceLength + 1); - instance.memory().write(sourcePointer, sourceBytes, 0, sourceLength); - instance.memory().writeByte(sourcePointer + sourceLength, (byte) 0); - - optionsPointer = exports.calloc(1, packedOptions.length); - instance.memory().write(optionsPointer, packedOptions); - - bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); - exports.pmBufferInit(bufferPointer); - - exports.pmSerializeParse( - bufferPointer, sourcePointer, sourceLength, optionsPointer); - - result = instance.memory().readBytes( - exports.pmBufferValue(bufferPointer), - exports.pmBufferLength(bufferPointer)); - } finally { - if (sourcePointer != 0) { - exports.free(sourcePointer); - } - if (optionsPointer != 0) { - exports.free(optionsPointer); - } - if (bufferPointer != 0) { - exports.pmBufferFree(bufferPointer); - exports.free(bufferPointer); - } - } - - return result; - } - - // DEBUG - public int memorySize() { - return instance.memory().pages(); - } -} diff --git a/java-wasm/src/test/java/org/prism/DummyTest.java b/java-wasm/src/test/java/org/prism/DummyTest.java index fe6d87d2e7..fd106e07a3 100644 --- a/java-wasm/src/test/java/org/prism/DummyTest.java +++ b/java-wasm/src/test/java/org/prism/DummyTest.java @@ -28,7 +28,7 @@ public void test1() { var source = "1 + 1"; ParseResult pr = null; - try (Prism prism = new PrismWASM()) { + try (Prism prism = new Prism()) { pr = prism.serializeParse(packedOptions, source); } @@ -44,7 +44,7 @@ public void test1Aot() { var source = "1 + 1"; ParseResult pr = null; - try (Prism prism = new PrismAOT()) { + try (Prism prism = new Prism()) { pr = prism.serializeParse(packedOptions, source); } @@ -60,7 +60,7 @@ public void test2() { var source = "puts \"h\ne\nl\nl\no\n\""; ParseResult pr = null; - try (Prism prism = new PrismWASM()) { + try (Prism prism = new Prism()) { pr = prism.serializeParse(packedOptions, source); } @@ -76,7 +76,7 @@ public void test2Aot() { var source = "puts \"h\ne\nl\nl\no\n\""; ParseResult pr = null; - try (Prism prism = new PrismAOT()) { + try (Prism prism = new Prism()) { pr = prism.serializeParse(packedOptions, source); } diff --git a/java-wasm/src/test/java/org/prism/JRubyTest.java b/java-wasm/src/test/java/org/prism/JRubyTest.java index 7dc265c983..c158568602 100644 --- a/java-wasm/src/test/java/org/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/prism/JRubyTest.java @@ -56,26 +56,36 @@ public class JRubyTest { "META-INF/jruby.home/lib/ruby/stdlib/rubygems/version.rb", }; + private class TestingPrism extends Prism { + TestingPrism() { + super(); + } + + public int memPages() { + return exports.memory().pages(); + } + } + @Test - public void jrubyAOT() throws Exception { - var prismAot = new PrismAOT(); + public void jrubyReproducer() throws Exception { + var prism = new TestingPrism(); for (int i = 0; i < 3; i++) { - basicJRubyTest(prismAot); + basicJRubyTest(prism); } - var memoryPagesBefore = prismAot.memorySize(); + var memoryPagesBefore = prism.memPages(); for (int i = 0; i < 100; i++) { - basicJRubyTest(prismAot); + var before = System.currentTimeMillis(); + + basicJRubyTest(prism); + + var after = System.currentTimeMillis(); + System.out.println("Elapsed: " + (after - before)); } - var memoryPagesAfter = prismAot.memorySize(); + var memoryPagesAfter = prism.memPages(); assertEquals(memoryPagesBefore, memoryPagesAfter); } - @Test - public void jrubyWASM() throws Exception { - basicJRubyTest(new PrismWASM()); - } - private static void basicJRubyTest(Prism prism) throws Exception { byte[] src = new byte[1024 * 1024]; @@ -92,6 +102,7 @@ private static void basicJRubyTest(Prism prism) throws Exception { false, new byte[][][]{} ); + try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { DataInputStream dis = new DataInputStream(fileIn); int read = dis.read(src); diff --git a/java-wasm/src/main/resources/.gitignore b/java-wasm/src/test/resources/.gitignore similarity index 100% rename from java-wasm/src/main/resources/.gitignore rename to java-wasm/src/test/resources/.gitignore From d716178eaa2e477f8a9310007c62f46801eb76e6 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 3 Feb 2026 13:42:07 -0600 Subject: [PATCH 054/289] Update java-wasm to Java 21 minimum This is only intended to ever be used with JRuby 10+, which already requires Java 21. --- .github/workflows/java-wasm-bindings.yml | 2 +- java-wasm/pom.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 3a0a066334..679fb09a8b 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -38,7 +38,7 @@ jobs: uses: actions/setup-java@v5 with: distribution: 'temurin' - java-version: '17' + java-version: '21' cache: maven - name: Run the tests diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 0e0ed2fb96..501711e1fd 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -12,8 +12,8 @@ UTF-8 UTF-8 - 11 - 11 + 21 + 21 1.6.1 6.0.3 @@ -86,7 +86,7 @@ maven-compiler-plugin 3.15.0 - 11 + 21 com.dylibso.chicory From 365d3df66eced09b66c396d039869de447f9dad3 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 3 Feb 2026 14:18:12 -0600 Subject: [PATCH 055/289] Move WASM parser to a JRuby package * org.jruby.parser is base package for JRuby parsers * org.jruby.parser.prism is for parsers based on Prism * org.jruby.parser.prism.wasm is for the WASM Prism wrapper --- java-wasm/perf-test/test | 2 +- java-wasm/pom.xml | 2 +- .../org/{prism => jruby/parser/prism/wasm}/WasmResource.java | 2 +- .../java/org/{prism => jruby/parser/prism/wasm}/Prism.java | 4 +++- .../test/java/org/{ => jruby/parser}/prism/DummyTest.java | 5 ++++- .../test/java/org/{ => jruby/parser}/prism/JRubyTest.java | 4 +++- 6 files changed, 13 insertions(+), 6 deletions(-) rename java-wasm/src/main/java-templates/org/{prism => jruby/parser/prism/wasm}/WasmResource.java (82%) rename java-wasm/src/main/java/org/{prism => jruby/parser/prism/wasm}/Prism.java (97%) rename java-wasm/src/test/java/org/{ => jruby/parser}/prism/DummyTest.java (94%) rename java-wasm/src/test/java/org/{ => jruby/parser}/prism/JRubyTest.java (97%) diff --git a/java-wasm/perf-test/test b/java-wasm/perf-test/test index e3aed8347c..e2c8dfb575 100755 --- a/java-wasm/perf-test/test +++ b/java-wasm/perf-test/test @@ -12,7 +12,7 @@ import java.util.EnumSet; import org.jruby.Ruby; -import org.prism.Prism; +import org.jruby.parser.prism.wasm.Prism; import org.prism.ParsingOptions; public class test { diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 501711e1fd..587e094ab7 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -130,7 +130,7 @@ compile - org.prism.PrismParser + org.jruby.parser.prism.wasm.PrismParser src/test/resources/prism.wasm diff --git a/java-wasm/src/main/java-templates/org/prism/WasmResource.java b/java-wasm/src/main/java-templates/org/jruby/parser/prism/wasm/WasmResource.java similarity index 82% rename from java-wasm/src/main/java-templates/org/prism/WasmResource.java rename to java-wasm/src/main/java-templates/org/jruby/parser/prism/wasm/WasmResource.java index 48f2671714..2b95406d13 100644 --- a/java-wasm/src/main/java-templates/org/prism/WasmResource.java +++ b/java-wasm/src/main/java-templates/org/jruby/parser/prism/wasm/WasmResource.java @@ -1,4 +1,4 @@ -package org.prism; +package org.jruby.parser.prism.wasm; public final class WasmResource { public static final String absoluteFile = "file://${project.basedir}/src/test/resources/prism.wasm"; diff --git a/java-wasm/src/main/java/org/prism/Prism.java b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java similarity index 97% rename from java-wasm/src/main/java/org/prism/Prism.java rename to java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java index a92709f932..dafba022e9 100644 --- a/java-wasm/src/main/java/org/prism/Prism.java +++ b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java @@ -1,4 +1,4 @@ -package org.prism; +package org.jruby.parser.prism.wasm; import com.dylibso.chicory.annotations.WasmModuleInterface; import com.dylibso.chicory.runtime.ByteArrayMemory; @@ -6,6 +6,8 @@ import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasi.WasiOptions; import com.dylibso.chicory.wasi.WasiPreview1; +import org.prism.Loader; +import org.prism.ParseResult; import java.nio.charset.StandardCharsets; diff --git a/java-wasm/src/test/java/org/prism/DummyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java similarity index 94% rename from java-wasm/src/test/java/org/prism/DummyTest.java rename to java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java index fd106e07a3..5c12fb45a1 100644 --- a/java-wasm/src/test/java/org/prism/DummyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java @@ -1,6 +1,9 @@ -package org.prism; +package org.jruby.parser.prism; +import org.jruby.parser.prism.wasm.Prism; import org.junit.jupiter.api.Test; +import org.prism.ParseResult; +import org.prism.ParsingOptions; import java.util.EnumSet; diff --git a/java-wasm/src/test/java/org/prism/JRubyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java similarity index 97% rename from java-wasm/src/test/java/org/prism/JRubyTest.java rename to java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java index c158568602..5b6364a926 100644 --- a/java-wasm/src/test/java/org/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java @@ -1,7 +1,9 @@ -package org.prism; +package org.jruby.parser.prism; import org.jruby.Ruby; +import org.jruby.parser.prism.wasm.Prism; import org.junit.jupiter.api.Test; +import org.prism.ParsingOptions; import java.io.DataInputStream; import java.io.InputStream; From 80b7402f8ba8ea13a23dbafcb36484e1eee73bcd Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 4 Feb 2026 14:48:06 -0600 Subject: [PATCH 056/289] Rename Java package to org.ruby_lang.prism This moves all of the non-JRuby Java code from the org.prism package to the org.ruby_lang.prism package (corresponding to the ruby-lang.org domain and prism project). --- .gitignore | 6 +++--- docs/configuration.md | 6 +++--- docs/releasing.md | 6 +++--- java-wasm/perf-test/test | 2 +- .../src/main/java/org/jruby/parser/prism/wasm/Prism.java | 4 ++-- .../src/test/java/org/jruby/parser/prism/DummyTest.java | 4 ++-- .../src/test/java/org/jruby/parser/prism/JRubyTest.java | 2 +- java/org/{ => ruby_lang}/prism/MarkNewlinesVisitor.java | 2 +- java/org/{ => ruby_lang}/prism/ParseResult.java | 2 +- java/org/{ => ruby_lang}/prism/Parser.java | 2 +- java/org/{ => ruby_lang}/prism/ParsingOptions.java | 2 +- rakelib/serialization.rake | 2 +- .../org/{ => ruby_lang}/prism/AbstractNodeVisitor.java.erb | 2 +- templates/java/org/{ => ruby_lang}/prism/Loader.java.erb | 4 ++-- templates/java/org/{ => ruby_lang}/prism/Nodes.java.erb | 2 +- templates/template.rb | 6 +++--- 16 files changed, 27 insertions(+), 27 deletions(-) rename java/org/{ => ruby_lang}/prism/MarkNewlinesVisitor.java (98%) rename java/org/{ => ruby_lang}/prism/ParseResult.java (98%) rename java/org/{ => ruby_lang}/prism/Parser.java (92%) rename java/org/{ => ruby_lang}/prism/ParsingOptions.java (99%) rename templates/java/org/{ => ruby_lang}/prism/AbstractNodeVisitor.java.erb (94%) rename templates/java/org/{ => ruby_lang}/prism/Loader.java.erb (99%) rename templates/java/org/{ => ruby_lang}/prism/Nodes.java.erb (99%) diff --git a/.gitignore b/.gitignore index b00333f107..218a76cd00 100644 --- a/.gitignore +++ b/.gitignore @@ -39,9 +39,9 @@ out.svg /javascript/src/visitor.js /javascript/src/prism.wasm /javascript/src/*.d.ts -/java/org/prism/AbstractNodeVisitor.java -/java/org/prism/Loader.java -/java/org/prism/Nodes.java +/java/org/ruby_lang/prism/AbstractNodeVisitor.java +/java/org/ruby_lang/prism/Loader.java +/java/org/ruby_lang/prism/Nodes.java /lib/prism/compiler.rb /lib/prism/dispatcher.rb /lib/prism/dot_visitor.rb diff --git a/docs/configuration.md b/docs/configuration.md index 04887d6d9c..97e01c8d82 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -7,9 +7,9 @@ A lot of code in prism's repository is templated from a single configuration fil * `include/prism/diagnostic.h` - for defining the diagnostics * `javascript/src/deserialize.js` - for defining how to deserialize the nodes in JavaScript * `javascript/src/nodes.js` - for defining the nodes in JavaScript -* `java/org/prism/AbstractNodeVisitor.java` - for defining the visitor interface for the nodes in Java -* `java/org/prism/Loader.java` - for defining how to deserialize the nodes in Java -* `java/org/prism/Nodes.java` - for defining the nodes in Java +* `java/org/ruby_lang/prism/AbstractNodeVisitor.java` - for defining the visitor interface for the nodes in Java +* `java/org/ruby_lang/prism/Loader.java` - for defining how to deserialize the nodes in Java +* `java/org/ruby_lang/prism/Nodes.java` - for defining the nodes in Java * `lib/prism/compiler.rb` - for defining the compiler for the nodes in Ruby * `lib/prism/dispatcher.rb` - for defining the dispatch visitors for the nodes in Ruby * `lib/prism/dot_visitor.rb` - for defining the dot visitor for the nodes in Ruby diff --git a/docs/releasing.md b/docs/releasing.md index a7d3cf5eb3..6d0f892926 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -23,9 +23,9 @@ ruby -pi -e 'gsub(/PRISM_VERSION_PATCH \d+/, %Q{PRISM_VERSION_PATCH #{ENV["PRISM ruby -pi -e 'gsub(/PRISM_VERSION ".+?"/, %Q{PRISM_VERSION "#{ENV["PRISM_VERSION"]}"})' include/prism/version.h ruby -pi -e 'gsub(/"version": ".+?"/, %Q{"version": "#{ENV["PRISM_VERSION"]}"})' javascript/package.json ruby -pi -e 'gsub(/lossy\(\), ".+?"/, %Q{lossy(), "#{ENV["PRISM_VERSION"]}"})' rust/ruby-prism-sys/tests/utils_tests.rs -ruby -pi -e 'gsub(/\d+, "prism major/, %Q{#{ENV["PRISM_MAJOR"]}, "prism major})' templates/java/org/prism/Loader.java.erb -ruby -pi -e 'gsub(/\d+, "prism minor/, %Q{#{ENV["PRISM_MINOR"]}, "prism minor})' templates/java/org/prism/Loader.java.erb -ruby -pi -e 'gsub(/\d+, "prism patch/, %Q{#{ENV["PRISM_PATCH"]}, "prism patch})' templates/java/org/prism/Loader.java.erb +ruby -pi -e 'gsub(/\d+, "prism major/, %Q{#{ENV["PRISM_MAJOR"]}, "prism major})' templates/java/org/ruby_lang/prism/Loader.java.erb +ruby -pi -e 'gsub(/\d+, "prism minor/, %Q{#{ENV["PRISM_MINOR"]}, "prism minor})' templates/java/org/ruby_lang/prism/Loader.java.erb +ruby -pi -e 'gsub(/\d+, "prism patch/, %Q{#{ENV["PRISM_PATCH"]}, "prism patch})' templates/java/org/ruby_lang/prism/Loader.java.erb ruby -pi -e 'gsub(/MAJOR_VERSION = \d+/, %Q{MAJOR_VERSION = #{ENV["PRISM_MAJOR"]}})' templates/javascript/src/deserialize.js.erb ruby -pi -e 'gsub(/MINOR_VERSION = \d+/, %Q{MINOR_VERSION = #{ENV["PRISM_MINOR"]}})' templates/javascript/src/deserialize.js.erb ruby -pi -e 'gsub(/PATCH_VERSION = \d+/, %Q{PATCH_VERSION = #{ENV["PRISM_PATCH"]}})' templates/javascript/src/deserialize.js.erb diff --git a/java-wasm/perf-test/test b/java-wasm/perf-test/test index e2c8dfb575..f2d5492bc4 100755 --- a/java-wasm/perf-test/test +++ b/java-wasm/perf-test/test @@ -13,7 +13,7 @@ import java.util.EnumSet; import org.jruby.Ruby; import org.jruby.parser.prism.wasm.Prism; -import org.prism.ParsingOptions; +import org.ruby_lang.prism.ParsingOptions; public class test { diff --git a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java index dafba022e9..6dd89c70cb 100644 --- a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java +++ b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java @@ -6,8 +6,8 @@ import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasi.WasiOptions; import com.dylibso.chicory.wasi.WasiPreview1; -import org.prism.Loader; -import org.prism.ParseResult; +import org.ruby_lang.prism.Loader; +import org.ruby_lang.prism.ParseResult; import java.nio.charset.StandardCharsets; diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java index 5c12fb45a1..4e89f6f6e3 100644 --- a/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java @@ -2,8 +2,8 @@ import org.jruby.parser.prism.wasm.Prism; import org.junit.jupiter.api.Test; -import org.prism.ParseResult; -import org.prism.ParsingOptions; +import org.ruby_lang.prism.ParseResult; +import org.ruby_lang.prism.ParsingOptions; import java.util.EnumSet; diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java index 5b6364a926..b8249f4c70 100644 --- a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java @@ -3,7 +3,7 @@ import org.jruby.Ruby; import org.jruby.parser.prism.wasm.Prism; import org.junit.jupiter.api.Test; -import org.prism.ParsingOptions; +import org.ruby_lang.prism.ParsingOptions; import java.io.DataInputStream; import java.io.InputStream; diff --git a/java/org/prism/MarkNewlinesVisitor.java b/java/org/ruby_lang/prism/MarkNewlinesVisitor.java similarity index 98% rename from java/org/prism/MarkNewlinesVisitor.java rename to java/org/ruby_lang/prism/MarkNewlinesVisitor.java index 27ab8643e7..8d08424942 100644 --- a/java/org/prism/MarkNewlinesVisitor.java +++ b/java/org/ruby_lang/prism/MarkNewlinesVisitor.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; // Keep in sync with Ruby MarkNewlinesVisitor final class MarkNewlinesVisitor extends AbstractNodeVisitor { diff --git a/java/org/prism/ParseResult.java b/java/org/ruby_lang/prism/ParseResult.java similarity index 98% rename from java/org/prism/ParseResult.java rename to java/org/ruby_lang/prism/ParseResult.java index 144ea16e36..aad05a892d 100644 --- a/java/org/prism/ParseResult.java +++ b/java/org/ruby_lang/prism/ParseResult.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; // @formatter:off public final class ParseResult { diff --git a/java/org/prism/Parser.java b/java/org/ruby_lang/prism/Parser.java similarity index 92% rename from java/org/prism/Parser.java rename to java/org/ruby_lang/prism/Parser.java index 717c3e5179..5c60977d80 100644 --- a/java/org/prism/Parser.java +++ b/java/org/ruby_lang/prism/Parser.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; public abstract class Parser { diff --git a/java/org/prism/ParsingOptions.java b/java/org/ruby_lang/prism/ParsingOptions.java similarity index 99% rename from java/org/prism/ParsingOptions.java rename to java/org/ruby_lang/prism/ParsingOptions.java index be0a8a7dba..8990f72104 100644 --- a/java/org/prism/ParsingOptions.java +++ b/java/org/ruby_lang/prism/ParsingOptions.java @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; diff --git a/rakelib/serialization.rake b/rakelib/serialization.rake index a57a7ba700..499be443ce 100644 --- a/rakelib/serialization.rake +++ b/rakelib/serialization.rake @@ -26,7 +26,7 @@ task "test:java_loader:internal" => :compile do puts path serialized = Prism.dump_file(path) source_bytes = File.binread(path).unpack('c*') - parse_result = org.prism.Loader.load(serialized.unpack('c*'), source_bytes) + parse_result = org.ruby_lang.prism.Loader.load(serialized.unpack('c*'), source_bytes) puts parse_result.value end end diff --git a/templates/java/org/prism/AbstractNodeVisitor.java.erb b/templates/java/org/ruby_lang/prism/AbstractNodeVisitor.java.erb similarity index 94% rename from templates/java/org/prism/AbstractNodeVisitor.java.erb rename to templates/java/org/ruby_lang/prism/AbstractNodeVisitor.java.erb index a66daedf63..58eabebae8 100644 --- a/templates/java/org/prism/AbstractNodeVisitor.java.erb +++ b/templates/java/org/ruby_lang/prism/AbstractNodeVisitor.java.erb @@ -1,4 +1,4 @@ -package org.prism; +package org.ruby_lang.prism; // GENERATED BY <%= File.basename(__FILE__) %> // @formatter:off diff --git a/templates/java/org/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb similarity index 99% rename from templates/java/org/prism/Loader.java.erb rename to templates/java/org/ruby_lang/prism/Loader.java.erb index aa8e1e30c9..af47aeed73 100644 --- a/templates/java/org/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,7 +1,7 @@ <%- string_type = Prism::Template::JAVA_STRING_TYPE -%> -package org.prism; +package org.ruby_lang.prism; -import org.prism.Nodes; +import org.ruby_lang.prism.Nodes; import java.lang.Short; import java.math.BigInteger; diff --git a/templates/java/org/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb similarity index 99% rename from templates/java/org/prism/Nodes.java.erb rename to templates/java/org/ruby_lang/prism/Nodes.java.erb index 8b0a9ce20d..47b2ea0a7e 100644 --- a/templates/java/org/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -1,5 +1,5 @@ <%- string_type = Prism::Template::JAVA_STRING_TYPE -%> -package org.prism; +package org.ruby_lang.prism; import java.lang.Override; import java.lang.String; diff --git a/templates/template.rb b/templates/template.rb index 65e6ed0381..18da0647a0 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -724,9 +724,9 @@ def locals "javascript/src/deserialize.js", "javascript/src/nodes.js", "javascript/src/visitor.js", - "java/org/prism/Loader.java", - "java/org/prism/Nodes.java", - "java/org/prism/AbstractNodeVisitor.java", + "java/org/ruby_lang/prism/Loader.java", + "java/org/ruby_lang/prism/Nodes.java", + "java/org/ruby_lang/prism/AbstractNodeVisitor.java", "lib/prism/compiler.rb", "lib/prism/dispatcher.rb", "lib/prism/dot_visitor.rb", From 16674e519cdb6deb52691101e443b334e34ea757 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Sun, 18 Jan 2026 13:33:54 -0500 Subject: [PATCH 057/289] [rust] add support for accesing the list of line offsets --- rust/ruby-prism/src/lib.rs | 21 +++++++++++++++++++++ rust/ruby-prism/src/parse_result/mod.rs | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 6824768193..f628056b3e 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -65,6 +65,27 @@ mod tests { } } + #[test] + fn line_offsets_test() { + let source = ""; + let result = parse(source.as_ref()); + + let expected: [u32; 1] = [0]; + assert_eq!(expected, result.line_offsets()); + + let source = "1 + 1"; + let result = parse(source.as_ref()); + + let expected: [u32; 1] = [0]; + assert_eq!(expected, result.line_offsets()); + + let source = "begin\n1 + 1\n2 + 2\nend"; + let result = parse(source.as_ref()); + + let expected: [u32; 4] = [0, 6, 12, 18]; + assert_eq!(expected, result.line_offsets()); + } + #[test] fn magic_comments_test() { use crate::MagicComment; diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index 33eb1ac9a0..ab12f8be04 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -119,6 +119,15 @@ impl<'pr> ParseResult<'pr> { &self.source[start..end] } + /// Returns a slice containing the offsets of the start of each line in the source string + /// that was parsed. + #[must_use] + pub fn line_offsets(&self) -> &'pr [u32] { + unsafe { + let list = &(*self.parser.as_ptr()).line_offsets; + std::slice::from_raw_parts(list.offsets, list.size) + } + } /// Returns an iterator that can be used to iterate over the errors in the /// parse result. #[must_use] From b7e247ce6ae83e2d88c5ed6ee892e524a421931f Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:10:40 +0100 Subject: [PATCH 058/289] [Feature #19107] Allow trailing comma in method signature --- .../trailing_comma_after_method_arguments.txt | 207 ++++++++++++++++++ src/prism.c | 56 +++-- ...w_trailing_commas_in_method_parameters.txt | 0 ...ing_commas_after_terminating_arguments.txt | 6 + .../trailing_comma_after_method_arguments.txt | 15 ++ test/prism/fixtures_test.rb | 2 + test/prism/locals_test.rb | 3 + test/prism/ruby/ripper_test.rb | 2 + 8 files changed, 276 insertions(+), 15 deletions(-) create mode 100644 snapshots/4.1/trailing_comma_after_method_arguments.txt rename test/prism/errors/{ => 3.3-4.0}/do_not_allow_trailing_commas_in_method_parameters.txt (100%) create mode 100644 test/prism/errors/4.1/do_not_allow_trailing_commas_after_terminating_arguments.txt create mode 100644 test/prism/fixtures/4.1/trailing_comma_after_method_arguments.txt diff --git a/snapshots/4.1/trailing_comma_after_method_arguments.txt b/snapshots/4.1/trailing_comma_after_method_arguments.txt new file mode 100644 index 0000000000..b71459ff54 --- /dev/null +++ b/snapshots/4.1/trailing_comma_after_method_arguments.txt @@ -0,0 +1,207 @@ +@ ProgramNode (location: (1,0)-(15,5)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(15,5)) + ├── flags: ∅ + └── body: (length: 6) + ├── @ DefNode (location: (1,0)-(1,19)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (1,4)-(1,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (1,8)-(1,13)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 3) + │ │ │ ├── @ RequiredParameterNode (location: (1,8)-(1,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ ├── @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :b + │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :c + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b, :c] + │ ├── def_keyword_loc: (1,0)-(1,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (1,7)-(1,8) = "(" + │ ├── rparen_loc: (1,14)-(1,15) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (1,16)-(1,19) = "end" + ├── @ DefNode (location: (3,0)-(3,20)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (3,4)-(3,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (3,8)-(3,14)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (3,8)-(3,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (3,10)-(3,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: + │ │ │ @ RestParameterNode (location: (3,12)-(3,14)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :c + │ │ │ ├── name_loc: (3,13)-(3,14) = "c" + │ │ │ └── operator_loc: (3,12)-(3,13) = "*" + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b, :c] + │ ├── def_keyword_loc: (3,0)-(3,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (3,7)-(3,8) = "(" + │ ├── rparen_loc: (3,15)-(3,16) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (3,17)-(3,20) = "end" + ├── @ DefNode (location: (5,0)-(5,19)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (5,4)-(5,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (5,8)-(5,13)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (5,8)-(5,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (5,10)-(5,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: + │ │ │ @ RestParameterNode (location: (5,12)-(5,13)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: ∅ + │ │ │ ├── name_loc: ∅ + │ │ │ └── operator_loc: (5,12)-(5,13) = "*" + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b] + │ ├── def_keyword_loc: (5,0)-(5,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (5,7)-(5,8) = "(" + │ ├── rparen_loc: (5,14)-(5,15) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (5,16)-(5,19) = "end" + ├── @ DefNode (location: (7,0)-(7,21)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (7,4)-(7,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (7,8)-(7,15)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (7,8)-(7,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (7,10)-(7,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: + │ │ │ @ KeywordRestParameterNode (location: (7,12)-(7,15)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :c + │ │ │ ├── name_loc: (7,14)-(7,15) = "c" + │ │ │ └── operator_loc: (7,12)-(7,14) = "**" + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b, :c] + │ ├── def_keyword_loc: (7,0)-(7,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (7,7)-(7,8) = "(" + │ ├── rparen_loc: (7,16)-(7,17) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (7,18)-(7,21) = "end" + ├── @ DefNode (location: (9,0)-(9,20)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (9,4)-(9,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (9,8)-(9,14)) + │ │ ├── flags: ∅ + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (9,8)-(9,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (9,10)-(9,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: + │ │ │ @ KeywordRestParameterNode (location: (9,12)-(9,14)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: ∅ + │ │ │ ├── name_loc: ∅ + │ │ │ └── operator_loc: (9,12)-(9,14) = "**" + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b] + │ ├── def_keyword_loc: (9,0)-(9,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (9,7)-(9,8) = "(" + │ ├── rparen_loc: (9,15)-(9,16) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (9,17)-(9,20) = "end" + └── @ DefNode (location: (11,0)-(15,5)) + ├── flags: newline + ├── name: :foo + ├── name_loc: (11,4)-(11,7) = "foo" + ├── receiver: ∅ + ├── parameters: + │ @ ParametersNode (location: (12,2)-(14,3)) + │ ├── flags: ∅ + │ ├── requireds: (length: 3) + │ │ ├── @ RequiredParameterNode (location: (12,2)-(12,3)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :a + │ │ ├── @ RequiredParameterNode (location: (13,2)-(13,3)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :b + │ │ └── @ RequiredParameterNode (location: (14,2)-(14,3)) + │ │ ├── flags: ∅ + │ │ └── name: :c + │ ├── optionals: (length: 0) + │ ├── rest: ∅ + │ ├── posts: (length: 0) + │ ├── keywords: (length: 0) + │ ├── keyword_rest: ∅ + │ └── block: ∅ + ├── body: ∅ + ├── locals: [:a, :b, :c] + ├── def_keyword_loc: (11,0)-(11,3) = "def" + ├── operator_loc: ∅ + ├── lparen_loc: (11,7)-(11,8) = "(" + ├── rparen_loc: (15,0)-(15,1) = ")" + ├── equal_loc: ∅ + └── end_keyword_loc: (15,2)-(15,5) = "end" diff --git a/src/prism.c b/src/prism.c index 4465b4982e..7c6e3cfae4 100644 --- a/src/prism.c +++ b/src/prism.c @@ -13907,6 +13907,43 @@ update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_ord return true; } +static inline void +parse_parameters_handle_trailing_comma( + pm_parser_t *parser, + pm_parameters_node_t *params, + pm_parameters_order_t order, + bool in_block, + bool allows_trailing_comma +) { + if (!allows_trailing_comma) { + pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); + return; + } + + if (in_block) { + if (order >= PM_PARAMETERS_ORDER_NAMED) { + // foo do |bar,|; end + pm_node_t *param = UP(pm_implicit_rest_node_create(parser, &parser->previous)); + + if (params->rest == NULL) { + pm_parameters_node_rest_set(params, param); + } else { + pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI); + pm_parameters_node_posts_append(params, UP(param)); + } + } else { + // foo do |*bar,|; end + pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); + } + } else { + // https://bugs.ruby-lang.org/issues/19107 + // Allow `def foo(bar,); end`, `def foo(*bar,); end`, etc. but not `def foo(...,); end` + if (parser->version < PM_OPTIONS_VERSION_CRUBY_4_1 || order == PM_PARAMETERS_ORDER_NOTHING_AFTER) { + pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); + } + } +} + /** * Parse a list of parameters on a method definition. */ @@ -14255,20 +14292,7 @@ parse_parameters( } default: if (parser->previous.type == PM_TOKEN_COMMA) { - if (allows_trailing_comma && order >= PM_PARAMETERS_ORDER_NAMED) { - // If we get here, then we have a trailing comma in a - // block parameter list. - pm_node_t *param = UP(pm_implicit_rest_node_create(parser, &parser->previous)); - - if (params->rest == NULL) { - pm_parameters_node_rest_set(params, param); - } else { - pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI); - pm_parameters_node_posts_append(params, UP(param)); - } - } else { - pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA); - } + parse_parameters_handle_trailing_comma(parser, params, order, in_block, allows_trailing_comma); } parsing = false; @@ -18865,7 +18889,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { params = NULL; } else { - params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true, true, false, (uint16_t) (depth + 1)); + // https://bugs.ruby-lang.org/issues/19107 + bool allow_trailing_comma = parser->version >= PM_OPTIONS_VERSION_CRUBY_4_1; + params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, allow_trailing_comma, true, true, false, (uint16_t) (depth + 1)); } lex_state_set(parser, PM_LEX_STATE_BEG); diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt b/test/prism/errors/3.3-4.0/do_not_allow_trailing_commas_in_method_parameters.txt similarity index 100% rename from test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt rename to test/prism/errors/3.3-4.0/do_not_allow_trailing_commas_in_method_parameters.txt diff --git a/test/prism/errors/4.1/do_not_allow_trailing_commas_after_terminating_arguments.txt b/test/prism/errors/4.1/do_not_allow_trailing_commas_after_terminating_arguments.txt new file mode 100644 index 0000000000..b3e06f4154 --- /dev/null +++ b/test/prism/errors/4.1/do_not_allow_trailing_commas_after_terminating_arguments.txt @@ -0,0 +1,6 @@ +def foo(a,b,...,);end + ^ unexpected `,` in parameters + +def foo(a,b,&block,);end + ^ unexpected `,` in parameters + diff --git a/test/prism/fixtures/4.1/trailing_comma_after_method_arguments.txt b/test/prism/fixtures/4.1/trailing_comma_after_method_arguments.txt new file mode 100644 index 0000000000..ef1385d973 --- /dev/null +++ b/test/prism/fixtures/4.1/trailing_comma_after_method_arguments.txt @@ -0,0 +1,15 @@ +def foo(a,b,c,);end + +def foo(a,b,*c,);end + +def foo(a,b,*,);end + +def foo(a,b,**c,);end + +def foo(a,b,**,);end + +def foo( + a, + b, + c, +);end diff --git a/test/prism/fixtures_test.rb b/test/prism/fixtures_test.rb index 3a704b8389..dcbcb7c117 100644 --- a/test/prism/fixtures_test.rb +++ b/test/prism/fixtures_test.rb @@ -28,6 +28,8 @@ class FixturesTest < TestCase except << "command_method_call_2.txt" # https://bugs.ruby-lang.org/issues/21669 except << "4.1/void_value.txt" + # https://bugs.ruby-lang.org/issues/19107 + except << "4.1/trailing_comma_after_method_arguments.txt" Fixture.each_for_current_ruby(except: except) do |fixture| define_method(fixture.test_name) { assert_valid_syntax(fixture.read) } diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb index bcb964aff6..417730a8a7 100644 --- a/test/prism/locals_test.rb +++ b/test/prism/locals_test.rb @@ -31,6 +31,9 @@ class LocalsTest < TestCase # https://bugs.ruby-lang.org/issues/21669 "4.1/void_value.txt", + + # https://bugs.ruby-lang.org/issues/19107 + "4.1/trailing_comma_after_method_arguments.txt", ] Fixture.each_for_current_ruby(except: except) do |fixture| diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index 39cb9395ab..ba01732bcb 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -39,6 +39,8 @@ class RipperTest < TestCase # https://bugs.ruby-lang.org/issues/21669 incorrect << "4.1/void_value.txt" + # https://bugs.ruby-lang.org/issues/19107 + incorrect << "4.1/trailing_comma_after_method_arguments.txt" # Skip these tests that we haven't implemented yet. omitted_sexp_raw = [ From a8a7c6b77de24d3873d8e09c2dee86ad5d453478 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:54:40 +0100 Subject: [PATCH 059/289] Preserve line-continuation only in dedent heredocs Closes https://github.com/ruby/prism/issues/3837 While these lines are whitespace only from a runtime perspective, the line continuation is significant for AST consumers. Sort of a followup to https://github.com/ruby/prism/commit/faab217d9382186133862ce4d5ba9a9e090a9550 --- .../heredoc_dedent_line_continuation.txt | 30 +++++++++++++++++++ src/prism.c | 18 +++++++++-- .../heredoc_dedent_line_continuation.txt | 5 ++++ test/prism/ruby/ruby_parser_test.rb | 1 + 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 snapshots/heredoc_dedent_line_continuation.txt create mode 100644 test/prism/fixtures/heredoc_dedent_line_continuation.txt diff --git a/snapshots/heredoc_dedent_line_continuation.txt b/snapshots/heredoc_dedent_line_continuation.txt new file mode 100644 index 0000000000..d0c29ef2a2 --- /dev/null +++ b/snapshots/heredoc_dedent_line_continuation.txt @@ -0,0 +1,30 @@ +@ ProgramNode (location: (1,0)-(1,6)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(1,6)) + ├── flags: ∅ + └── body: (length: 1) + └── @ InterpolatedStringNode (location: (1,0)-(1,6)) + ├── flags: newline + ├── opening_loc: (1,0)-(1,6) = "<<~FOO" + ├── parts: (length: 3) + │ ├── @ StringNode (location: (2,0)-(3,0)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (2,0)-(3,0) = " foo\\\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "foo" + │ ├── @ StringNode (location: (3,0)-(4,0)) + │ │ ├── flags: static_literal, frozen + │ │ ├── opening_loc: ∅ + │ │ ├── content_loc: (3,0)-(4,0) = " \\\n" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "" + │ └── @ StringNode (location: (4,0)-(5,0)) + │ ├── flags: static_literal, frozen + │ ├── opening_loc: ∅ + │ ├── content_loc: (4,0)-(5,0) = " bar\n" + │ ├── closing_loc: ∅ + │ └── unescaped: "bar\n" + └── closing_loc: (5,0)-(6,0) = "FOO\n" diff --git a/src/prism.c b/src/prism.c index 7c6e3cfae4..4ab1ca4594 100644 --- a/src/prism.c +++ b/src/prism.c @@ -15957,6 +15957,19 @@ parse_heredoc_dedent_string(pm_string_t *string, size_t common_whitespace) { string->length = dest_length; } +/** + * If we end up trimming all of the whitespace from a node and it isn't + * part of a line continuation, then we'll drop it from the list entirely. + */ +static inline bool +heredoc_dedent_discard_string_node(pm_parser_t *parser, pm_string_node_t *string_node) { + if (string_node->unescaped.length == 0) { + const uint8_t *cursor = parser->start + PM_LOCATION_START(&string_node->content_loc); + return pm_memchr(cursor, '\\', string_node->content_loc.length, parser->encoding_changed, parser->encoding) == NULL; + } + return false; +} + /** * Take a heredoc node that is indented by a ~ and trim the leading whitespace. */ @@ -15967,8 +15980,7 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w bool dedent_next = true; // Iterate over all nodes, and trim whitespace accordingly. We're going to - // keep around two indices: a read and a write. If we end up trimming all of - // the whitespace from a node, then we'll drop it from the list entirely. + // keep around two indices: a read and a write. size_t write_index = 0; pm_node_t *node; @@ -15987,7 +15999,7 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w parse_heredoc_dedent_string(&string_node->unescaped, common_whitespace); } - if (string_node->unescaped.length == 0) { + if (heredoc_dedent_discard_string_node(parser, string_node)) { pm_node_destroy(parser, node); } else { nodes->nodes[write_index++] = node; diff --git a/test/prism/fixtures/heredoc_dedent_line_continuation.txt b/test/prism/fixtures/heredoc_dedent_line_continuation.txt new file mode 100644 index 0000000000..661db490c7 --- /dev/null +++ b/test/prism/fixtures/heredoc_dedent_line_continuation.txt @@ -0,0 +1,5 @@ +<<~FOO + foo\ + \ + bar +FOO diff --git a/test/prism/ruby/ruby_parser_test.rb b/test/prism/ruby/ruby_parser_test.rb index 25107978f3..bc89bdae72 100644 --- a/test/prism/ruby/ruby_parser_test.rb +++ b/test/prism/ruby/ruby_parser_test.rb @@ -37,6 +37,7 @@ class RubyParserTest < TestCase "alias.txt", "dsym_str.txt", "dos_endings.txt", + "heredoc_dedent_line_continuation.txt", "heredoc_percent_q_newline_delimiter.txt", "heredocs_with_fake_newlines.txt", "heredocs_with_ignored_newlines.txt", From 3b3d236078bccdf39b0259dd2ee017ef36eda603 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:35:38 +0000 Subject: [PATCH 060/289] Bump the java-deps group in /java-wasm with 2 updates Bumps the java-deps group in /java-wasm with 2 updates: org.jruby:jruby-complete and [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire). Updates `org.jruby:jruby-complete` from 10.0.2.0 to 10.0.3.0 Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.5.4 to 3.5.5 - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.4...surefire-3.5.5) --- updated-dependencies: - dependency-name: org.jruby:jruby-complete dependency-version: 10.0.3.0 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: java-deps - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-version: 3.5.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: java-deps ... Signed-off-by: dependabot[bot] --- java-wasm/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 587e094ab7..b37e86090d 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -62,7 +62,7 @@ org.jruby jruby-complete - 10.0.2.0 + 10.0.3.0 @@ -99,7 +99,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.4 + 3.5.5 org.codehaus.mojo From 64e29baac6bbf9004eba3de6dba05afbe90dae82 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 23 Feb 2026 13:53:43 +0100 Subject: [PATCH 061/289] Fix some locations in the the config --- config.yml | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/config.yml b/config.yml index 7527e01070..472ab291a7 100644 --- a/config.yml +++ b/config.yml @@ -1046,19 +1046,19 @@ nodes: Represents an array pattern in pattern matching. foo in 1, 2 - ^^^^^^^^^^^ + ^^^^ foo in [1, 2] - ^^^^^^^^^^^^^ + ^^^^^^ foo in *bar - ^^^^^^^^^^^ + ^^^^ foo in Bar[] - ^^^^^^^^^^^^ + ^^^^^ foo in Bar[1, 2, 3] - ^^^^^^^^^^^^^^^^^^^ + ^^^^^^^^^^^^ - name: AssocNode fields: - name: key @@ -1167,7 +1167,7 @@ nodes: Represents the else clause within the begin block. begin x; rescue y; else z; end - ^^^^^^ + ^^^^^^^^^^^ - name: ensure_clause type: node? kind: EnsureNode @@ -1200,7 +1200,7 @@ nodes: The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). foo(&args) - ^^^^^ + ^^^^ - name: operator_loc type: location comment: | @@ -1212,7 +1212,7 @@ nodes: Represents a block argument using `&`. bar(&args) - ^^^^^^^^^^ + ^^^^^ - name: BlockLocalVariableNode flags: ParameterFlags fields: @@ -1753,7 +1753,7 @@ nodes: Represents assigning to a local variable in pattern matching. foo => [bar => baz] - ^^^^^^^^^^^^ + ^^^^^^^^^^ - name: CaseMatchNode fields: - name: predicate @@ -1763,7 +1763,7 @@ nodes: Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). case true; in false; end - ^^^^ + ^^^^ - name: conditions type: node[] kind: InNode @@ -1779,7 +1779,7 @@ nodes: Represents the else clause of the case match. case true; in false; else; end - ^^^^ + ^^^^^^^^^ - name: case_keyword_loc type: location comment: | @@ -1826,7 +1826,7 @@ nodes: Represents the else clause of the case statement. case true; when false; else; end - ^^^^ + ^^^^^^^^^ - name: case_keyword_loc type: location comment: | @@ -1888,9 +1888,8 @@ nodes: comment: | Represents the body of the class. - class Foo - foo - ^^^ + class Foo; bar; end + ^^^ - name: end_keyword_loc type: location comment: | @@ -4635,7 +4634,7 @@ nodes: The else clause of the unless expression, if present. unless cond then bar else baz end - ^^^^^^^^ + ^^^^^^^^^^^^ - name: end_keyword_loc type: location? comment: | From cbe9692229ca94001b2663893beee8a0e13fd592 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:43:10 +0000 Subject: [PATCH 062/289] Bump the ruby-deps group across 9 directories with 1 update Bumps the ruby-deps group with 1 update in the /gemfiles/2.7 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/3.0 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/3.1 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/3.2 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/3.3 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/3.4 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/4.0 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/4.1 directory: [parser](https://github.com/whitequark/parser). Bumps the ruby-deps group with 1 update in the /gemfiles/typecheck directory: [parser](https://github.com/whitequark/parser). Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) Updates `parser` from 3.3.10.1 to 3.3.10.2 - [Changelog](https://github.com/whitequark/parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/whitequark/parser/compare/v3.3.10.1...v3.3.10.2) --- updated-dependencies: - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps - dependency-name: parser dependency-version: 3.3.10.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps ... Signed-off-by: dependabot[bot] --- gemfiles/2.7/Gemfile.lock | 2 +- gemfiles/3.0/Gemfile.lock | 2 +- gemfiles/3.1/Gemfile.lock | 2 +- gemfiles/3.2/Gemfile.lock | 2 +- gemfiles/3.3/Gemfile.lock | 2 +- gemfiles/3.4/Gemfile.lock | 2 +- gemfiles/4.0/Gemfile.lock | 2 +- gemfiles/4.1/Gemfile.lock | 2 +- gemfiles/typecheck/Gemfile.lock | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gemfiles/2.7/Gemfile.lock b/gemfiles/2.7/Gemfile.lock index fd5d5e89c8..7eab6a5528 100644 --- a/gemfiles/2.7/Gemfile.lock +++ b/gemfiles/2.7/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/3.0/Gemfile.lock b/gemfiles/3.0/Gemfile.lock index 532d7e61f7..d295f1f173 100644 --- a/gemfiles/3.0/Gemfile.lock +++ b/gemfiles/3.0/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/3.1/Gemfile.lock b/gemfiles/3.1/Gemfile.lock index ed479ba08d..3b242f5c3c 100644 --- a/gemfiles/3.1/Gemfile.lock +++ b/gemfiles/3.1/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/3.2/Gemfile.lock b/gemfiles/3.2/Gemfile.lock index b1b1a89735..661e0434d9 100644 --- a/gemfiles/3.2/Gemfile.lock +++ b/gemfiles/3.2/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/3.3/Gemfile.lock b/gemfiles/3.3/Gemfile.lock index 7227459626..55d0a9103d 100644 --- a/gemfiles/3.3/Gemfile.lock +++ b/gemfiles/3.3/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/3.4/Gemfile.lock b/gemfiles/3.4/Gemfile.lock index 56910904e1..6857ef7c0b 100644 --- a/gemfiles/3.4/Gemfile.lock +++ b/gemfiles/3.4/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/4.0/Gemfile.lock b/gemfiles/4.0/Gemfile.lock index 3cf2bf99ab..8514c58291 100644 --- a/gemfiles/4.0/Gemfile.lock +++ b/gemfiles/4.0/Gemfile.lock @@ -8,7 +8,7 @@ GEM specs: ast (2.4.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/4.1/Gemfile.lock b/gemfiles/4.1/Gemfile.lock index 62a55c4f79..db51633a6d 100644 --- a/gemfiles/4.1/Gemfile.lock +++ b/gemfiles/4.1/Gemfile.lock @@ -9,7 +9,7 @@ GEM ast (2.4.3) ffi (1.17.3) onigmo (0.1.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index 8ebb8670e7..2d057171a0 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -39,7 +39,7 @@ GEM mutex_m (0.3.0) netrc (0.11.0) parallel (1.27.0) - parser (3.3.10.1) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) From a5c3ee3e4c1f2de540eafed5bff83828fe6ebd32 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Sun, 1 Feb 2026 18:32:16 +0100 Subject: [PATCH 063/289] Introduce xfree_sized and xrealloc_sized This will allow prism to pass buffer sizes to the Ruby GC. It also helps avoid buffer overflow as it confirms the size was correctly tracked all the way until the buffer is freed. --- Doxyfile | 1 + ext/prism/extension.c | 4 +- include/prism/debug_allocator.h | 99 ++++++++++++++++++++++++++++++ include/prism/defines.h | 32 ++++++++-- prism.gemspec | 1 + src/options.c | 4 +- src/prism.c | 53 ++++++++-------- src/static_literals.c | 4 +- src/util/pm_buffer.c | 5 +- src/util/pm_constant_pool.c | 19 +++--- src/util/pm_integer.c | 17 ++--- src/util/pm_line_offset_list.c | 4 +- src/util/pm_list.c | 2 +- src/util/pm_string.c | 15 ++--- templates/ext/prism/api_node.c.erb | 2 +- templates/src/diagnostic.c.erb | 4 +- templates/src/node.c.erb | 10 ++- 17 files changed, 207 insertions(+), 69 deletions(-) create mode 100644 include/prism/debug_allocator.h diff --git a/Doxyfile b/Doxyfile index 8827dea28d..4ea648ed7a 100644 --- a/Doxyfile +++ b/Doxyfile @@ -24,6 +24,7 @@ OUTPUT_DIRECTORY = doc JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES INPUT = src src/util include include/prism include/prism/util +EXCLUDE = include/prism/debug_allocator.h HTML_OUTPUT = c SORT_MEMBER_DOCS = NO GENERATE_LATEX = NO diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 03182c1a57..fcbc1e6c24 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -413,7 +413,7 @@ dump(int argc, VALUE *argv, VALUE self) { if (options.freeze) rb_obj_freeze(value); #ifdef PRISM_BUILD_DEBUG - xfree(dup); + xfree_sized(dup, length); #endif pm_string_free(&input); @@ -929,7 +929,7 @@ parse(int argc, VALUE *argv, VALUE self) { VALUE value = parse_input(&input, &options); #ifdef PRISM_BUILD_DEBUG - xfree(dup); + xfree_sized(dup, length); #endif pm_string_free(&input); diff --git a/include/prism/debug_allocator.h b/include/prism/debug_allocator.h new file mode 100644 index 0000000000..3e28a95efb --- /dev/null +++ b/include/prism/debug_allocator.h @@ -0,0 +1,99 @@ +/** + * @file debug_allocator.h + * + * Decorate allocation function to ensure sizes are correct. + */ +#ifndef PRISM_DEBUG_ALLOCATOR_H +#define PRISM_DEBUG_ALLOCATOR_H + +#include +#include +#include + +static inline void * +pm_debug_malloc(size_t size) +{ + size_t *memory = xmalloc(size + sizeof(size_t)); + memory[0] = size; + return memory + 1; +} + +static inline void * +pm_debug_calloc(size_t nmemb, size_t size) +{ + size_t total_size = nmemb * size; + void *ptr = pm_debug_malloc(total_size); + memset(ptr, 0, total_size); + return ptr; +} + +static inline void * +pm_debug_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) { + return pm_debug_malloc(size); + } + + size_t *memory = (size_t *)ptr; + void *raw_memory = memory - 1; + memory = (size_t *)xrealloc(raw_memory, size + sizeof(size_t)); + memory[0] = size; + return memory + 1; +} + +static inline void +pm_debug_free(void *ptr) +{ + if (ptr != NULL) { + size_t *memory = (size_t *)ptr; + xfree(memory - 1); + } +} + +static inline void +pm_debug_free_sized(void *ptr, size_t old_size) +{ + if (ptr != NULL) { + size_t *memory = (size_t *)ptr; + if (old_size != memory[-1]) { + fprintf(stderr, "[BUG] buffer %p was allocated with size %lu but freed with size %lu\n", ptr, memory[-1], old_size); + abort(); + } + xfree_sized(memory - 1, old_size + sizeof(size_t)); + } +} + +static inline void * +pm_debug_realloc_sized(void *ptr, size_t size, size_t old_size) +{ + if (ptr == NULL) { + if (old_size != 0) { + fprintf(stderr, "[BUG] realloc_sized called with NULL pointer and old size %lu\n", old_size); + abort(); + } + return pm_debug_malloc(size); + } + + size_t *memory = (size_t *)ptr; + if (old_size != memory[-1]) { + fprintf(stderr, "[BUG] buffer %p was allocated with size %lu but realloced with size %lu\n", ptr, memory[-1], old_size); + abort(); + } + return pm_debug_realloc(ptr, size); +} + +#undef xmalloc +#undef xrealloc +#undef xcalloc +#undef xfree +#undef xrealloc_sized +#undef xfree_sized + +#define xmalloc pm_debug_malloc +#define xrealloc pm_debug_realloc +#define xcalloc pm_debug_calloc +#define xfree pm_debug_free +#define xrealloc_sized pm_debug_realloc_sized +#define xfree_sized pm_debug_free_sized + +#endif diff --git a/include/prism/defines.h b/include/prism/defines.h index f2e814fa1d..1c4e5fa053 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -161,10 +161,12 @@ * ``` * #ifndef PRISM_XALLOCATOR_H * #define PRISM_XALLOCATOR_H - * #define xmalloc my_malloc - * #define xrealloc my_realloc - * #define xcalloc my_calloc - * #define xfree my_free + * #define xmalloc my_malloc + * #define xrealloc my_realloc + * #define xcalloc my_calloc + * #define xfree my_free + * #define xrealloc_sized my_realloc_sized // (optional) + * #define xfree_sized my_free_sized // (optional) * #endif * ``` */ @@ -204,6 +206,28 @@ #endif #endif +#ifndef xfree_sized +/** + * The free_sized function that should be used. This can be overridden with the + * PRISM_XALLOCATOR define. + * If not defined, defaults to calling xfree. + */ + #define xfree_sized(p, s) xfree(((void)(s), (p))) +#endif + +#ifndef xrealloc_sized +/** + * The xrealloc_sized function that should be used. This can be overridden with the + * PRISM_XALLOCATOR define. + * If not defined, defaults to calling xrealloc. + */ + #define xrealloc_sized(p, ns, os) xrealloc((p), ((void)(os), (ns))) +#endif + +#ifdef PRISM_BUILD_DEBUG + #include "prism/debug_allocator.h" +#endif + /** * If PRISM_BUILD_MINIMAL is defined, then we're going to define every possible * switch that will turn off certain features of prism. diff --git a/prism.gemspec b/prism.gemspec index a155dc3da4..dde7e711e2 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -48,6 +48,7 @@ Gem::Specification.new do |spec| "ext/prism/extension.h", "include/prism.h", "include/prism/ast.h", + "include/prism/debug_allocator.h", "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", diff --git a/src/options.c b/src/options.c index 09d2a65a6c..961d52330f 100644 --- a/src/options.c +++ b/src/options.c @@ -226,10 +226,10 @@ pm_options_free(pm_options_t *options) { pm_string_free(&scope->locals[local_index]); } - xfree(scope->locals); + xfree_sized(scope->locals, scope->locals_count * sizeof(pm_string_t)); } - xfree(options->scopes); + xfree_sized(options->scopes, options->scopes_count * sizeof(pm_options_scope_t)); } /** diff --git a/src/prism.c b/src/prism.c index 4ab1ca4594..bfa91f4296 100644 --- a/src/prism.c +++ b/src/prism.c @@ -286,7 +286,7 @@ lex_mode_pop(pm_parser_t *parser) { } else { parser->lex_modes.index--; pm_lex_mode_t *prev = parser->lex_modes.current->prev; - xfree(parser->lex_modes.current); + xfree_sized(parser->lex_modes.current, sizeof(pm_lex_mode_t)); parser->lex_modes.current = prev; } } @@ -777,7 +777,7 @@ pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constan static void pm_locals_free(pm_locals_t *locals) { if (locals->capacity > 0) { - xfree(locals->locals); + xfree_sized(locals->locals, locals->capacity * sizeof(pm_local_t)); } } @@ -2956,7 +2956,7 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3010,7 +3010,7 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3040,7 +3040,7 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3071,7 +3071,7 @@ pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3101,7 +3101,7 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3132,7 +3132,7 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3164,7 +3164,7 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3192,7 +3192,7 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { // Here we're going to free the target, since it is no longer necessary. // However, we don't want to call `pm_node_destroy` because we want to keep // around all of its children since we just reused them. - xfree(target); + xfree_sized(target, sizeof(pm_call_node_t)); return node; } @@ -3873,7 +3873,8 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { // First, get a buffer of the content. size_t length = (size_t) diff; - char *buffer = xmalloc(sizeof(char) * (length + 1)); + const size_t buffer_size = sizeof(char) * (length + 1); + char *buffer = xmalloc(buffer_size); memcpy((void *) buffer, token->start, length); // Next, determine if we need to replace the decimal point because of @@ -3908,7 +3909,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { // is in a valid format. However it's good to be safe. if ((eptr != buffer + length) || (errno != 0 && errno != ERANGE)) { PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, token, PM_ERR_FLOAT_PARSE); - xfree((void *) buffer); + xfree_sized(buffer, buffer_size); return 0.0; } @@ -3931,7 +3932,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { } // Finally we can free the buffer and return the value. - xfree((void *) buffer); + xfree_sized(buffer, buffer_size); return value; } @@ -4017,7 +4018,7 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) { digits[0] = '1'; if (fract_length > 1) memset(digits + 1, '0', fract_length - 1); pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + fract_length); - xfree(digits); + xfree_sized(digits, length); pm_integers_reduce(&node->numerator, &node->denominator); return node; @@ -5521,7 +5522,7 @@ pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, // Explicitly do not call pm_node_destroy here because we want to keep // around all of the information within the MultiWriteNode node. - xfree(target); + xfree_sized(target, sizeof(pm_multi_target_node_t)); return node; } @@ -5646,7 +5647,7 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to value = 0; } - xfree(digits); + xfree_sized(digits, sizeof(char) * (length + 1)); if ((errno == ERANGE) || (value > NTH_REF_MAX)) { PM_PARSER_WARN_FORMAT(parser, U32(start - parser->start), U32(length), PM_WARN_INVALID_NUMBERED_REFERENCE, (int) (length + 1), (const char *) token->start); @@ -6751,7 +6752,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const // We are explicitly _not_ using pm_node_destroy here because we don't want // to trash the unescaped string. We could instead copy the string if we // know that it is owned, but we're taking the fast path for now. - xfree(node); + xfree_sized(node, sizeof(pm_string_node_t)); return new_node; } @@ -6784,7 +6785,7 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { // We are explicitly _not_ using pm_node_destroy here because we don't want // to trash the unescaped string. We could instead copy the string if we // know that it is owned, but we're taking the fast path for now. - xfree(node); + xfree_sized(node, sizeof(pm_symbol_node_t)); return new_node; } @@ -7247,7 +7248,7 @@ pm_parser_scope_pop(pm_parser_t *parser) { parser->current_scope = scope->previous; pm_locals_free(&scope->locals); pm_node_list_free(&scope->implicit_parameters); - xfree(scope); + xfree_sized(scope, sizeof(pm_scope_t)); } /******************************************************************************/ @@ -7847,7 +7848,7 @@ context_push(pm_parser_t *parser, pm_context_t context) { static void context_pop(pm_parser_t *parser) { pm_context_node_t *prev = parser->current_context->prev; - xfree(parser->current_context); + xfree_sized(parser->current_context, sizeof(pm_context_node_t)); parser->current_context = prev; } @@ -16639,7 +16640,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node } pm_hash_pattern_node_t *node = pm_hash_pattern_node_node_list_create(parser, &assocs, rest); - xfree(assocs.nodes); + xfree_sized(assocs.nodes, assocs.capacity * sizeof(pm_node_t *)); pm_static_literals_free(&keys); return node; @@ -17166,7 +17167,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag } } - xfree(nodes.nodes); + xfree_sized(nodes.nodes, nodes.capacity * sizeof(pm_node_t *)); } else if (leading_rest) { // Otherwise, if we parsed a single splat pattern, then we know we have // an array pattern, so we can go ahead and create that node. @@ -19453,7 +19454,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_symbol_node_append(interpolated, first_string); pm_interpolated_symbol_node_append(interpolated, second_string); - xfree(current); + xfree_sized(current, sizeof(pm_symbol_node_t)); current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19538,7 +19539,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_symbol_node_append(interpolated, first_string); pm_interpolated_symbol_node_append(interpolated, second_string); - xfree(current); + xfree_sized(current, sizeof(pm_symbol_node_t)); current = UP(interpolated); } else { assert(false && "unreachable"); @@ -22252,7 +22253,7 @@ pm_comment_list_free(pm_list_t *list) { next = node->next; pm_comment_t *comment = (pm_comment_t *) node; - xfree(comment); + xfree_sized(comment, sizeof(pm_comment_t)); } } @@ -22267,7 +22268,7 @@ pm_magic_comment_list_free(pm_list_t *list) { next = node->next; pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) node; - xfree(magic_comment); + xfree_sized(magic_comment, sizeof(pm_magic_comment_t)); } } diff --git a/src/static_literals.c b/src/static_literals.c index 58a08a8c03..f3a5650d31 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -183,7 +183,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m } // Finally, free the old node list and update the hash. - xfree(hash->nodes); + xfree_sized(hash->nodes, hash->capacity * sizeof(pm_node_t *)); hash->nodes = new_nodes; hash->capacity = new_capacity; } @@ -221,7 +221,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m */ static void pm_node_hash_free(pm_node_hash_t *hash) { - if (hash->capacity > 0) xfree(hash->nodes); + if (hash->capacity > 0) xfree_sized(hash->nodes, hash->capacity * sizeof(pm_node_t *)); } /** diff --git a/src/util/pm_buffer.c b/src/util/pm_buffer.c index 2136a7c43e..9e392427c6 100644 --- a/src/util/pm_buffer.c +++ b/src/util/pm_buffer.c @@ -50,6 +50,7 @@ pm_buffer_length(const pm_buffer_t *buffer) { static inline bool pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { size_t next_length = buffer->length + length; + const size_t original_capacity = buffer->capacity; if (next_length > buffer->capacity) { if (buffer->capacity == 0) { @@ -60,7 +61,7 @@ pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { buffer->capacity *= 2; } - buffer->value = xrealloc(buffer->value, buffer->capacity); + buffer->value = xrealloc_sized(buffer->value, buffer->capacity, original_capacity); if (buffer->value == NULL) return false; } @@ -353,5 +354,5 @@ pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t le */ void pm_buffer_free(pm_buffer_t *buffer) { - xfree(buffer->value); + xfree_sized(buffer->value, buffer->capacity); } diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index 922ce6a18c..bde7f959ea 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -33,8 +33,13 @@ pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity) bool pm_constant_id_list_append(pm_constant_id_list_t *list, pm_constant_id_t id) { if (list->size >= list->capacity) { + const size_t original_capacity = list->capacity; list->capacity = list->capacity == 0 ? 8 : list->capacity * 2; - list->ids = (pm_constant_id_t *) xrealloc(list->ids, sizeof(pm_constant_id_t) * list->capacity); + list->ids = (pm_constant_id_t *) xrealloc_sized( + list->ids, + sizeof(pm_constant_id_t) * list->capacity, + sizeof(pm_constant_id_t) * original_capacity + ); if (list->ids == NULL) return false; } @@ -71,7 +76,7 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) { void pm_constant_id_list_free(pm_constant_id_list_t *list) { if (list->ids != NULL) { - xfree(list->ids); + xfree_sized(list->ids, list->capacity * sizeof(pm_constant_id_t)); } } @@ -165,7 +170,7 @@ pm_constant_pool_resize(pm_constant_pool_t *pool) { // pool->constants and pool->buckets are allocated out of the same chunk // of memory, with the buckets coming first. - xfree(pool->buckets); + xfree_sized(pool->buckets, pool->capacity * element_size); pool->constants = next_constants; pool->buckets = next_buckets; pool->capacity = next_capacity; @@ -257,12 +262,12 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l // an existing constant, then either way we don't want the given // memory. Either it's duplicated with the existing constant or // it's not necessary because we have a shared version. - xfree((void *) start); + xfree_sized((void *) start, length); } else if (bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { // If we're attempting to insert a shared constant and the // existing constant is owned, then we can free the owned // constant and replace it with the shared constant. - xfree((void *) constant->start); + xfree_sized((void *) constant->start, constant->length); constant->start = start; bucket->type = (unsigned int) (type & 0x3); } @@ -334,9 +339,9 @@ pm_constant_pool_free(pm_constant_pool_t *pool) { // If an id is set on this constant, then we know we have content here. if (bucket->id != PM_CONSTANT_ID_UNSET && bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { pm_constant_t *constant = &pool->constants[bucket->id - 1]; - xfree((void *) constant->start); + xfree_sized((void *) constant->start, constant->length); } } - xfree(pool->buckets); + xfree_sized(pool->buckets, pool->capacity * (sizeof(pm_constant_pool_bucket_t) + sizeof(pm_constant_t))); } diff --git a/src/util/pm_integer.c b/src/util/pm_integer.c index 4170ecc58d..2b77a4b5d2 100644 --- a/src/util/pm_integer.c +++ b/src/util/pm_integer.c @@ -374,7 +374,7 @@ pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, u } } - xfree(bigints); + xfree_sized(bigints, bigints_length * sizeof(pm_integer_t)); bigints = next_bigints; bigints_length = next_length; } @@ -383,7 +383,7 @@ pm_integer_convert_base(pm_integer_t *destination, const pm_integer_t *source, u destination->negative = source->negative; pm_integer_normalize(destination); - xfree(bigints); + xfree_sized(bigints, bigints_length * sizeof(pm_integer_t)); pm_integer_free(&base); } @@ -422,7 +422,7 @@ pm_integer_parse_powof2(pm_integer_t *integer, uint32_t base, const uint8_t *dig static void pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t digits_length) { const size_t batch = 9; - size_t length = (digits_length + batch - 1) / batch; + const size_t length = (digits_length + batch - 1) / batch; uint32_t *values = (uint32_t *) xcalloc(length, sizeof(uint32_t)); uint32_t value = 0; @@ -439,7 +439,7 @@ pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t di // Convert base from 10**9 to 1<<32. pm_integer_convert_base(integer, &((pm_integer_t) { .length = length, .values = values, .value = 0, .negative = false }), 1000000000, ((uint64_t) 1 << 32)); - xfree(values); + xfree_sized(values, length * sizeof(uint32_t)); } /** @@ -448,7 +448,8 @@ pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t di static void pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t *start, const uint8_t *end) { // Allocate an array to store digits. - uint8_t *digits = xmalloc(sizeof(uint8_t) * (size_t) (end - start)); + const size_t digits_capa = sizeof(uint8_t) * (size_t) (end - start); + uint8_t *digits = xmalloc(digits_capa); size_t digits_length = 0; for (; start < end; start++) { @@ -463,7 +464,7 @@ pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t * pm_integer_parse_powof2(integer, multiplier, digits, digits_length); } - xfree(digits); + xfree_sized(digits, digits_capa); } /** @@ -635,7 +636,7 @@ pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { } // Allocate a buffer that we'll copy the decimal digits into. - size_t digits_length = converted.length * 9; + const size_t digits_length = converted.length * 9; char *digits = xcalloc(digits_length, sizeof(char)); if (digits == NULL) return; @@ -654,7 +655,7 @@ pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { // Finally, append the string to the buffer and free the digits. pm_buffer_append_string(buffer, digits + start_offset, digits_length - start_offset); - xfree(digits); + xfree_sized(digits, sizeof(char) * digits_length); pm_integer_free(&converted); } diff --git a/src/util/pm_line_offset_list.c b/src/util/pm_line_offset_list.c index 710fa4b788..d55b2f6874 100644 --- a/src/util/pm_line_offset_list.c +++ b/src/util/pm_line_offset_list.c @@ -39,7 +39,7 @@ pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor) { if (list->offsets == NULL) return false; memcpy(list->offsets, original_offsets, list->size * sizeof(uint32_t)); - xfree(original_offsets); + xfree_sized(original_offsets, list->size * sizeof(uint32_t)); } assert(list->size == 0 || cursor > list->offsets[list->size - 1]); @@ -109,5 +109,5 @@ pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t curs */ void pm_line_offset_list_free(pm_line_offset_list_t *list) { - xfree(list->offsets); + xfree_sized(list->offsets, list->capacity * sizeof(uint32_t)); } diff --git a/src/util/pm_list.c b/src/util/pm_list.c index ad2294cd60..940baffb64 100644 --- a/src/util/pm_list.c +++ b/src/util/pm_list.c @@ -41,7 +41,7 @@ pm_list_free(pm_list_t *list) { while (node != NULL) { next = node->next; - xfree(node); + xfree_sized(node, sizeof(pm_list_node_t)); node = next; } diff --git a/src/util/pm_string.c b/src/util/pm_string.c index a7493c468b..5ba8c78ec1 100644 --- a/src/util/pm_string.c +++ b/src/util/pm_string.c @@ -71,9 +71,10 @@ pm_string_file_handle_open(pm_string_file_handle_t *handle, const char *filepath int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0); if (length == 0) return PM_STRING_INIT_ERROR_GENERIC; - handle->path = xmalloc(sizeof(WCHAR) * ((size_t) length)); + const size_t path_size = sizeof(WCHAR) * ((size_t) length); + handle->path = xmalloc(path_size); if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) { - xfree(handle->path); + xfree_sized(handle->path, path_size); return PM_STRING_INIT_ERROR_GENERIC; } @@ -88,7 +89,7 @@ pm_string_file_handle_open(pm_string_file_handle_t *handle, const char *filepath } } - xfree(handle->path); + xfree_sized(handle->path, path_size); return result; } @@ -215,7 +216,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { if (result != PM_STRING_INIT_SUCCESS) return result; // Get the file size. - DWORD file_size = GetFileSize(handle.file, NULL); + const DWORD file_size = GetFileSize(handle.file, NULL); if (file_size == INVALID_FILE_SIZE) { pm_string_file_handle_close(&handle); return PM_STRING_INIT_ERROR_GENERIC; @@ -245,7 +246,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { // Check the number of bytes read if (bytes_read != file_size) { - xfree(source); + xfree_sized(source, file_size); pm_string_file_handle_close(&handle); return PM_STRING_INIT_ERROR_GENERIC; } @@ -281,7 +282,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { return PM_STRING_INIT_SUCCESS; } - size_t length = (size_t) size; + const size_t length = (size_t) size; uint8_t *source = xmalloc(length); if (source == NULL) { close(fd); @@ -292,7 +293,7 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { close(fd); if (bytes_read == -1) { - xfree(source); + xfree_sized(source, length); return PM_STRING_INIT_ERROR_GENERIC; } diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index 69f70240f8..e3bcf116cc 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -113,7 +113,7 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) { const pm_node_t *visit = current->visit; *stack = current->prev; - xfree(current); + xfree_sized(current, sizeof(pm_node_stack_node_t)); return visit; } diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 88f8525f80..a11c7893d3 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -488,7 +488,7 @@ pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t lengt size_t message_length = (size_t) (result + 1); char *message = (char *) xmalloc(message_length); if (message == NULL) { - xfree(diagnostic); + xfree_sized(diagnostic, sizeof(pm_diagnostic_t)); return false; } @@ -519,7 +519,7 @@ pm_diagnostic_list_free(pm_list_t *list) { pm_diagnostic_t *next = (pm_diagnostic_t *) node->node.next; if (node->owned) xfree((void *) node->message); - xfree(node); + xfree_sized(node, sizeof(pm_diagnostic_t)); node = next; } diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index f1709a0249..e42a8e5b70 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -32,7 +32,11 @@ pm_node_list_grow(pm_node_list_t *list, size_t size) { next_capacity = double_capacity; } - pm_node_t **nodes = (pm_node_t **) xrealloc(list->nodes, sizeof(pm_node_t *) * next_capacity); + pm_node_t **nodes = (pm_node_t **) xrealloc_sized( + list->nodes, + sizeof(pm_node_t *) * next_capacity, + sizeof(pm_node_t *) * list->capacity + ); if (nodes == NULL) return false; list->nodes = nodes; @@ -79,7 +83,7 @@ pm_node_list_concat(pm_node_list_t *list, pm_node_list_t *other) { void pm_node_list_free(pm_node_list_t *list) { if (list->capacity > 0) { - xfree(list->nodes); + xfree_sized(list->nodes, sizeof(pm_node_t *) * list->capacity); *list = (pm_node_list_t) { 0 }; } } @@ -132,6 +136,7 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { <%- raise -%> <%- end -%> <%- end -%> + xfree_sized(node, sizeof(pm_<%= node.human %>_t)); break; } <%- end -%> @@ -140,7 +145,6 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { assert(false && "unreachable"); break; } - xfree(node); } /** From d8953190c083949aed022bfc0504726c2bd77396 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 25 Feb 2026 12:15:51 +0100 Subject: [PATCH 064/289] Bump dependencies in the main gemfile (#3945) Because dependabot won't do it. In particular this updates irb which contains a bugfix for binding.irb debugging on Ruby >= 4.0 --- Gemfile.lock | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7e23a63cd5..f42c601c6f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,24 +10,25 @@ GEM benchmark-ips (2.14.0) date (3.5.1) date (3.5.1-java) - erb (6.0.1) - erb (6.0.1-java) + erb (6.0.2) + erb (6.0.2-java) ffi (1.17.3) io-console (0.8.2) io-console (0.8.2-java) - irb (1.16.0) + irb (1.17.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jar-dependencies (0.5.5) mini_portile2 (2.8.9) - nokogiri (1.19.0) + nokogiri (1.19.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.19.0-java) + nokogiri (1.19.1-java) racc (~> 1.4) onigmo (0.1.0) - parser (3.3.10.0) + parser (3.3.10.2) ast (~> 2.4.1) racc power_assert (3.0.1) @@ -45,7 +46,7 @@ GEM rake (13.3.1) rake-compiler (1.3.1) rake - rdoc (7.0.3) + rdoc (7.2.0) erb psych (>= 4.0.0) tsort @@ -58,7 +59,7 @@ GEM sexp_processor (~> 4.16) sexp_processor (4.17.5) stringio (3.2.0) - test-unit (3.7.6) + test-unit (3.7.7) power_assert tsort (0.2.0) From 1fdd4c5a4986f179934c41ae8dc4f62342edff20 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Feb 2026 10:27:06 -0500 Subject: [PATCH 065/289] rbs-inline --- .gitattributes | 1 + .gitignore | 6 - Steepfile | 21 +- gemfiles/typecheck/Gemfile | 2 + gemfiles/typecheck/Gemfile.lock | 13 +- lib/prism.rb | 33 + lib/prism/desugar_compiler.rb | 78 +- lib/prism/lex_compat.rb | 143 +- lib/prism/node_ext.rb | 165 +- lib/prism/parse_result.rb | 311 +- lib/prism/parse_result/comments.rb | 42 +- lib/prism/parse_result/errors.rb | 7 +- lib/prism/parse_result/newlines.rb | 58 +- lib/prism/pattern.rb | 50 +- lib/prism/relocation.rb | 185 +- lib/prism/string_query.rb | 16 +- lib/prism/translation.rb | 1 + lib/prism/translation/parser_current.rb | 1 - prism.gemspec | 40 +- rakelib/typecheck.rake | 8 + sig/generated/prism.rbs | 76 + sig/generated/prism/compiler.rbs | 492 + sig/generated/prism/desugar_compiler.rbs | 305 + sig/generated/prism/dispatcher.rbs | 1292 + sig/generated/prism/dot_visitor.rbs | 635 + sig/generated/prism/dsl.rbs | 921 + sig/generated/prism/inspect_visitor.rbs | 509 + sig/generated/prism/lex_compat.rbs | 151 + sig/generated/prism/mutation_compiler.rbs | 464 + sig/generated/prism/node.rbs | 20896 ++++++++++++++++ sig/generated/prism/node_ext.rbs | 387 + sig/generated/prism/parse_result.rbs | 811 + sig/generated/prism/parse_result/comments.rbs | 108 + sig/generated/prism/parse_result/errors.rbs | 22 + sig/generated/prism/parse_result/newlines.rbs | 129 + sig/generated/prism/pattern.rbs | 156 + sig/generated/prism/reflection.rbs | 101 + sig/generated/prism/relocation.rbs | 502 + sig/generated/prism/serialize.rbs | 186 + sig/generated/prism/string_query.rbs | 36 + sig/generated/prism/translation.rbs | 8 + sig/generated/prism/visitor.rbs | 1111 + sig/prism/_private/node.rbs | 8 - sig/prism/_private/node_ext.rbs | 9 - sig/prism/_private/parse_result.rbs | 50 - sig/prism/_private/pattern.rbs | 26 - sig/prism/_private/relocation.rbs | 12 - sig/prism/_private/string_query.rbs | 7 - sig/prism/compiler.rbs | 9 - sig/prism/dispatcher.rbs | 19 - sig/prism/dot_visitor.rbs | 6 - sig/prism/inspect_visitor.rbs | 22 - sig/prism/lex_compat.rbs | 10 - sig/prism/node_ext.rbs | 149 - sig/prism/parse_result.rbs | 197 - sig/prism/parse_result/comments.rbs | 38 - sig/prism/pattern.rbs | 13 - sig/prism/reflection.rbs | 50 - sig/prism/relocation.rbs | 185 - sig/prism/serialize.rbs | 8 - sig/prism/string_query.rbs | 11 - templates/lib/prism/compiler.rb.erb | 9 + templates/lib/prism/dispatcher.rb.erb | 23 +- templates/lib/prism/dot_visitor.rb.erb | 36 +- templates/lib/prism/dsl.rb.erb | 24 + templates/lib/prism/inspect_visitor.rb.erb | 23 +- templates/lib/prism/mutation_compiler.rb.erb | 3 + templates/lib/prism/node.rb.erb | 161 +- templates/lib/prism/reflection.rb.erb | 12 +- templates/lib/prism/serialize.rb.erb | 244 +- templates/lib/prism/visitor.rb.erb | 17 + templates/sig/prism.rbs.erb | 92 - .../sig/prism/_private/dot_visitor.rbs.erb | 45 - templates/sig/prism/dsl.rbs.erb | 31 - templates/sig/prism/mutation_compiler.rbs.erb | 7 - templates/sig/prism/node.rbs.erb | 136 - templates/sig/prism/visitor.rbs.erb | 17 - templates/template.rb | 31 +- 78 files changed, 30777 insertions(+), 1442 deletions(-) create mode 100644 sig/generated/prism.rbs create mode 100644 sig/generated/prism/compiler.rbs create mode 100644 sig/generated/prism/desugar_compiler.rbs create mode 100644 sig/generated/prism/dispatcher.rbs create mode 100644 sig/generated/prism/dot_visitor.rbs create mode 100644 sig/generated/prism/dsl.rbs create mode 100644 sig/generated/prism/inspect_visitor.rbs create mode 100644 sig/generated/prism/lex_compat.rbs create mode 100644 sig/generated/prism/mutation_compiler.rbs create mode 100644 sig/generated/prism/node.rbs create mode 100644 sig/generated/prism/node_ext.rbs create mode 100644 sig/generated/prism/parse_result.rbs create mode 100644 sig/generated/prism/parse_result/comments.rbs create mode 100644 sig/generated/prism/parse_result/errors.rbs create mode 100644 sig/generated/prism/parse_result/newlines.rbs create mode 100644 sig/generated/prism/pattern.rbs create mode 100644 sig/generated/prism/reflection.rbs create mode 100644 sig/generated/prism/relocation.rbs create mode 100644 sig/generated/prism/serialize.rbs create mode 100644 sig/generated/prism/string_query.rbs create mode 100644 sig/generated/prism/translation.rbs create mode 100644 sig/generated/prism/visitor.rbs delete mode 100644 sig/prism/_private/node.rbs delete mode 100644 sig/prism/_private/node_ext.rbs delete mode 100644 sig/prism/_private/parse_result.rbs delete mode 100644 sig/prism/_private/pattern.rbs delete mode 100644 sig/prism/_private/relocation.rbs delete mode 100644 sig/prism/_private/string_query.rbs delete mode 100644 sig/prism/compiler.rbs delete mode 100644 sig/prism/dispatcher.rbs delete mode 100644 sig/prism/dot_visitor.rbs delete mode 100644 sig/prism/inspect_visitor.rbs delete mode 100644 sig/prism/lex_compat.rbs delete mode 100644 sig/prism/node_ext.rbs delete mode 100644 sig/prism/parse_result.rbs delete mode 100644 sig/prism/parse_result/comments.rbs delete mode 100644 sig/prism/pattern.rbs delete mode 100644 sig/prism/reflection.rbs delete mode 100644 sig/prism/relocation.rbs delete mode 100644 sig/prism/serialize.rbs delete mode 100644 sig/prism/string_query.rbs delete mode 100644 templates/sig/prism.rbs.erb delete mode 100644 templates/sig/prism/_private/dot_visitor.rbs.erb delete mode 100644 templates/sig/prism/dsl.rbs.erb delete mode 100644 templates/sig/prism/mutation_compiler.rbs.erb delete mode 100644 templates/sig/prism/node.rbs.erb delete mode 100644 templates/sig/prism/visitor.rbs.erb diff --git a/.gitattributes b/.gitattributes index 21fd53cb14..6b1cb4d76a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,7 @@ test/prism/fixtures/seattlerb/**/*.txt linguist-vendored test/prism/fixtures/unparser/**/*.txt linguist-vendored test/prism/fixtures/whitequark/**/*.txt linguist-vendored test/prism/snapshots/**/*.txt linguist-generated +sig/generated/**/*.rbs linguist-generated # All .rb files should have LF line ending, even on Windows, regardless of the git config core.autocrlf value. # All .txt should have their line endings as committed in the repository (there are some intentional CR in there), diff --git a/.gitignore b/.gitignore index 218a76cd00..f649d2de44 100644 --- a/.gitignore +++ b/.gitignore @@ -59,12 +59,6 @@ out.svg /src/serialize.c /src/token_type.c /src/**/*.o -/sig/prism.rbs -/sig/prism/dsl.rbs -/sig/prism/mutation_compiler.rbs -/sig/prism/node.rbs -/sig/prism/visitor.rbs -/sig/prism/_private/dot_visitor.rbs /rbi/prism/dsl.rbi /rbi/prism/node.rbi /rbi/prism/visitor.rbi diff --git a/Steepfile b/Steepfile index 433e53cd29..e6e1a8efb5 100644 --- a/Steepfile +++ b/Steepfile @@ -1,21 +1,18 @@ # frozen_string_literal: true target :lib do + check "lib" signature "sig" - library "cgi" # in lib/prism/dot_visitor.rb (Prism::DotVisitor) - - check "lib" + library "cgi" + library "pp" - # TODO: Type-checking these files is still WIP - ignore "lib/prism/desugar_compiler.rb" - ignore "lib/prism/lex_compat.rb" - ignore "lib/prism/serialize.rb" - ignore "lib/prism/ffi.rb" + # Ignored because it requires other libraries. ignore "lib/prism/translation" - ignore "lib/prism/polyfill/append_as_bytes.rb" - ignore "lib/prism/polyfill/byteindex.rb" - ignore "lib/prism/polyfill/scan_byte.rb" - ignore "lib/prism/polyfill/unpack1.rb" + # Ignored because they are only for older Rubies. + ignore "lib/prism/polyfill" + + # Ignored because we do not want to overlap with the C extension. + ignore "lib/prism/ffi.rb" end diff --git a/gemfiles/typecheck/Gemfile b/gemfiles/typecheck/Gemfile index 951dc83e3d..63003220c3 100644 --- a/gemfiles/typecheck/Gemfile +++ b/gemfiles/typecheck/Gemfile @@ -5,8 +5,10 @@ source "https://rubygems.org" gem "parser" gem "rake-compiler" gem "rake" +gem "rbs-inline" gem "ruby_parser" gem "sorbet", "<= 0.6.12666" # until tapioca is bumped gem "steep", ">= 1.7.0.dev.1" gem "tapioca" gem "test-unit" +gem "tsort" # until rbs is bumped diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index 2d057171a0..5e22e9088e 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -23,8 +23,7 @@ GEM csv (3.3.5) drb (2.2.3) erubi (1.13.1) - ffi (1.17.3-arm64-darwin) - ffi (1.17.3-x86_64-linux-gnu) + ffi (1.17.3) fileutils (1.8.0) i18n (1.14.7) concurrent-ruby (~> 1.0) @@ -57,12 +56,15 @@ GEM rbs (>= 3.4.4) rbs (3.10.2) logger + rbs-inline (0.13.0) + prism (>= 0.29) + rbs (>= 3.8.0) rexml (3.4.4) ruby_parser (3.22.0) racc (~> 1.5) sexp_processor (~> 4.16) securerandom (0.4.1) - sexp_processor (4.17.4) + sexp_processor (4.17.5) sorbet (0.6.12666) sorbet-static (= 0.6.12666) sorbet-runtime (0.6.12666) @@ -111,11 +113,12 @@ GEM test-unit (3.7.7) power_assert thor (1.4.0) + tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (3.2.0) unicode-emoji (~> 4.1) - unicode-emoji (4.1.0) + unicode-emoji (4.2.0) uri (1.1.1) yard (0.9.37) yard-sorbet (0.9.0) @@ -130,11 +133,13 @@ DEPENDENCIES parser rake rake-compiler + rbs-inline ruby_parser sorbet (<= 0.6.12666) steep (>= 1.7.0.dev.1) tapioca test-unit + tsort BUNDLED WITH 2.5.16 diff --git a/lib/prism.rb b/lib/prism.rb index 5b3ce8752c..c7530e5874 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown # The Prism Ruby parser. @@ -37,6 +38,8 @@ module Prism # Raised when requested to parse as the currently running Ruby version but Prism has no support for it. class CurrentVersionError < ArgumentError # Initialize a new exception for the given ruby version string. + #-- + #: (String version) -> void def initialize(version) message = +"invalid version: Requested to parse as `version: 'current'`; " segments = @@ -61,6 +64,8 @@ def initialize(version) # resembles the return value of Ripper.lex. # # For supported options, see Prism.parse. + #-- + #: (String source, **untyped options) -> LexCompat::Result def self.lex_compat(source, **options) LexCompat.new(source, **options).result # steep:ignore end @@ -69,9 +74,37 @@ def self.lex_compat(source, **options) # load(source, serialized, freeze) -> ParseResult # # Load the serialized AST using the source as a reference into a tree. + #-- + #: (String source, String serialized, ?bool freeze) -> ParseResult def self.load(source, serialized, freeze = false) Serialize.load_parse(source, serialized, freeze) end + + # @rbs! + # VERSION: String + # BACKEND: :CEXT | :FFI + # + # interface _Stream + # def gets: (?Integer integer) -> (String | nil) + # end + # + # def self.parse: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + # def self.profile: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + # def self.lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + # def self.parse_lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + # def self.dump: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + # def self.parse_comments: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + # def self.parse_success?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + # def self.parse_failure?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + # def self.parse_stream: (_Stream stream, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + # def self.parse_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + # def self.profile_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + # def self.lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + # def self.parse_lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + # def self.dump_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + # def self.parse_file_comments: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + # def self.parse_file_success?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + # def self.parse_file_failure?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool end require_relative "prism/polyfill/byteindex" diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb index 7d4201c1c4..e08faa3219 100644 --- a/lib/prism/desugar_compiler.rb +++ b/lib/prism/desugar_compiler.rb @@ -1,12 +1,17 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism class DesugarAndWriteNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -16,6 +21,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x &&= y` to `x && x = y` + #-- + #: () -> node def compile and_node( location: node.location, @@ -36,8 +43,12 @@ def compile class DesugarOrWriteDefinedNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -47,6 +58,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x ||= y` to `defined?(x) ? x : x = y` + #-- + #: () -> node def compile if_node( location: node.location, @@ -87,8 +100,12 @@ def compile class DesugarOperatorWriteNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -98,6 +115,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x += y` to `x = x + y` + #-- + #: () -> node def compile binary_operator_loc = node.binary_operator_loc.chop @@ -131,8 +150,12 @@ def compile class DesugarOrWriteNode # :nodoc: include DSL - attr_reader :node, :default_source, :read_class, :write_class, :arguments + attr_reader :node #: InstanceVariableOrWriteNode | LocalVariableOrWriteNode + attr_reader :default_source #: Source + attr_reader :read_class, :write_class #: Symbol + attr_reader :arguments #: Hash[Symbol, untyped] + #: ((InstanceVariableOrWriteNode | LocalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void def initialize(node, default_source, read_class, write_class, **arguments) @node = node @default_source = default_source @@ -142,6 +165,8 @@ def initialize(node, default_source, read_class, write_class, **arguments) end # Desugar `x ||= y` to `x || x = y` + #-- + #: () -> node def compile or_node( location: node.location, @@ -162,90 +187,105 @@ def compile private_constant :DesugarAndWriteNode, :DesugarOrWriteNode, :DesugarOrWriteDefinedNode, :DesugarOperatorWriteNode class ClassVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ClassVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteDefinedNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ClassVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile end end class ConstantAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class ConstantOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteDefinedNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class ConstantOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile end end class GlobalVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class GlobalVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteDefinedNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class GlobalVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile end end class InstanceVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class InstanceVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class InstanceVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile end end class LocalVariableAndWriteNode + #: () -> node def desugar # :nodoc: DesugarAndWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end end class LocalVariableOrWriteNode + #: () -> node def desugar # :nodoc: DesugarOrWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end end class LocalVariableOperatorWriteNode + #: () -> node def desugar # :nodoc: DesugarOperatorWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile end @@ -259,6 +299,8 @@ class DesugarCompiler < MutationCompiler # becomes # # `@@foo && @@foo = bar` + #-- + #: (ClassVariableAndWriteNode node) -> node def visit_class_variable_and_write_node(node) node.desugar end @@ -268,6 +310,8 @@ def visit_class_variable_and_write_node(node) # becomes # # `defined?(@@foo) ? @@foo : @@foo = bar` + #-- + #: (ClassVariableOrWriteNode node) -> node def visit_class_variable_or_write_node(node) node.desugar end @@ -277,6 +321,8 @@ def visit_class_variable_or_write_node(node) # becomes # # `@@foo = @@foo + bar` + #-- + #: (ClassVariableOperatorWriteNode node) -> node def visit_class_variable_operator_write_node(node) node.desugar end @@ -286,6 +332,8 @@ def visit_class_variable_operator_write_node(node) # becomes # # `Foo && Foo = bar` + #-- + #: (ConstantAndWriteNode node) -> node def visit_constant_and_write_node(node) node.desugar end @@ -295,6 +343,8 @@ def visit_constant_and_write_node(node) # becomes # # `defined?(Foo) ? Foo : Foo = bar` + #-- + #: (ConstantOrWriteNode node) -> node def visit_constant_or_write_node(node) node.desugar end @@ -304,6 +354,8 @@ def visit_constant_or_write_node(node) # becomes # # `Foo = Foo + bar` + #-- + #: (ConstantOperatorWriteNode node) -> node def visit_constant_operator_write_node(node) node.desugar end @@ -313,6 +365,8 @@ def visit_constant_operator_write_node(node) # becomes # # `$foo && $foo = bar` + #-- + #: (GlobalVariableAndWriteNode node) -> node def visit_global_variable_and_write_node(node) node.desugar end @@ -322,6 +376,8 @@ def visit_global_variable_and_write_node(node) # becomes # # `defined?($foo) ? $foo : $foo = bar` + #-- + #: (GlobalVariableOrWriteNode node) -> node def visit_global_variable_or_write_node(node) node.desugar end @@ -331,6 +387,8 @@ def visit_global_variable_or_write_node(node) # becomes # # `$foo = $foo + bar` + #-- + #: (GlobalVariableOperatorWriteNode node) -> node def visit_global_variable_operator_write_node(node) node.desugar end @@ -340,6 +398,8 @@ def visit_global_variable_operator_write_node(node) # becomes # # `@foo && @foo = bar` + #-- + #: (InstanceVariableAndWriteNode node) -> node def visit_instance_variable_and_write_node(node) node.desugar end @@ -349,6 +409,8 @@ def visit_instance_variable_and_write_node(node) # becomes # # `@foo || @foo = bar` + #-- + #: (InstanceVariableOrWriteNode node) -> node def visit_instance_variable_or_write_node(node) node.desugar end @@ -358,6 +420,8 @@ def visit_instance_variable_or_write_node(node) # becomes # # `@foo = @foo + bar` + #-- + #: (InstanceVariableOperatorWriteNode node) -> node def visit_instance_variable_operator_write_node(node) node.desugar end @@ -367,6 +431,8 @@ def visit_instance_variable_operator_write_node(node) # becomes # # `foo && foo = bar` + #-- + #: (LocalVariableAndWriteNode node) -> node def visit_local_variable_and_write_node(node) node.desugar end @@ -376,6 +442,8 @@ def visit_local_variable_and_write_node(node) # becomes # # `foo || foo = bar` + #-- + #: (LocalVariableOrWriteNode node) -> node def visit_local_variable_or_write_node(node) node.desugar end @@ -385,6 +453,8 @@ def visit_local_variable_or_write_node(node) # becomes # # `foo = foo + bar` + #-- + #: (LocalVariableOperatorWriteNode node) -> node def visit_local_variable_operator_write_node(node) node.desugar end diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 3d5cbfcddc..bdef99acfc 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -1,25 +1,47 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism + # @rbs! + # module Translation + # class Ripper + # EXPR_BEG: Integer + # + # class Lexer < Ripper + # class State + # def self.[]: (Integer value) -> State + # end + # end + # end + # end + # This class is responsible for lexing the source using prism and then # converting those tokens to be compatible with Ripper. In the vast majority # of cases, this is a one-to-one mapping of the token type. Everything else # generally lines up. However, there are a few cases that require special # handling. class LexCompat # :nodoc: + # @rbs! + # # A token produced by the Ripper lexer that Prism is replicating. + # type lex_compat_token = [[Integer, Integer], Symbol, String, untyped] + # A result class specialized for holding tokens produced by the lexer. class Result < Prism::Result # The list of tokens that were produced by the lexer. - attr_reader :value + attr_reader :value #: Array[lex_compat_token] # Create a new lex compat result object with the given values. + #-- + #: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) @value = value super(comments, magic_comments, data_loc, errors, warnings, source) end # Implement the hash pattern matching interface for Result. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end @@ -205,16 +227,19 @@ module Heredoc # :nodoc: # order back into the token stream and set the state of the last token to # the state that the heredoc was opened in. class PlainHeredoc # :nodoc: - attr_reader :tokens + attr_reader :tokens #: Array[lex_compat_token] + #: () -> void def initialize @tokens = [] end + #: (lex_compat_token token) -> void def <<(token) tokens << token end + #: () -> Array[lex_compat_token] def to_a tokens end @@ -224,21 +249,25 @@ def to_a # that need to be split on "\\\n" to mimic Ripper's behavior. We also need # to keep track of the state that the heredoc was opened in. class DashHeredoc # :nodoc: - attr_reader :split, :tokens + attr_reader :split #: bool + attr_reader :tokens #: Array[lex_compat_token] + #: (bool split) -> void def initialize(split) @split = split @tokens = [] end + #: (lex_compat_token token) -> void def <<(token) tokens << token end + #: () -> Array[lex_compat_token] def to_a embexpr_balance = 0 - tokens.each_with_object([]) do |token, results| #$ Array[Token] + tokens.each_with_object([]) do |token, results| #$ Array[lex_compat_token] case token[1] when :on_embexpr_beg embexpr_balance += 1 @@ -285,8 +314,13 @@ def to_a class DedentingHeredoc # :nodoc: TAB_WIDTH = 8 - attr_reader :tokens, :dedent_next, :dedent, :embexpr_balance + attr_reader :tokens #: Array[lex_compat_token] + attr_reader :dedent_next #: bool + attr_reader :dedent #: Integer? + attr_reader :embexpr_balance #: Integer + # @rbs @ended_on_newline: bool + #: () -> void def initialize @tokens = [] @dedent_next = true @@ -298,6 +332,8 @@ def initialize # As tokens are coming in, we track the minimum amount of common leading # whitespace on plain string content tokens. This allows us to later # remove that amount of whitespace from the beginning of each line. + # + #: (lex_compat_token token) -> void def <<(token) case token[1] when :on_embexpr_beg, :on_heredoc_beg @@ -310,7 +346,7 @@ def <<(token) line = token[2] if dedent_next && !(line.strip.empty? && line.end_with?("\n")) - leading = line[/\A(\s*)\n?/, 1] + leading = line[/\A(\s*)\n?/, 1] #: String next_dedent = 0 leading.each_char do |char| @@ -335,11 +371,12 @@ def <<(token) tokens << token end + #: () -> Array[lex_compat_token] def to_a # If every line in the heredoc is blank, we still need to split up the # string content token into multiple tokens. if dedent.nil? - results = [] #: Array[Token] + results = [] #: Array[lex_compat_token] embexpr_balance = 0 tokens.each do |token| @@ -374,7 +411,7 @@ def to_a # If the minimum common whitespace is 0, then we need to concatenate # string nodes together that are immediately adjacent. if dedent == 0 - results = [] #: Array[Token] + results = [] #: Array[lex_compat_token] embexpr_balance = 0 index = 0 @@ -407,7 +444,7 @@ def to_a # insert on_ignored_sp tokens for the amount of dedent that we need to # perform. We also need to remove the dedent from the beginning of # each line of plain string content tokens. - results = [] #: Array[Token] + results = [] #: Array[lex_compat_token] dedent_next = true embexpr_balance = 0 @@ -446,7 +483,8 @@ def to_a # line or this line doesn't start with whitespace, then we # should concatenate the rest of the string to match ripper. if dedent == 0 && (!dedent_next || !line.start_with?(/\s/)) - line = splits[index..].join + unjoined = splits[index..] #: Array[String] + line = unjoined.join index = splits.length end @@ -511,6 +549,8 @@ def to_a # Here we will split between the two types of heredocs and return the # object that will store their tokens. + #-- + #: (lex_compat_token opening) -> (PlainHeredoc | DashHeredoc | DedentingHeredoc) def self.build(opening) case opening[2][2] when "~" @@ -530,31 +570,38 @@ def self.build(opening) BOM_FLUSHED = RUBY_VERSION >= "3.3.0" private_constant :BOM_FLUSHED - attr_reader :options + attr_reader :options #: Hash[Symbol, untyped] + # @rbs @source: String - def initialize(code, **options) - @code = code + #: (String source, **untyped options) -> void + def initialize(source, **options) + @source = source @options = options end + #: () -> Result def result - tokens = [] #: Array[LexCompat::Token] + tokens = [] #: Array[lex_compat_token] state = :default heredoc_stack = [[]] #: Array[Array[Heredoc::PlainHeredoc | Heredoc::DashHeredoc | Heredoc::DedentingHeredoc]] - result = Prism.lex(@code, **options) + result = Prism.lex(@source, **options) source = result.source result_value = result.value - previous_state = nil #: State? + previous_state = nil #: Translation::Ripper::Lexer::State? last_heredoc_end = nil #: Integer? - eof_token = nil + eof_token = nil #: Token? bom = source.slice(0, 3) == "\xEF\xBB\xBF" - result_value.each_with_index do |(token, lex_state), index| - lineno = token.location.start_line - column = token.location.start_column + result_value.each_with_index do |(prism_token, prism_state), index| + lineno = prism_token.location.start_line + column = prism_token.location.start_column + + event = RIPPER.fetch(prism_token.type) + value = prism_token.value + lex_state = Translation::Ripper::Lexer::State[prism_state] # If there's a UTF-8 byte-order mark as the start of the file, then for # certain tokens ripper sets the first token back by 3 bytes. It also @@ -566,43 +613,38 @@ def result if index == 0 && column == 0 && !BOM_FLUSHED flushed = - case token.type + case prism_token.type when :BACK_REFERENCE, :INSTANCE_VARIABLE, :CLASS_VARIABLE, :GLOBAL_VARIABLE, :NUMBERED_REFERENCE, :PERCENT_LOWER_I, :PERCENT_LOWER_X, :PERCENT_LOWER_W, :PERCENT_UPPER_I, :PERCENT_UPPER_W, :STRING_BEGIN true when :REGEXP_BEGIN, :SYMBOL_BEGIN - token.value.start_with?("%") + value.start_with?("%") else false end unless flushed column -= 3 - value = token.value value.prepend(String.new("\xEF\xBB\xBF", encoding: value.encoding)) end end end - event = RIPPER.fetch(token.type) - value = token.value - lex_state = Translation::Ripper::Lexer::State[lex_state] - - token = + lex_compat_token = case event when :on___end__ # Ripper doesn't include the rest of the token in the event, so we need to # trim it down to just the content on the first line. - value = value[0..value.index("\n")] + value = value[0..value.index("\n")] #: String [[lineno, column], event, value, lex_state] when :on_comment [[lineno, column], event, value, lex_state] when :on_heredoc_end # Heredoc end tokens can be emitted in an odd order, so we don't # want to bother comparing the state on them. - last_heredoc_end = token.location.end_offset + last_heredoc_end = prism_token.location.end_offset [[lineno, column], event, value, lex_state] when :on_embexpr_end [[lineno, column], event, value, lex_state] @@ -615,7 +657,7 @@ def result end tokens << [[lineno, column], event, line, lex_state] end - tokens.pop + tokens.pop #: lex_compat_token when :on_regexp_end # On regex end, Ripper scans and then sets end state, so the ripper # lexed output is begin, when it should be end. prism sets lex state @@ -647,7 +689,7 @@ def result [[lineno, column], event, value, lex_state] when :on_eof - eof_token = token + eof_token = prism_token previous_token = result_value[index - 1][0] # If we're at the end of the file and the previous token was a @@ -662,7 +704,7 @@ def result # Use the greater offset of the two to determine the start of # the trailing whitespace. start_offset = [previous_token.location.end_offset, last_heredoc_end].compact.max - end_offset = token.location.start_offset + end_offset = prism_token.location.start_offset if start_offset < end_offset if bom @@ -677,7 +719,7 @@ def result [[lineno, column], event, value, lex_state] else [[lineno, column], event, value, lex_state] - end + end #: lex_compat_token previous_state = lex_state @@ -694,19 +736,19 @@ def result when :default # The default state is when there are no heredocs at all. In this # state we can append the token to the list of tokens and move on. - tokens << token + tokens << lex_compat_token # If we get the declaration of a heredoc, then we open a new heredoc # and move into the heredoc_opened state. if event == :on_heredoc_beg state = :heredoc_opened - heredoc_stack.last << Heredoc.build(token) + heredoc_stack.last << Heredoc.build(lex_compat_token) end when :heredoc_opened # The heredoc_opened state is when we've seen the declaration of a # heredoc and are now lexing the body of the heredoc. In this state we # push tokens onto the most recently created heredoc. - heredoc_stack.last.last << token + heredoc_stack.last.last << lex_compat_token case event when :on_heredoc_beg @@ -714,7 +756,7 @@ def result # heredoc, this means we have nested heredocs. In this case we'll # push a new heredoc onto the stack and stay in the heredoc_opened # state since we're now lexing the body of the new heredoc. - heredoc_stack << [Heredoc.build(token)] + heredoc_stack << [Heredoc.build(lex_compat_token)] when :on_heredoc_end # If we receive the end of a heredoc, then we're done lexing the # body of the heredoc. In this case we now have a completed heredoc @@ -723,10 +765,10 @@ def result state = :heredoc_closed end when :heredoc_closed - if %i[on_nl on_ignored_nl on_comment].include?(event) || (event == :on_tstring_content && value.end_with?("\n")) + if %i[on_nl on_ignored_nl on_comment].include?(event) || ((event == :on_tstring_content) && value.end_with?("\n")) if heredoc_stack.size > 1 - flushing = heredoc_stack.pop - heredoc_stack.last.last << token + flushing = heredoc_stack.pop #: Array[Heredoc::PlainHeredoc | Heredoc::DashHeredoc | Heredoc::DedentingHeredoc] + heredoc_stack.last.last << lex_compat_token flushing.each do |heredoc| heredoc.to_a.each do |flushed_token| @@ -738,12 +780,12 @@ def result next end elsif event == :on_heredoc_beg - tokens << token + tokens << lex_compat_token state = :heredoc_opened - heredoc_stack.last << Heredoc.build(token) + heredoc_stack.last << Heredoc.build(lex_compat_token) next elsif heredoc_stack.size > 1 - heredoc_stack[-2].last << token + heredoc_stack[-2].last << lex_compat_token next end @@ -754,13 +796,15 @@ def result heredoc_stack.last.clear state = :default - tokens << token + tokens << lex_compat_token end end # Drop the EOF token from the list. The EOF token may not be # present if the source was syntax invalid - tokens = tokens[0...-1] if tokens.dig(-1, 1) == :on_eof + if tokens.dig(-1, 1) == :on_eof + tokens = tokens[0...-1] #: Array[lex_compat_token] + end # We sort by location because Ripper.lex sorts. tokens.sort_by! do |token| @@ -775,8 +819,9 @@ def result private + #: (Array[lex_compat_token] tokens, Source source, Location? data_loc, bool bom, Token? eof_token) -> Array[lex_compat_token] def post_process_tokens(tokens, source, data_loc, bom, eof_token) - new_tokens = [] + new_tokens = [] #: Array[lex_compat_token] prev_token_state = Translation::Ripper::Lexer::State[Translation::Ripper::EXPR_BEG] prev_token_end = bom ? 3 : 0 @@ -806,8 +851,8 @@ def post_process_tokens(tokens, source, data_loc, bom, eof_token) next_whitespace_index = continuation_index + 1 next_whitespace_index += 1 if sp_value.byteslice(next_whitespace_index) == "\r" next_whitespace_index += 1 - first_whitespace = sp_value[0...continuation_index] - continuation = sp_value[continuation_index...next_whitespace_index] + first_whitespace = sp_value[0...continuation_index] #: String + continuation = sp_value[continuation_index...next_whitespace_index] #: String second_whitespace = sp_value[next_whitespace_index..] || "" new_tokens << [[sp_line, sp_column], :on_sp, first_whitespace, prev_token_state] unless first_whitespace.empty? diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index a05123d1bb..57593a1612 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown #-- @@ -7,6 +8,7 @@ #++ module Prism class Node + #: (*String replacements) -> void def deprecated(*replacements) # :nodoc: location = caller_locations(1, 1) location = location[0].label if location @@ -23,7 +25,9 @@ def deprecated(*replacements) # :nodoc: module RegularExpressionOptions # :nodoc: # Returns a numeric value that represents the flags that were used to create # the regular expression. - def options + #-- + #: (Integer flags) -> Integer + def self.options(flags) o = 0 o |= Regexp::IGNORECASE if flags.anybits?(RegularExpressionFlags::IGNORE_CASE) o |= Regexp::EXTENDED if flags.anybits?(RegularExpressionFlags::EXTENDED) @@ -35,43 +39,87 @@ def options end class InterpolatedMatchLastLineNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end class InterpolatedRegularExpressionNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end class MatchLastLineNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end class RegularExpressionNode < Node - include RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + #-- + #: () -> Integer + def options + RegularExpressionOptions.options(flags) + end end private_constant :RegularExpressionOptions module HeredocQuery # :nodoc: # Returns true if this node was represented as a heredoc in the source code. - def heredoc? + #-- + #: (String? opening) -> bool? + def self.heredoc?(opening) + # @type self: InterpolatedStringNode | InterpolatedXStringNode | StringNode | XStringNode opening&.start_with?("<<") end end class InterpolatedStringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end end class InterpolatedXStringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end end class StringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end # Occasionally it's helpful to treat a string as if it were interpolated so # that there's a consistent interface for working with strings. + #-- + #: () -> InterpolatedStringNode def to_interpolated InterpolatedStringNode.new( source, @@ -86,10 +134,17 @@ def to_interpolated end class XStringNode < Node - include HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + #-- + #: () -> bool? + def heredoc? + HeredocQuery.heredoc?(opening) + end # Occasionally it's helpful to treat a string as if it were interpolated so # that there's a consistent interface for working with strings. + #-- + #: () -> InterpolatedXStringNode def to_interpolated InterpolatedXStringNode.new( source, @@ -107,6 +162,8 @@ def to_interpolated class ImaginaryNode < Node # Returns the value of the node as a Ruby Complex. + #-- + #: () -> Complex def value Complex(0, numeric.value) end @@ -114,12 +171,16 @@ def value class RationalNode < Node # Returns the value of the node as a Ruby Rational. + #-- + #: () -> Rational def value Rational(numerator, denominator) end # Returns the value of the node as an IntegerNode or a FloatNode. This # method is deprecated in favor of #value or #numerator/#denominator. + #-- + #: () -> (IntegerNode | FloatNode) def numeric deprecated("value", "numerator", "denominator") @@ -134,11 +195,15 @@ def numeric class ConstantReadNode < Node # Returns the list of parts for the full name of this constant. # For example: [:Foo] + #-- + #: () -> Array[Symbol] def full_name_parts [name] end # Returns the full name of this constant. For example: "Foo" + #-- + #: () -> String def full_name name.to_s end @@ -147,11 +212,15 @@ def full_name class ConstantWriteNode < Node # Returns the list of parts for the full name of this constant. # For example: [:Foo] + #-- + #: () -> Array[Symbol] def full_name_parts [name] end # Returns the full name of this constant. For example: "Foo" + #-- + #: () -> String def full_name name.to_s end @@ -173,6 +242,8 @@ class MissingNodesInConstantPathError < StandardError; end # Returns the list of parts for the full name of this constant path. # For example: [:Foo, :Bar] + #-- + #: () -> Array[Symbol] def full_name_parts parts = [] #: Array[Symbol] current = self #: node? @@ -195,6 +266,8 @@ def full_name_parts end # Returns the full name of this constant path. For example: "Foo::Bar" + #-- + #: () -> String def full_name full_name_parts.join("::") end @@ -202,10 +275,12 @@ def full_name # Previously, we had a child node on this class that contained either a # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. + #-- + #: () -> (ConstantReadNode | MissingNode) def child deprecated("name", "name_loc") - if name + if (name = self.name) ConstantReadNode.new(source, -1, name_loc, 0, name) else MissingNode.new(source, -1, location, 0) @@ -216,9 +291,11 @@ def child class ConstantPathTargetNode < Node # Returns the list of parts for the full name of this constant path. # For example: [:Foo, :Bar] + #-- + #: () -> Array[Symbol] def full_name_parts parts = - case parent + case (parent = self.parent) when ConstantPathNode, ConstantReadNode parent.full_name_parts when nil @@ -228,7 +305,7 @@ def full_name_parts raise ConstantPathNode::DynamicPartsInConstantPathError, "Constant target path contains dynamic parts. Cannot compute full name" end - if name.nil? + if (name = self.name).nil? raise ConstantPathNode::MissingNodesInConstantPathError, "Constant target path contains missing nodes. Cannot compute full name" end @@ -236,6 +313,8 @@ def full_name_parts end # Returns the full name of this constant path. For example: "Foo::Bar" + #-- + #: () -> String def full_name full_name_parts.join("::") end @@ -243,10 +322,12 @@ def full_name # Previously, we had a child node on this class that contained either a # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. + #-- + #: () -> (ConstantReadNode | MissingNode) def child deprecated("name", "name_loc") - if name + if (name = self.name) ConstantReadNode.new(source, -1, name_loc, 0, name) else MissingNode.new(source, -1, location, 0) @@ -257,11 +338,15 @@ def child class ConstantTargetNode < Node # Returns the list of parts for the full name of this constant. # For example: [:Foo] + #-- + #: () -> Array[Symbol] def full_name_parts [name] end # Returns the full name of this constant. For example: "Foo" + #-- + #: () -> String def full_name name.to_s end @@ -269,6 +354,8 @@ def full_name class ParametersNode < Node # Mirrors the Method#parameters method. + #-- + #: () -> Array[[Symbol, Symbol] | [Symbol]] def signature names = [] #: Array[[Symbol, Symbol] | [Symbol]] @@ -278,7 +365,7 @@ def signature optionals.each { |param| names << [:opt, param.name] } - if rest && rest.is_a?(RestParameterNode) + if (rest = self.rest).is_a?(RestParameterNode) names << [:rest, rest.name || :*] end @@ -309,7 +396,7 @@ def signature keyopt.each { |param| names << [:key, param.name] } - case keyword_rest + case (keyword_rest = self.keyword_rest) when ForwardingParameterNode names.concat([[:rest, :*], [:keyrest, :**], [:block, :&]]) when KeywordRestParameterNode @@ -318,7 +405,7 @@ def signature names << [:nokey] end - case block + case (block = self.block) when BlockParameterNode names << [:block, block.name || :&] when NoBlockParameterNode @@ -339,6 +426,8 @@ class CallNode < Node # can be any amount of space between the message and the = sign. However, # sometimes you want the location of the full message including the inner # space and the = sign. This method provides that. + #-- + #: () -> Location? def full_message_loc attribute_write? ? message_loc&.adjoin("=") : message_loc end @@ -347,6 +436,8 @@ def full_message_loc class CallOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -354,6 +445,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -363,6 +456,8 @@ def operator_loc class ClassVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -370,6 +465,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -379,6 +476,8 @@ def operator_loc class ConstantOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -386,6 +485,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -395,6 +496,8 @@ def operator_loc class ConstantPathOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -402,6 +505,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -411,6 +516,8 @@ def operator_loc class GlobalVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -418,6 +525,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -427,6 +536,8 @@ def operator_loc class IndexOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -434,6 +545,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -443,6 +556,8 @@ def operator_loc class InstanceVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -450,6 +565,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -459,6 +576,8 @@ def operator_loc class LocalVariableOperatorWriteNode < Node # Returns the binary operator used to modify the receiver. This method is # deprecated in favor of #binary_operator. + #-- + #: () -> Symbol def operator deprecated("binary_operator") binary_operator @@ -466,6 +585,8 @@ def operator # Returns the location of the binary operator used to modify the receiver. # This method is deprecated in favor of #binary_operator_loc. + #-- + #: () -> Location def operator_loc deprecated("binary_operator_loc") binary_operator_loc @@ -475,6 +596,8 @@ def operator_loc class CaseMatchNode < Node # Returns the else clause of the case match node. This method is deprecated # in favor of #else_clause. + #-- + #: () -> ElseNode? def consequent deprecated("else_clause") else_clause @@ -484,6 +607,8 @@ def consequent class CaseNode < Node # Returns the else clause of the case node. This method is deprecated in # favor of #else_clause. + #-- + #: () -> ElseNode? def consequent deprecated("else_clause") else_clause @@ -493,6 +618,8 @@ def consequent class IfNode < Node # Returns the subsequent if/elsif/else clause of the if node. This method is # deprecated in favor of #subsequent. + #-- + #: () -> (IfNode | ElseNode)? def consequent deprecated("subsequent") subsequent @@ -502,6 +629,8 @@ def consequent class RescueNode < Node # Returns the subsequent rescue clause of the rescue node. This method is # deprecated in favor of #subsequent. + #-- + #: () -> RescueNode? def consequent deprecated("subsequent") subsequent @@ -511,6 +640,8 @@ def consequent class UnlessNode < Node # Returns the else clause of the unless node. This method is deprecated in # favor of #else_clause. + #-- + #: () -> ElseNode? def consequent deprecated("else_clause") else_clause diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 07529c4295..e2e1145bdc 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -1,7 +1,15 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism + # @rbs! + # # An internal interface for a cache that can be used to compute code + # # units from byte offsets. + # interface _CodeUnitsCache + # def []: (Integer byte_offset) -> Integer + # end + # This represents a source of Ruby code that has been parsed. It is used in # conjunction with locations to allow them to resolve line numbers and source # ranges. @@ -10,6 +18,8 @@ class Source # be used instead of `new` and it will return either a `Source` or a # specialized and more performant `ASCIISource` if no multibyte characters # are present in the source code. + #-- + #: (String source, ?Integer start_line, ?Array[Integer] offsets) -> Source def self.for(source, start_line = 1, offsets = []) if source.ascii_only? ASCIISource.new(source, start_line, offsets) @@ -34,15 +44,17 @@ def self.for(source, start_line = 1, offsets = []) end # The source code that this source object represents. - attr_reader :source + attr_reader :source #: String # The line number where this source starts. - attr_reader :start_line + attr_reader :start_line #: Integer # The list of newline byte offsets in the source code. - attr_reader :offsets + attr_reader :offsets #: Array[Integer] # Create a new source object with the given source code. + #-- + #: (String source, ?Integer start_line, ?Array[Integer] offsets) -> void def initialize(source, start_line = 1, offsets = []) @source = source @start_line = start_line # set after parsing is done @@ -50,33 +62,45 @@ def initialize(source, start_line = 1, offsets = []) end # Replace the value of start_line with the given value. + #-- + #: (Integer start_line) -> void def replace_start_line(start_line) @start_line = start_line end # Replace the value of offsets with the given value. + #-- + #: (Array[Integer] offsets) -> void def replace_offsets(offsets) @offsets.replace(offsets) end # Returns the encoding of the source code, which is set by parameters to the # parser or by the encoding magic comment. + #-- + #: () -> Encoding def encoding source.encoding end # Returns the lines of the source code as an array of strings. + #-- + #: () -> Array[String] def lines source.lines end # Perform a byteslice on the source code using the given byte offset and # byte length. + #-- + #: (Integer byte_offset, Integer length) -> String def slice(byte_offset, length) source.byteslice(byte_offset, length) or raise end # Converts the line number and column in bytes to a byte offset. + #-- + #: (Integer line, Integer column) -> Integer def byte_offset(line, column) normal = line - @start_line raise IndexError if normal < 0 @@ -87,33 +111,45 @@ def byte_offset(line, column) # Binary search through the offsets to find the line number for the given # byte offset. + #-- + #: (Integer byte_offset) -> Integer def line(byte_offset) start_line + find_line(byte_offset) end # Return the byte offset of the start of the line corresponding to the given # byte offset. + #-- + #: (Integer byte_offset) -> Integer def line_start(byte_offset) offsets[find_line(byte_offset)] end # Returns the byte offset of the end of the line corresponding to the given # byte offset. + #-- + #: (Integer byte_offset) -> Integer def line_end(byte_offset) offsets[find_line(byte_offset) + 1] || source.bytesize end # Return the column in bytes for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def column(byte_offset) byte_offset - line_start(byte_offset) end # Return the character offset for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_offset(byte_offset) (source.byteslice(0, byte_offset) or raise).length end # Return the column in characters for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_column(byte_offset) character_offset(byte_offset) - character_offset(line_start(byte_offset)) end @@ -130,6 +166,8 @@ def character_column(byte_offset) # possible that the given byte offset will not occur on a character # boundary. Second, it's possible that the source code will contain a # character that has no equivalent in the given encoding. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_offset(byte_offset, encoding) byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding, invalid: :replace, undef: :replace) @@ -142,17 +180,23 @@ def code_units_offset(byte_offset, encoding) # Generate a cache that targets a specific encoding for calculating code # unit offsets. + #-- + #: (Encoding encoding) -> CodeUnitsCache def code_units_cache(encoding) CodeUnitsCache.new(source, encoding) end # Returns the column in code units for the given encoding for the # given byte offset. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_column(byte_offset, encoding) code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding) end # Freeze this object and the objects it contains. + #-- + #: () -> void def deep_freeze source.freeze offsets.freeze @@ -163,6 +207,8 @@ def deep_freeze # Binary search through the offsets to find the line number for the given # byte offset. + #-- + #: (Integer byte_offset) -> Integer def find_line(byte_offset) # :nodoc: index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length index - 1 @@ -185,30 +231,47 @@ def find_line(byte_offset) # :nodoc: # class CodeUnitsCache class UTF16Counter # :nodoc: + # @rbs @source: String + # @rbs @encoding: Encoding + + #: (String source, Encoding encoding) -> void def initialize(source, encoding) @source = source @encoding = encoding end + #: (Integer byte_offset, Integer byte_length) -> Integer def count(byte_offset, byte_length) - @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2 + (@source.byteslice(byte_offset, byte_length) or raise).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2 end end class LengthCounter # :nodoc: + # @rbs @source: String + # @rbs @encoding: Encoding + + #: (String source, Encoding encoding) -> void def initialize(source, encoding) @source = source @encoding = encoding end + #: (Integer byte_offset, Integer byte_length) -> Integer def count(byte_offset, byte_length) - @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).length + (@source.byteslice(byte_offset, byte_length) or raise).encode(@encoding, invalid: :replace, undef: :replace).length end end private_constant :UTF16Counter, :LengthCounter + # @rbs @source: String + # @rbs @counter: UTF16Counter | LengthCounter + # @rbs @cache: Hash[Integer, Integer] + # @rbs @offsets: Array[Integer] + # Initialize a new cache with the given source and encoding. + #-- + #: (String source, Encoding encoding) -> void def initialize(source, encoding) @source = source @counter = @@ -223,6 +286,8 @@ def initialize(source, encoding) end # Retrieve the code units offset from the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def [](byte_offset) @cache[byte_offset] ||= if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil? @@ -249,11 +314,15 @@ def [](byte_offset) # at that point we will treat everything as single-byte characters. class ASCIISource < Source # Return the character offset for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_offset(byte_offset) byte_offset end # Return the column in characters for the given byte offset. + #-- + #: (Integer byte_offset) -> Integer def character_column(byte_offset) byte_offset - line_start(byte_offset) end @@ -264,6 +333,8 @@ def character_column(byte_offset) # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the # concept of code units that differs from the number of characters in other # encodings, it is not captured here. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_offset(byte_offset, encoding) byte_offset end @@ -271,6 +342,8 @@ def code_units_offset(byte_offset, encoding) # Returns a cache that is the identity function in order to maintain the # same interface. We can do this because code units are always equivalent to # byte offsets for ASCII-only sources. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) ->(byte_offset) { byte_offset } end @@ -278,6 +351,8 @@ def code_units_cache(encoding) # Specialized version of `code_units_column` that does not depend on # `code_units_offset`, which is a more expensive operation. This is # essentially the same as `Prism::Source#column`. + #-- + #: (Integer byte_offset, Encoding encoding) -> Integer def code_units_column(byte_offset, encoding) byte_offset - line_start(byte_offset) end @@ -287,18 +362,23 @@ def code_units_column(byte_offset, encoding) class Location # A Source object that is used to determine more information from the given # offset and length. - attr_reader :source + attr_reader :source #: Source protected :source # The byte offset from the beginning of the source where this location # starts. - attr_reader :start_offset + attr_reader :start_offset #: Integer # The length of this location in bytes. - attr_reader :length + attr_reader :length #: Integer + + # @rbs @leading_comments: Array[Comment]? + # @rbs @trailing_comments: Array[Comment]? # Create a new location object with the given source, start byte offset, and # byte length. + #-- + #: (Source source, Integer start_offset, Integer length) -> void def initialize(source, start_offset, length) @source = source @start_offset = start_offset @@ -313,53 +393,73 @@ def initialize(source, start_offset, length) # These are the comments that are associated with this location that exist # before the start of this location. + #-- + #: () -> Array[Comment] def leading_comments @leading_comments ||= [] end # Attach a comment to the leading comments of this location. + #-- + #: (Comment comment) -> void def leading_comment(comment) leading_comments << comment end # These are the comments that are associated with this location that exist # after the end of this location. + #-- + #: () -> Array[Comment] def trailing_comments @trailing_comments ||= [] end # Attach a comment to the trailing comments of this location. + #-- + #: (Comment comment) -> void def trailing_comment(comment) trailing_comments << comment end # Returns all comments that are associated with this location (both leading # and trailing comments). + #-- + #: () -> Array[Comment] def comments - [*@leading_comments, *@trailing_comments] + [*@leading_comments, *@trailing_comments] #: Array[Comment] end # Create a new location object with the given options. + #-- + #: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location def copy(source: self.source, start_offset: self.start_offset, length: self.length) Location.new(source, start_offset, length) end # Returns a new location that is the result of chopping off the last byte. + #-- + #: () -> Location def chop copy(length: length == 0 ? length : length - 1) end # Returns a string representation of this location. + #-- + #: () -> String def inspect # :nodoc: "#" end # Returns all of the lines of the source code associated with this location. + #-- + #: () -> Array[String] def source_lines source.lines end # The source code that this location represents. + #-- + #: () -> String def slice source.slice(start_offset, length) end @@ -367,6 +467,8 @@ def slice # The source code that this location represents starting from the beginning # of the line that this location starts on to the end of the line that this # location ends on. + #-- + #: () -> String def slice_lines line_start = source.line_start(start_offset) line_end = source.line_end(end_offset) @@ -375,118 +477,160 @@ def slice_lines # The character offset from the beginning of the source where this location # starts. + #-- + #: () -> Integer def start_character_offset source.character_offset(start_offset) end # The offset from the start of the file in code units of the given encoding. + #-- + #: (Encoding encoding) -> Integer def start_code_units_offset(encoding = Encoding::UTF_16LE) source.code_units_offset(start_offset, encoding) end # The start offset from the start of the file in code units using the given # cache to fetch or calculate the value. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_offset(cache) cache[start_offset] end # The byte offset from the beginning of the source where this location ends. + #-- + #: () -> Integer def end_offset start_offset + length end # The character offset from the beginning of the source where this location # ends. + #-- + #: () -> Integer def end_character_offset source.character_offset(end_offset) end # The offset from the start of the file in code units of the given encoding. + #-- + #: (Encoding encoding) -> Integer def end_code_units_offset(encoding = Encoding::UTF_16LE) source.code_units_offset(end_offset, encoding) end # The end offset from the start of the file in code units using the given # cache to fetch or calculate the value. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_end_code_units_offset(cache) cache[end_offset] end # The line number where this location starts. + #-- + #: () -> Integer def start_line source.line(start_offset) end # The content of the line where this location starts before this location. + #-- + #: () -> String def start_line_slice offset = source.line_start(start_offset) source.slice(offset, start_offset - offset) end # The line number where this location ends. + #-- + #: () -> Integer def end_line source.line(end_offset) end # The column in bytes where this location starts from the start of # the line. + #-- + #: () -> Integer def start_column source.column(start_offset) end # The column in characters where this location ends from the start of # the line. + #-- + #: () -> Integer def start_character_column source.character_column(start_offset) end # The column in code units of the given encoding where this location # starts from the start of the line. + #-- + #: (?Encoding encoding) -> Integer def start_code_units_column(encoding = Encoding::UTF_16LE) source.code_units_column(start_offset, encoding) end # The start column in code units using the given cache to fetch or calculate # the value. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_column(cache) cache[start_offset] - cache[source.line_start(start_offset)] end # The column in bytes where this location ends from the start of the # line. + #-- + #: () -> Integer def end_column source.column(end_offset) end # The column in characters where this location ends from the start of # the line. + #-- + #: () -> Integer def end_character_column source.character_column(end_offset) end # The column in code units of the given encoding where this location # ends from the start of the line. + #-- + #: (?Encoding encoding) -> Integer def end_code_units_column(encoding = Encoding::UTF_16LE) source.code_units_column(end_offset, encoding) end # The end column in code units using the given cache to fetch or calculate # the value. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_end_code_units_column(cache) cache[end_offset] - cache[source.line_start(end_offset)] end # Implement the hash pattern matching interface for Location. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { start_offset: start_offset, end_offset: end_offset } end # Implement the pretty print interface for Location. + #-- + #: (PP q) -> void def pretty_print(q) # :nodoc: q.text("(#{start_line},#{start_column})-(#{end_line},#{end_column})") end # Returns true if the given other location is equal to this location. + #-- + #: (untyped other) -> bool def ==(other) Location === other && other.start_offset == start_offset && @@ -496,6 +640,8 @@ def ==(other) # Returns a new location that stretches from this location to the given # other location. Raises an error if this location is not before the other # location or if they don't share the same source. + #-- + #: (Location other) -> Location def join(other) raise "Incompatible sources" if source != other.source raise "Incompatible locations" if start_offset > other.start_offset @@ -506,6 +652,8 @@ def join(other) # Join this location with the first occurrence of the string in the source # that occurs after this location on the same line, and return the new # location. This will raise an error if the string does not exist. + #-- + #: (String string) -> Location def adjoin(string) line_suffix = source.slice(end_offset, source.line_end(end_offset) - end_offset) @@ -520,22 +668,37 @@ def adjoin(string) # base class for all comment types. class Comment # The Location of this comment in the source. - attr_reader :location + attr_reader :location #: Location # Create a new comment object with the given location. + #-- + #: (Location location) -> void def initialize(location) @location = location end # Implement the hash pattern matching interface for Comment. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { location: location } end # Returns the content of the comment by slicing it from the source code. + #-- + #: () -> String def slice location.slice end + + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. This can only be true for inline + # comments and should be false for block comments. + #-- + #: () -> bool + def trailing? + raise NotImplementedError, "trailing? is not implemented for #{self.class}" + end end # InlineComment objects are the most common. They correspond to comments in @@ -543,11 +706,15 @@ def slice class InlineComment < Comment # Returns true if this comment happens on the same line as other code and # false if the comment is by itself. + #-- + #: () -> bool def trailing? !location.start_line_slice.strip.empty? end # Returns a string representation of this comment. + #-- + #: () -> String def inspect # :nodoc: "#" end @@ -557,11 +724,15 @@ def inspect # :nodoc: # and =end. class EmbDocComment < Comment # Returns false. This can only be true for inline comments. + #-- + #: () -> bool def trailing? false end # Returns a string representation of this comment. + #-- + #: () -> String def inspect # :nodoc: "#" end @@ -570,33 +741,43 @@ def inspect # :nodoc: # This represents a magic comment that was encountered during parsing. class MagicComment # A Location object representing the location of the key in the source. - attr_reader :key_loc + attr_reader :key_loc #: Location # A Location object representing the location of the value in the source. - attr_reader :value_loc + attr_reader :value_loc #: Location # Create a new magic comment object with the given key and value locations. + #-- + #: (Location key_loc, Location value_loc) -> void def initialize(key_loc, value_loc) @key_loc = key_loc @value_loc = value_loc end # Returns the key of the magic comment by slicing it from the source code. + #-- + #: () -> String def key key_loc.slice end # Returns the value of the magic comment by slicing it from the source code. + #-- + #: () -> String def value value_loc.slice end # Implement the hash pattern matching interface for MagicComment. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { key_loc: key_loc, value_loc: value_loc } end # Returns a string representation of this magic comment. + #-- + #: () -> String def inspect # :nodoc: "#" end @@ -606,18 +787,20 @@ def inspect # :nodoc: class ParseError # The type of error. This is an _internal_ symbol that is used for # communicating with translation layers. It is not meant to be public API. - attr_reader :type + attr_reader :type #: Symbol # The message associated with this error. - attr_reader :message + attr_reader :message #: String # A Location object representing the location of this error in the source. - attr_reader :location + attr_reader :location #: Location # The level of this error. - attr_reader :level + attr_reader :level #: Symbol # Create a new error object with the given message and location. + #-- + #: (Symbol type, String message, Location location, Symbol level) -> void def initialize(type, message, location, level) @type = type @message = message @@ -626,11 +809,15 @@ def initialize(type, message, location, level) end # Implement the hash pattern matching interface for ParseError. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { type: type, message: message, location: location, level: level } end # Returns a string representation of this error. + #-- + #: () -> String def inspect # :nodoc: "#" end @@ -640,18 +827,20 @@ def inspect # :nodoc: class ParseWarning # The type of warning. This is an _internal_ symbol that is used for # communicating with translation layers. It is not meant to be public API. - attr_reader :type + attr_reader :type #: Symbol # The message associated with this warning. - attr_reader :message + attr_reader :message #: String # A Location object representing the location of this warning in the source. - attr_reader :location + attr_reader :location #: Location # The level of this warning. - attr_reader :level + attr_reader :level #: Symbol # Create a new warning object with the given message and location. + #-- + #: (Symbol type, String message, Location location, Symbol level) -> void def initialize(type, message, location, level) @type = type @message = message @@ -660,11 +849,15 @@ def initialize(type, message, location, level) end # Implement the hash pattern matching interface for ParseWarning. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { type: type, message: message, location: location, level: level } end # Returns a string representation of this warning. + #-- + #: () -> String def inspect # :nodoc: "#" end @@ -675,26 +868,28 @@ def inspect # :nodoc: # and any errors that were encountered. class Result # The list of comments that were encountered during parsing. - attr_reader :comments + attr_reader :comments #: Array[Comment] # The list of magic comments that were encountered during parsing. - attr_reader :magic_comments + attr_reader :magic_comments #: Array[MagicComment] # An optional location that represents the location of the __END__ marker # and the rest of the content of the file. This content is loaded into the # DATA constant when the file being parsed is the main file being executed. - attr_reader :data_loc + attr_reader :data_loc #: Location? # The list of errors that were generated during parsing. - attr_reader :errors + attr_reader :errors #: Array[ParseError] # The list of warnings that were generated during parsing. - attr_reader :warnings + attr_reader :warnings #: Array[ParseWarning] # A Source instance that represents the source code that was parsed. - attr_reader :source + attr_reader :source #: Source # Create a new result object with the given values. + #-- + #: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void def initialize(comments, magic_comments, data_loc, errors, warnings, source) @comments = comments @magic_comments = magic_comments @@ -705,28 +900,38 @@ def initialize(comments, magic_comments, data_loc, errors, warnings, source) end # Implement the hash pattern matching interface for Result. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings } end # Returns the encoding of the source code that was parsed. + #-- + #: () -> Encoding def encoding source.encoding end # Returns true if there were no errors during parsing and false if there # were. + #-- + #: () -> bool def success? errors.empty? end # Returns true if there were errors during parsing and false if there were # not. + #-- + #: () -> bool def failure? !success? end # Create a code units cache for the given encoding. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) source.code_units_cache(encoding) end @@ -743,32 +948,42 @@ class ParseResult < Result private_constant :Newlines # The syntax tree that was parsed from the source code. - attr_reader :value + attr_reader :value #: ProgramNode # Create a new parse result object with the given values. + #-- + #: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) @value = value super(comments, magic_comments, data_loc, errors, warnings, source) end # Implement the hash pattern matching interface for ParseResult. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end # Attach the list of comments to their respective locations in the tree. + #-- + #: () -> void def attach_comments! Comments.new(self).attach! # steep:ignore end # Walk the tree and mark nodes that are on a new line, loosely emulating # the behavior of CRuby's `:line` tracepoint event. + #-- + #: () -> void def mark_newlines! value.accept(Newlines.new(source.offsets.size)) # steep:ignore end # Returns a string representation of the syntax tree with the errors # displayed inline. + #-- + #: () -> String def errors_format Errors.new(self).format end @@ -777,15 +992,19 @@ def errors_format # This is a result specific to the `lex` and `lex_file` methods. class LexResult < Result # The list of tokens that were parsed from the source code. - attr_reader :value + attr_reader :value #: Array[[Token, Integer]] # Create a new lex result object with the given values. + #-- + #: (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) @value = value super(comments, magic_comments, data_loc, errors, warnings, source) end # Implement the hash pattern matching interface for LexResult. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end @@ -795,15 +1014,19 @@ def deconstruct_keys(keys) # :nodoc: class ParseLexResult < Result # A tuple of the syntax tree and the list of tokens that were parsed from # the source code. - attr_reader :value + attr_reader :value #: [ProgramNode, Array[[Token, Integer]]] # Create a new parse lex result object with the given values. + #-- + #: ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) @value = value super(comments, magic_comments, data_loc, errors, warnings, source) end # Implement the hash pattern matching interface for ParseLexResult. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: super.merge!(value: value) end @@ -812,16 +1035,20 @@ def deconstruct_keys(keys) # :nodoc: # This represents a token from the Ruby source. class Token # The Source object that represents the source this token came from. - attr_reader :source + attr_reader :source #: Source private :source # The type of token that this token is. - attr_reader :type + attr_reader :type #: Symbol # A byteslice of the source that this token represents. - attr_reader :value + attr_reader :value #: String + + # @rbs @location: Location | Integer # Create a new token object with the given type, value, and location. + #-- + #: (Source source, Symbol type, String value, Location | Integer location) -> void def initialize(source, type, value, location) @source = source @type = type @@ -830,11 +1057,15 @@ def initialize(source, type, value, location) end # Implement the hash pattern matching interface for Token. + #-- + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { type: type, value: value, location: location } end # A Location object representing the location of this token in the source. + #-- + #: () -> Location def location location = @location return location if location.is_a?(Location) @@ -842,6 +1073,8 @@ def location end # Implement the pretty print interface for Token. + #-- + #: (PP q) -> void def pretty_print(q) # :nodoc: q.group do q.text(type.to_s) @@ -857,6 +1090,8 @@ def pretty_print(q) # :nodoc: end # Returns true if the given other token is equal to this token. + #-- + #: (untyped other) -> bool def ==(other) Token === other && other.type == type && @@ -864,12 +1099,16 @@ def ==(other) end # Returns a string representation of this token. + #-- + #: () -> String def inspect # :nodoc: location super end # Freeze this object and the objects it contains. + #-- + #: () -> void def deep_freeze value.freeze location.freeze @@ -884,14 +1123,16 @@ def deep_freeze class Scope # The list of local variables that are defined in this scope. This should be # defined as an array of symbols. - attr_reader :locals + attr_reader :locals #: Array[Symbol] # The list of local variables that are forwarded to the next scope. This # should by defined as an array of symbols containing the specific values of # :*, :**, :&, or :"...". - attr_reader :forwarding + attr_reader :forwarding #: Array[Symbol] # Create a new scope object with the given locals and forwarding. + #-- + #: (Array[Symbol] locals, Array[Symbol] forwarding) -> void def initialize(locals, forwarding) @locals = locals @forwarding = forwarding @@ -901,6 +1142,8 @@ def initialize(locals, forwarding) # Create a new scope with the given locals and forwarding options that is # suitable for passing into one of the Prism.* methods that accepts the # `scopes` option. + #-- + #: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope def self.scope(locals: [], forwarding: []) Scope.new(locals, forwarding) end diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index 3e93316aff..7b54ce7fd6 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism @@ -18,32 +19,49 @@ class ParseResult < Result # the comment. Otherwise it will favor attaching to the nearest location # that is after the comment. class Comments + # @rbs! + # # An internal interface for a target that comments can be attached + # # to. This is either going to be a NodeTarget or a CommentTarget. + # interface _CommentTarget + # def start_offset: () -> Integer + # def end_offset: () -> Integer + # def encloses?: (Comment) -> bool + # def leading_comment: (Comment) -> void + # def trailing_comment: (Comment) -> void + # end + # A target for attaching comments that is based on a specific node's # location. class NodeTarget # :nodoc: - attr_reader :node + attr_reader :node #: node + #: (node node) -> void def initialize(node) @node = node end + #: () -> Integer def start_offset node.start_offset end + #: () -> Integer def end_offset node.end_offset end + #: (Comment comment) -> bool def encloses?(comment) start_offset <= comment.location.start_offset && comment.location.end_offset <= end_offset end + #: (Comment comment) -> void def leading_comment(comment) node.location.leading_comment(comment) end + #: (Comment comment) -> void def trailing_comment(comment) node.location.trailing_comment(comment) end @@ -52,44 +70,54 @@ def trailing_comment(comment) # A target for attaching comments that is based on a location field on a # node. For example, the `end` token of a ClassNode. class LocationTarget # :nodoc: - attr_reader :location + attr_reader :location #: Location + #: (Location location) -> void def initialize(location) @location = location end + #: () -> Integer def start_offset location.start_offset end + #: () -> Integer def end_offset location.end_offset end + #: (Comment comment) -> bool def encloses?(comment) false end + #: (Comment comment) -> void def leading_comment(comment) location.leading_comment(comment) end + #: (Comment comment) -> void def trailing_comment(comment) location.trailing_comment(comment) end end # The parse result that we are attaching comments to. - attr_reader :parse_result + attr_reader :parse_result #: ParseResult # Create a new Comments object that will attach comments to the given # parse result. + #-- + #: (ParseResult parse_result) -> void def initialize(parse_result) @parse_result = parse_result end # Attach the comments to their respective locations in the tree by # mutating the parse result. + #-- + #: () -> void def attach! parse_result.comments.each do |comment| preceding, enclosing, following = nearest_targets(parse_result.value, comment) @@ -117,11 +145,13 @@ def attach! # Responsible for finding the nearest targets to the given comment within # the context of the given encapsulating node. + #-- + #: (node node, Comment comment) -> [_CommentTarget?, _CommentTarget?, _CommentTarget?] def nearest_targets(node, comment) comment_start = comment.location.start_offset comment_end = comment.location.end_offset - targets = [] #: Array[_Target] + targets = [] #: Array[_CommentTarget] node.comment_targets.map do |value| case value when StatementsNode @@ -134,8 +164,8 @@ def nearest_targets(node, comment) end targets.sort_by!(&:start_offset) - preceding = nil #: _Target? - following = nil #: _Target? + preceding = nil #: _CommentTarget? + following = nil #: _CommentTarget? left = 0 right = targets.length diff --git a/lib/prism/parse_result/errors.rb b/lib/prism/parse_result/errors.rb index 26c376b3ce..03d65daecf 100644 --- a/lib/prism/parse_result/errors.rb +++ b/lib/prism/parse_result/errors.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown require "stringio" @@ -9,14 +10,18 @@ class ParseResult < Result # can be used to format the errors in a human-readable way. class Errors # The parse result that contains the errors. - attr_reader :parse_result + attr_reader :parse_result #: ParseResult # Initialize a new set of errors from the given parse result. + #-- + #: (ParseResult parse_result) -> void def initialize(parse_result) @parse_result = parse_result end # Formats the errors in a human-readable way and return them as a string. + #-- + #: () -> String def format error_lines = {} #: Hash[Integer, Array[ParseError]] parse_result.errors.each do |error| diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index e7fd62cafe..cfbc1ea1d0 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism @@ -24,13 +25,20 @@ class ParseResult < Result # that case. We do that to avoid storing the extra `@newline` instance # variable on every node if we don't need it. class Newlines < Visitor + # The map of lines indices to whether or not they have been marked as + # emitting a newline event. + # @rbs @lines: Array[bool] + # Create a new Newlines visitor with the given newline offsets. + #-- + #: (Integer lines) -> void def initialize(lines) - # @type var lines: Integer @lines = Array.new(1 + lines, false) end - # Permit block/lambda nodes to mark newlines within themselves. + # Permit block nodes to mark newlines within themselves. + #-- + #: (BlockNode node) -> void def visit_block_node(node) old_lines = @lines @lines = Array.new(old_lines.size, false) @@ -42,17 +50,39 @@ def visit_block_node(node) end end - alias_method :visit_lambda_node, :visit_block_node + # Permit lambda nodes to mark newlines within themselves. + #-- + #: (LambdaNode node) -> void + def visit_lambda_node(node) + old_lines = @lines + @lines = Array.new(old_lines.size, false) + + begin + super(node) + ensure + @lines = old_lines + end + end - # Mark if/unless nodes as newlines. + # Mark if nodes as newlines. + #-- + #: (IfNode node) -> void def visit_if_node(node) node.newline_flag!(@lines) super(node) end - alias_method :visit_unless_node, :visit_if_node + # Mark unless nodes as newlines. + #-- + #: (UnlessNode node) -> void + def visit_unless_node(node) + node.newline_flag!(@lines) + super(node) + end # Permit statements lists to mark newlines within themselves. + #-- + #: (StatementsNode node) -> void def visit_statements_node(node) node.body.each do |child| child.newline_flag!(@lines) @@ -63,10 +93,16 @@ def visit_statements_node(node) end class Node + # Tracks whether or not this node should emit a newline event when the + # instructions that it represents are executed. + # @rbs @newline_flag: bool + + #: () -> bool def newline_flag? # :nodoc: !!defined?(@newline_flag) end + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: line = location.start_line unless lines[line] @@ -77,48 +113,56 @@ def newline_flag!(lines) # :nodoc: end class BeginNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: # Never mark BeginNode with a newline flag, mark children instead. end end class ParenthesesNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: # Never mark ParenthesesNode with a newline flag, mark children instead. end end class IfNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class UnlessNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class UntilNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class WhileNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class RescueModifierNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: expression.newline_flag!(lines) end end class InterpolatedMatchLastLineNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -126,6 +170,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedRegularExpressionNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -133,6 +178,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedStringNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -140,6 +186,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedSymbolNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -147,6 +194,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedXStringNode < Node + # @rbs override def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index dde9d3b6f9..b15b04d9bc 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism @@ -41,6 +42,8 @@ class Pattern class CompilationError < StandardError # Create a new CompilationError with the given representation of the node # that caused the error. + #-- + #: (String repr) -> void def initialize(repr) # :nodoc: super(<<~ERROR) prism was unable to compile the pattern you provided into a usable @@ -57,10 +60,13 @@ def initialize(repr) # :nodoc: end # The query that this pattern was initialized with. - attr_reader :query + attr_reader :query #: String + # @rbs @compiled: Proc? # Create a new pattern with the given query. The query should be a string # containing a Ruby pattern matching expression. + #-- + #: (String query) -> void def initialize(query) @query = query @compiled = nil @@ -68,6 +74,8 @@ def initialize(query) # Compile the query into a callable object that can be used to match against # nodes. + #-- + #: () -> Proc def compile result = Prism.parse("case nil\nin #{query}\nend") @@ -84,6 +92,9 @@ def compile # pattern. If a block is given, it will be called with each node that # matches the pattern. If no block is given, an enumerator will be returned # that will yield each node that matches the pattern. + #-- + #: (node root) { (node) -> void } -> void + #: (node root) -> Enumerator[node, void] def scan(root) return to_enum(:scan, root) unless block_given? @@ -100,22 +111,32 @@ def scan(root) # Shortcut for combining two procs into one that returns true if both return # true. + #-- + #: (Proc left, Proc right) -> Proc def combine_and(left, right) # :nodoc: ->(other) { left.call(other) && right.call(other) } end # Shortcut for combining two procs into one that returns true if either # returns true. + #-- + #: (Proc left, Proc right) -> Proc def combine_or(left, right) # :nodoc: ->(other) { left.call(other) || right.call(other) } end - # Raise an error because the given node is not supported. + # Raise an error because the given node is not supported. Note purposefully + # not typing this method since it is a no return method that Steep does not + # understand. + #-- + #: (node node) -> bot def compile_error(node) # :nodoc: raise CompilationError, node.inspect end # in [foo, bar, baz] + #-- + #: (ArrayPatternNode node) -> Proc def compile_array_pattern_node(node) # :nodoc: compile_error(node) if !node.rest.nil? || node.posts.any? @@ -141,11 +162,15 @@ def compile_array_pattern_node(node) # :nodoc: end # in foo | bar + #-- + #: (AlternationPatternNode node) -> Proc def compile_alternation_pattern_node(node) # :nodoc: combine_or(compile_node(node.left), compile_node(node.right)) end # in Prism::ConstantReadNode + #-- + #: (ConstantPathNode node) -> Proc def compile_constant_path_node(node) # :nodoc: parent = node.parent @@ -161,11 +186,15 @@ def compile_constant_path_node(node) # :nodoc: # in ConstantReadNode # in String + #-- + #: (ConstantReadNode node) -> Proc def compile_constant_read_node(node) # :nodoc: compile_constant_name(node, node.name) end # Compile a name associated with a constant. + #-- + #: ((ConstantPathNode | ConstantReadNode) node, Symbol name) -> Proc def compile_constant_name(node, name) # :nodoc: if Prism.const_defined?(name, false) clazz = Prism.const_get(name) @@ -182,9 +211,14 @@ def compile_constant_name(node, name) # :nodoc: # in InstanceVariableReadNode[name: Symbol] # in { name: Symbol } + #-- + #: (HashPatternNode node) -> Proc def compile_hash_pattern_node(node) # :nodoc: compile_error(node) if node.rest - compiled_constant = compile_node(node.constant) if node.constant + + if (constant = node.constant) + compiled_constant = compile_node(constant) + end preprocessed = node.elements.to_h do |element| @@ -212,11 +246,15 @@ def compile_hash_pattern_node(node) # :nodoc: end # in nil + #-- + #: (NilNode node) -> Proc def compile_nil_node(node) # :nodoc: ->(attribute) { attribute.nil? } end # in /foo/ + #-- + #: (RegularExpressionNode node) -> Proc def compile_regular_expression_node(node) # :nodoc: regexp = Regexp.new(node.unescaped, node.closing[1..]) @@ -225,6 +263,8 @@ def compile_regular_expression_node(node) # :nodoc: # in "" # in "foo" + #-- + #: (StringNode node) -> Proc def compile_string_node(node) # :nodoc: string = node.unescaped @@ -233,6 +273,8 @@ def compile_string_node(node) # :nodoc: # in :+ # in :foo + #-- + #: (SymbolNode node) -> Proc def compile_symbol_node(node) # :nodoc: symbol = node.unescaped.to_sym @@ -241,6 +283,8 @@ def compile_symbol_node(node) # :nodoc: # Compile any kind of node. Dispatch out to the individual compilation # methods based on the type of node. + #-- + #: (node node) -> Proc def compile_node(node) # :nodoc: case node when AlternationPatternNode diff --git a/lib/prism/relocation.rb b/lib/prism/relocation.rb index 3e9210a785..2ac471d425 100644 --- a/lib/prism/relocation.rb +++ b/lib/prism/relocation.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism @@ -12,6 +13,33 @@ module Prism # "save" nodes and locations using a minimal amount of memory (just the # node_id and a field identifier) and then reify them later. module Relocation + # @rbs! + # type entry_value = untyped + # type entry_values = Hash[Symbol, entry_value] + # + # interface _Value + # def start_line: () -> Integer + # def end_line: () -> Integer + # def start_offset: () -> Integer + # def end_offset: () -> Integer + # def start_character_offset: () -> Integer + # def end_character_offset: () -> Integer + # def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + # def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + # def start_column: () -> Integer + # def end_column: () -> Integer + # def start_character_column: () -> Integer + # def end_character_column: () -> Integer + # def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + # def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + # def leading_comments: () -> Array[Comment] + # def trailing_comments: () -> Array[Comment] + # end + # + # interface _Field + # def fields: (_Value value) -> entry_values + # end + # An entry in a repository that will lazily reify its values when they are # first accessed. class Entry @@ -21,109 +49,152 @@ class Entry class MissingValueError < StandardError end + # @rbs @repository: Repository? + # @rbs @values: Hash[Symbol, untyped]? + # Initialize a new entry with the given repository. + #-- + #: (Repository repository) -> void def initialize(repository) @repository = repository @values = nil end # Fetch the filepath of the value. + #-- + #: () -> String def filepath fetch_value(:filepath) end # Fetch the start line of the value. + #-- + #: () -> Integer def start_line fetch_value(:start_line) end # Fetch the end line of the value. + #-- + #: () -> Integer def end_line fetch_value(:end_line) end # Fetch the start byte offset of the value. + #-- + #: () -> Integer def start_offset fetch_value(:start_offset) end # Fetch the end byte offset of the value. + #-- + #: () -> Integer def end_offset fetch_value(:end_offset) end # Fetch the start character offset of the value. + #-- + #: () -> Integer def start_character_offset fetch_value(:start_character_offset) end # Fetch the end character offset of the value. + #-- + #: () -> Integer def end_character_offset fetch_value(:end_character_offset) end # Fetch the start code units offset of the value, for the encoding that # was configured on the repository. + #-- + #: () -> Integer def start_code_units_offset fetch_value(:start_code_units_offset) end # Fetch the end code units offset of the value, for the encoding that was # configured on the repository. + #-- + #: () -> Integer def end_code_units_offset fetch_value(:end_code_units_offset) end # Fetch the start byte column of the value. + #-- + #: () -> Integer def start_column fetch_value(:start_column) end # Fetch the end byte column of the value. + #-- + #: () -> Integer def end_column fetch_value(:end_column) end # Fetch the start character column of the value. + #-- + #: () -> Integer def start_character_column fetch_value(:start_character_column) end # Fetch the end character column of the value. + #-- + #: () -> Integer def end_character_column fetch_value(:end_character_column) end # Fetch the start code units column of the value, for the encoding that # was configured on the repository. + #-- + #: () -> Integer def start_code_units_column fetch_value(:start_code_units_column) end # Fetch the end code units column of the value, for the encoding that was # configured on the repository. + #-- + #: () -> Integer def end_code_units_column fetch_value(:end_code_units_column) end # Fetch the leading comments of the value. + #-- + #: () -> Array[CommentsField::Comment] def leading_comments fetch_value(:leading_comments) end # Fetch the trailing comments of the value. + #-- + #: () -> Array[CommentsField::Comment] def trailing_comments fetch_value(:trailing_comments) end # Fetch the leading and trailing comments of the value. + #-- + #: () -> Array[CommentsField::Comment] def comments - leading_comments.concat(trailing_comments) + [*leading_comments, *trailing_comments] end # Reify the values on this entry with the given values. This is an # internal-only API that is called from the repository when it is time to # reify the values. + #-- + #: (entry_values values) -> void def reify!(values) # :nodoc: @repository = nil @values = values @@ -132,6 +203,8 @@ def reify!(values) # :nodoc: private # Fetch a value from the entry, raising an error if it is missing. + #-- + #: (Symbol name) -> entry_value def fetch_value(name) values.fetch(name) do raise MissingValueError, "No value for #{name}, make sure the " \ @@ -140,27 +213,35 @@ def fetch_value(name) end # Return the values from the repository, reifying them if necessary. + #-- + #: () -> entry_values def values - @values || (@repository.reify!; @values) + @values || (@repository&.reify!; @values) #: entry_values end end # Represents the source of a repository that will be reparsed. class Source # The value that will need to be reparsed. - attr_reader :value + attr_reader :value #: untyped # Initialize the source with the given value. + #-- + #: (untyped value) -> void def initialize(value) @value = value end # Reparse the value and return the parse result. + #-- + #: () -> ParseResult def result raise NotImplementedError, "Subclasses must implement #result" end # Create a code units cache for the given encoding. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) result.code_units_cache(encoding) end @@ -169,6 +250,8 @@ def code_units_cache(encoding) # A source that is represented by a file path. class SourceFilepath < Source # Reparse the file and return the parse result. + #-- + #: () -> ParseResult def result Prism.parse_file(value) end @@ -177,6 +260,8 @@ def result # A source that is represented by a string. class SourceString < Source # Reparse the string and return the parse result. + #-- + #: () -> ParseResult def result Prism.parse(value) end @@ -185,14 +270,18 @@ def result # A field that represents the file path. class FilepathField # The file path that this field represents. - attr_reader :value + attr_reader :value #: String # Initialize a new field with the given file path. + #-- + #: (String value) -> void def initialize(value) @value = value end # Fetch the file path. + #-- + #: (_Value _value) -> entry_values def fields(_value) { filepath: value } end @@ -201,6 +290,8 @@ def fields(_value) # A field representing the start and end lines. class LinesField # Fetches the start and end line of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_line: value.start_line, end_line: value.end_line } end @@ -209,6 +300,8 @@ def fields(value) # A field representing the start and end byte offsets. class OffsetsField # Fetches the start and end byte offset of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_offset: value.start_offset, end_offset: value.end_offset } end @@ -217,6 +310,8 @@ def fields(value) # A field representing the start and end character offsets. class CharacterOffsetsField # Fetches the start and end character offset of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_character_offset: value.start_character_offset, @@ -229,12 +324,16 @@ def fields(value) class CodeUnitOffsetsField # A pointer to the repository object that is used for lazily creating a # code units cache. - attr_reader :repository + attr_reader :repository #: Repository # The associated encoding for the code units. - attr_reader :encoding + attr_reader :encoding #: Encoding + + # @rbs @cache: _CodeUnitsCache? # Initialize a new field with the associated repository and encoding. + #-- + #: (Repository repository, Encoding encoding) -> void def initialize(repository, encoding) @repository = repository @encoding = encoding @@ -243,6 +342,8 @@ def initialize(repository, encoding) # Fetches the start and end code units offset of a value for a particular # encoding. + #-- + #: (_Value value) -> entry_values def fields(value) { start_code_units_offset: value.cached_start_code_units_offset(cache), @@ -253,6 +354,8 @@ def fields(value) private # Lazily create a code units cache for the associated encoding. + #-- + #: () -> _CodeUnitsCache def cache @cache ||= repository.code_units_cache(encoding) end @@ -261,6 +364,8 @@ def cache # A field representing the start and end byte columns. class ColumnsField # Fetches the start and end byte column of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_column: value.start_column, end_column: value.end_column } end @@ -269,6 +374,8 @@ def fields(value) # A field representing the start and end character columns. class CharacterColumnsField # Fetches the start and end character column of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { start_character_column: value.start_character_column, @@ -282,12 +389,16 @@ def fields(value) class CodeUnitColumnsField # The repository object that is used for lazily creating a code units # cache. - attr_reader :repository + attr_reader :repository #: Repository # The associated encoding for the code units. - attr_reader :encoding + attr_reader :encoding #: Encoding + + # @rbs @cache: _CodeUnitsCache? # Initialize a new field with the associated repository and encoding. + #-- + #: (Repository repository, Encoding encoding) -> void def initialize(repository, encoding) @repository = repository @encoding = encoding @@ -296,6 +407,8 @@ def initialize(repository, encoding) # Fetches the start and end code units column of a value for a particular # encoding. + #-- + #: (_Value value) -> entry_values def fields(value) { start_code_units_column: value.cached_start_code_units_column(cache), @@ -306,6 +419,8 @@ def fields(value) private # Lazily create a code units cache for the associated encoding. + #-- + #: () -> _CodeUnitsCache def cache @cache ||= repository.code_units_cache(encoding) end @@ -316,9 +431,11 @@ class CommentsField # An object that represents a slice of a comment. class Comment # The slice of the comment. - attr_reader :slice + attr_reader :slice #: String # Initialize a new comment with the given slice. + # + #: (String slice) -> void def initialize(slice) @slice = slice end @@ -327,6 +444,8 @@ def initialize(slice) private # Create comment objects from the given values. + #-- + #: (entry_value values) -> Array[Comment] def comments(values) values.map { |value| Comment.new(value.slice) } end @@ -335,6 +454,8 @@ def comments(values) # A field representing the leading comments. class LeadingCommentsField < CommentsField # Fetches the leading comments of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { leading_comments: comments(value.leading_comments) } end @@ -343,6 +464,8 @@ def fields(value) # A field representing the trailing comments. class TrailingCommentsField < CommentsField # Fetches the trailing comments of a value. + #-- + #: (_Value value) -> entry_values def fields(value) { trailing_comments: comments(value.trailing_comments) } end @@ -358,15 +481,17 @@ class ConfigurationError < StandardError # The source associated with this repository. This will be either a # SourceFilepath (the most common use case) or a SourceString. - attr_reader :source + attr_reader :source #: Source # The fields that have been configured on this repository. - attr_reader :fields + attr_reader :fields #: Hash[Symbol, _Field] # The entries that have been saved on this repository. - attr_reader :entries + attr_reader :entries #: Hash[Integer, Hash[Symbol, Entry]] # Initialize a new repository with the given source. + #-- + #: (Source source) -> void def initialize(source) @source = source @fields = {} @@ -374,69 +499,93 @@ def initialize(source) end # Create a code units cache for the given encoding from the source. + #-- + #: (Encoding encoding) -> _CodeUnitsCache def code_units_cache(encoding) source.code_units_cache(encoding) end # Configure the filepath field for this repository and return self. + #-- + #: () -> self def filepath raise ConfigurationError, "Can only specify filepath for a filepath source" unless source.is_a?(SourceFilepath) field(:filepath, FilepathField.new(source.value)) end # Configure the lines field for this repository and return self. + #-- + #: () -> self def lines field(:lines, LinesField.new) end # Configure the offsets field for this repository and return self. + #-- + #: () -> self def offsets field(:offsets, OffsetsField.new) end # Configure the character offsets field for this repository and return # self. + #-- + #: () -> self def character_offsets field(:character_offsets, CharacterOffsetsField.new) end # Configure the code unit offsets field for this repository for a specific # encoding and return self. + #-- + #: (Encoding encoding) -> self def code_unit_offsets(encoding) field(:code_unit_offsets, CodeUnitOffsetsField.new(self, encoding)) end # Configure the columns field for this repository and return self. + #-- + #: () -> self def columns field(:columns, ColumnsField.new) end # Configure the character columns field for this repository and return # self. + #-- + #: () -> self def character_columns field(:character_columns, CharacterColumnsField.new) end # Configure the code unit columns field for this repository for a specific # encoding and return self. + #-- + #: (Encoding encoding) -> self def code_unit_columns(encoding) field(:code_unit_columns, CodeUnitColumnsField.new(self, encoding)) end # Configure the leading comments field for this repository and return # self. + #-- + #: () -> self def leading_comments field(:leading_comments, LeadingCommentsField.new) end # Configure the trailing comments field for this repository and return # self. + #-- + #: () -> self def trailing_comments field(:trailing_comments, TrailingCommentsField.new) end # Configure both the leading and trailing comment fields for this # repository and return self. + #-- + #: () -> self def comments leading_comments.trailing_comments end @@ -444,6 +593,8 @@ def comments # This method is called from nodes and locations when they want to enter # themselves into the repository. It it internal-only and meant to be # called from the #save* APIs. + #-- + #: (Integer node_id, Symbol field_name) -> Entry def enter(node_id, field_name) # :nodoc: entry = Entry.new(self) @entries[node_id][field_name] = entry @@ -453,6 +604,8 @@ def enter(node_id, field_name) # :nodoc: # This method is called from the entries in the repository when they need # to reify their values. It is internal-only and meant to be called from # the various value APIs. + #-- + #: () -> void def reify! # :nodoc: result = source.result @@ -466,7 +619,7 @@ def reify! # :nodoc: while (node = queue.shift) @entries[node.node_id].each do |field_name, entry| value = node.public_send(field_name) - values = {} #: Hash[Symbol, untyped] + values = {} #: entry_values fields.each_value do |field| values.merge!(field.fields(value)) @@ -485,6 +638,8 @@ def reify! # :nodoc: # Append the given field to the repository and return the repository so # that these calls can be chained. + #-- + #: (Symbol name, _Field) -> self def field(name, value) raise ConfigurationError, "Cannot specify multiple #{name} fields" if @fields.key?(name) @fields[name] = value @@ -493,11 +648,15 @@ def field(name, value) end # Create a new repository for the given filepath. + #-- + #: (String value) -> Repository def self.filepath(value) Repository.new(SourceFilepath.new(value)) end # Create a new repository for the given string. + #-- + #: (String value) -> Repository def self.string(value) Repository.new(SourceString.new(value)) end diff --git a/lib/prism/string_query.rb b/lib/prism/string_query.rb index 547f58d2fa..c0dee63d3f 100644 --- a/lib/prism/string_query.rb +++ b/lib/prism/string_query.rb @@ -1,29 +1,43 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism # Query methods that allow categorizing strings based on their context for # where they could be valid in a Ruby syntax tree. class StringQuery + # @rbs! + # def self.local?: (String string) -> bool + # def self.constant?: (String string) -> bool + # def self.method_name?: (String string) -> bool + # The string that this query is wrapping. - attr_reader :string + attr_reader :string #: String # Initialize a new query with the given string. + #-- + #: (String string) -> void def initialize(string) @string = string end # Whether or not this string is a valid local variable name. + #-- + #: () -> bool def local? StringQuery.local?(string) end # Whether or not this string is a valid constant name. + #-- + #: () -> bool def constant? StringQuery.constant?(string) end # Whether or not this string is a valid method name. + #-- + #: () -> bool def method_name? StringQuery.method_name?(string) end diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb index 57b57135bc..d1afa5d8c5 100644 --- a/lib/prism/translation.rb +++ b/lib/prism/translation.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# rbs_inline: enabled # :markup: markdown module Prism diff --git a/lib/prism/translation/parser_current.rb b/lib/prism/translation/parser_current.rb index f13eff6bbe..2dd018627c 100644 --- a/lib/prism/translation/parser_current.rb +++ b/lib/prism/translation/parser_current.rb @@ -2,7 +2,6 @@ # :markup: markdown # typed: ignore -# module Prism module Translation case RUBY_VERSION diff --git a/prism.gemspec b/prism.gemspec index dde7e711e2..f3cba41a43 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -123,24 +123,28 @@ Gem::Specification.new do |spec| "rbi/prism/translation/parser_versions.rbi", "rbi/prism/translation/ripper.rbi", "rbi/prism/visitor.rbi", - "sig/prism.rbs", - "sig/prism/compiler.rbs", - "sig/prism/dispatcher.rbs", - "sig/prism/dot_visitor.rbs", - "sig/prism/dsl.rbs", - "sig/prism/inspect_visitor.rbs", - "sig/prism/lex_compat.rbs", - "sig/prism/mutation_compiler.rbs", - "sig/prism/node_ext.rbs", - "sig/prism/node.rbs", - "sig/prism/parse_result.rbs", - "sig/prism/parse_result/comments.rbs", - "sig/prism/pattern.rbs", - "sig/prism/reflection.rbs", - "sig/prism/relocation.rbs", - "sig/prism/serialize.rbs", - "sig/prism/string_query.rbs", - "sig/prism/visitor.rbs", + "sig/generated/prism.rbs", + "sig/generated/prism/compiler.rbs", + "sig/generated/prism/desugar_compiler.rbs", + "sig/generated/prism/dispatcher.rbs", + "sig/generated/prism/dot_visitor.rbs", + "sig/generated/prism/dsl.rbs", + "sig/generated/prism/inspect_visitor.rbs", + "sig/generated/prism/lex_compat.rbs", + "sig/generated/prism/mutation_compiler.rbs", + "sig/generated/prism/node.rbs", + "sig/generated/prism/node_ext.rbs", + "sig/generated/prism/parse_result.rbs", + "sig/generated/prism/pattern.rbs", + "sig/generated/prism/reflection.rbs", + "sig/generated/prism/relocation.rbs", + "sig/generated/prism/serialize.rbs", + "sig/generated/prism/string_query.rbs", + "sig/generated/prism/translation.rbs", + "sig/generated/prism/visitor.rbs", + "sig/generated/prism/parse_result/comments.rbs", + "sig/generated/prism/parse_result/errors.rbs", + "sig/generated/prism/parse_result/newlines.rbs", "src/diagnostic.c", "src/encoding.c", "src/node.c", diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index 55a8730106..52cc0d17f1 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -38,6 +38,7 @@ namespace :typecheck do - ./lib/prism/translation/ripper/sexp.rb - ./lib/prism/translation/ruby_parser.rb - ./lib/prism/inspect_visitor.rb + - ./lib/prism/serialize.rb - ./sample/prism/multiplex_constants.rb # We want to treat all polyfill files as "typed: false" <% polyfills.each do |file| -%> @@ -76,6 +77,13 @@ namespace :typecheck do end end + desc "Generate RBS with rbs-inline" + task rbs_inline: :templates do + with_gemfile do + sh "bundle", "exec", "rbs-inline", "lib", "--output", "lib" + end + end + desc "Typecheck with Steep" task steep: :templates do with_gemfile do diff --git a/sig/generated/prism.rbs b/sig/generated/prism.rbs new file mode 100644 index 0000000000..4777914d3e --- /dev/null +++ b/sig/generated/prism.rbs @@ -0,0 +1,76 @@ +# Generated from lib/prism.rb with RBS::Inline + +# The Prism Ruby parser. +# +# "Parsing Ruby is suddenly manageable!" +# - You, hopefully +module Prism + # Raised when requested to parse as the currently running Ruby version but Prism has no support for it. + class CurrentVersionError < ArgumentError + # Initialize a new exception for the given ruby version string. + # -- + # : (String version) -> void + def initialize: (String version) -> void + end + + # :call-seq: + # lex_compat(source, **options) -> LexCompat::Result + # + # Returns a parse result whose value is an array of tokens that closely + # resembles the return value of Ripper.lex. + # + # For supported options, see Prism.parse. + # -- + # : (String source, **untyped options) -> LexCompat::Result + def self.lex_compat: (String source, **untyped options) -> LexCompat::Result + + # :call-seq: + # load(source, serialized, freeze) -> ParseResult + # + # Load the serialized AST using the source as a reference into a tree. + # -- + # : (String source, String serialized, ?bool freeze) -> ParseResult + def self.load: (String source, String serialized, ?bool freeze) -> ParseResult + + VERSION: String + + BACKEND: :CEXT | :FFI + + interface _Stream + def gets: (?Integer integer) -> (String | nil) + end + + def self.parse: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + + def self.profile: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + + def self.lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + + def self.parse_lex: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + + def self.dump: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + + def self.parse_comments: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + + def self.parse_success?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + + def self.parse_failure?: (String source, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + + def self.parse_stream: (_Stream stream, ?filepath: String, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + + def self.parse_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseResult + + def self.profile_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> void + + def self.lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> LexResult + + def self.parse_lex_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> ParseLexResult + + def self.dump_file: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> String + + def self.parse_file_comments: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> Array[Comment] + + def self.parse_file_success?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool + + def self.parse_file_failure?: (String filepath, ?command_line: String, ?encoding: Encoding | false, ?freeze: bool, ?frozen_string_literal: bool, ?line: Integer, ?main_script: bool, ?partial_script: bool, ?scopes: Array[Array[Symbol]], ?version: String) -> bool +end diff --git a/sig/generated/prism/compiler.rbs b/sig/generated/prism/compiler.rbs new file mode 100644 index 0000000000..c2e4db0ace --- /dev/null +++ b/sig/generated/prism/compiler.rbs @@ -0,0 +1,492 @@ +# Generated from lib/prism/compiler.rb with RBS::Inline + +module Prism + # A compiler is a visitor that returns the value of each node as it visits. + # This is as opposed to a visitor which will only walk the tree. This can be + # useful when you are trying to compile a tree into a different format. + # + # For example, to build a representation of the tree as s-expressions, you + # could write: + # + # class SExpressions < Prism::Compiler + # def visit_arguments_node(node) = [:arguments, super] + # def visit_call_node(node) = [:call, super] + # def visit_integer_node(node) = [:integer] + # def visit_program_node(node) = [:program, super] + # end + # + # Prism.parse("1 + 2").value.accept(SExpressions.new) + # # => [:program, [[[:call, [[:integer], [:arguments, [[:integer]]]]]]]] + class Compiler < Visitor + # Visit an individual node. + # -- + # : (node?) -> untyped + def visit: (node?) -> untyped + + # Visit a list of nodes. + # -- + # : (Array[node?]) -> untyped + def visit_all: (Array[node?]) -> untyped + + # Visit the child nodes of the given node. + # -- + # : (node) -> Array[untyped] + def visit_child_nodes: (node) -> Array[untyped] + + # : (AliasGlobalVariableNode) -> Array[untyped] + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> Array[untyped] + + # : (AliasMethodNode) -> Array[untyped] + def visit_alias_method_node: (AliasMethodNode) -> Array[untyped] + + # : (AlternationPatternNode) -> Array[untyped] + def visit_alternation_pattern_node: (AlternationPatternNode) -> Array[untyped] + + # : (AndNode) -> Array[untyped] + def visit_and_node: (AndNode) -> Array[untyped] + + # : (ArgumentsNode) -> Array[untyped] + def visit_arguments_node: (ArgumentsNode) -> Array[untyped] + + # : (ArrayNode) -> Array[untyped] + def visit_array_node: (ArrayNode) -> Array[untyped] + + # : (ArrayPatternNode) -> Array[untyped] + def visit_array_pattern_node: (ArrayPatternNode) -> Array[untyped] + + # : (AssocNode) -> Array[untyped] + def visit_assoc_node: (AssocNode) -> Array[untyped] + + # : (AssocSplatNode) -> Array[untyped] + def visit_assoc_splat_node: (AssocSplatNode) -> Array[untyped] + + # : (BackReferenceReadNode) -> Array[untyped] + def visit_back_reference_read_node: (BackReferenceReadNode) -> Array[untyped] + + # : (BeginNode) -> Array[untyped] + def visit_begin_node: (BeginNode) -> Array[untyped] + + # : (BlockArgumentNode) -> Array[untyped] + def visit_block_argument_node: (BlockArgumentNode) -> Array[untyped] + + # : (BlockLocalVariableNode) -> Array[untyped] + def visit_block_local_variable_node: (BlockLocalVariableNode) -> Array[untyped] + + # : (BlockNode) -> Array[untyped] + def visit_block_node: (BlockNode) -> Array[untyped] + + # : (BlockParameterNode) -> Array[untyped] + def visit_block_parameter_node: (BlockParameterNode) -> Array[untyped] + + # : (BlockParametersNode) -> Array[untyped] + def visit_block_parameters_node: (BlockParametersNode) -> Array[untyped] + + # : (BreakNode) -> Array[untyped] + def visit_break_node: (BreakNode) -> Array[untyped] + + # : (CallAndWriteNode) -> Array[untyped] + def visit_call_and_write_node: (CallAndWriteNode) -> Array[untyped] + + # : (CallNode) -> Array[untyped] + def visit_call_node: (CallNode) -> Array[untyped] + + # : (CallOperatorWriteNode) -> Array[untyped] + def visit_call_operator_write_node: (CallOperatorWriteNode) -> Array[untyped] + + # : (CallOrWriteNode) -> Array[untyped] + def visit_call_or_write_node: (CallOrWriteNode) -> Array[untyped] + + # : (CallTargetNode) -> Array[untyped] + def visit_call_target_node: (CallTargetNode) -> Array[untyped] + + # : (CapturePatternNode) -> Array[untyped] + def visit_capture_pattern_node: (CapturePatternNode) -> Array[untyped] + + # : (CaseMatchNode) -> Array[untyped] + def visit_case_match_node: (CaseMatchNode) -> Array[untyped] + + # : (CaseNode) -> Array[untyped] + def visit_case_node: (CaseNode) -> Array[untyped] + + # : (ClassNode) -> Array[untyped] + def visit_class_node: (ClassNode) -> Array[untyped] + + # : (ClassVariableAndWriteNode) -> Array[untyped] + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> Array[untyped] + + # : (ClassVariableOperatorWriteNode) -> Array[untyped] + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> Array[untyped] + + # : (ClassVariableOrWriteNode) -> Array[untyped] + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> Array[untyped] + + # : (ClassVariableReadNode) -> Array[untyped] + def visit_class_variable_read_node: (ClassVariableReadNode) -> Array[untyped] + + # : (ClassVariableTargetNode) -> Array[untyped] + def visit_class_variable_target_node: (ClassVariableTargetNode) -> Array[untyped] + + # : (ClassVariableWriteNode) -> Array[untyped] + def visit_class_variable_write_node: (ClassVariableWriteNode) -> Array[untyped] + + # : (ConstantAndWriteNode) -> Array[untyped] + def visit_constant_and_write_node: (ConstantAndWriteNode) -> Array[untyped] + + # : (ConstantOperatorWriteNode) -> Array[untyped] + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> Array[untyped] + + # : (ConstantOrWriteNode) -> Array[untyped] + def visit_constant_or_write_node: (ConstantOrWriteNode) -> Array[untyped] + + # : (ConstantPathAndWriteNode) -> Array[untyped] + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> Array[untyped] + + # : (ConstantPathNode) -> Array[untyped] + def visit_constant_path_node: (ConstantPathNode) -> Array[untyped] + + # : (ConstantPathOperatorWriteNode) -> Array[untyped] + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> Array[untyped] + + # : (ConstantPathOrWriteNode) -> Array[untyped] + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> Array[untyped] + + # : (ConstantPathTargetNode) -> Array[untyped] + def visit_constant_path_target_node: (ConstantPathTargetNode) -> Array[untyped] + + # : (ConstantPathWriteNode) -> Array[untyped] + def visit_constant_path_write_node: (ConstantPathWriteNode) -> Array[untyped] + + # : (ConstantReadNode) -> Array[untyped] + def visit_constant_read_node: (ConstantReadNode) -> Array[untyped] + + # : (ConstantTargetNode) -> Array[untyped] + def visit_constant_target_node: (ConstantTargetNode) -> Array[untyped] + + # : (ConstantWriteNode) -> Array[untyped] + def visit_constant_write_node: (ConstantWriteNode) -> Array[untyped] + + # : (DefNode) -> Array[untyped] + def visit_def_node: (DefNode) -> Array[untyped] + + # : (DefinedNode) -> Array[untyped] + def visit_defined_node: (DefinedNode) -> Array[untyped] + + # : (ElseNode) -> Array[untyped] + def visit_else_node: (ElseNode) -> Array[untyped] + + # : (EmbeddedStatementsNode) -> Array[untyped] + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> Array[untyped] + + # : (EmbeddedVariableNode) -> Array[untyped] + def visit_embedded_variable_node: (EmbeddedVariableNode) -> Array[untyped] + + # : (EnsureNode) -> Array[untyped] + def visit_ensure_node: (EnsureNode) -> Array[untyped] + + # : (FalseNode) -> Array[untyped] + def visit_false_node: (FalseNode) -> Array[untyped] + + # : (FindPatternNode) -> Array[untyped] + def visit_find_pattern_node: (FindPatternNode) -> Array[untyped] + + # : (FlipFlopNode) -> Array[untyped] + def visit_flip_flop_node: (FlipFlopNode) -> Array[untyped] + + # : (FloatNode) -> Array[untyped] + def visit_float_node: (FloatNode) -> Array[untyped] + + # : (ForNode) -> Array[untyped] + def visit_for_node: (ForNode) -> Array[untyped] + + # : (ForwardingArgumentsNode) -> Array[untyped] + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> Array[untyped] + + # : (ForwardingParameterNode) -> Array[untyped] + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> Array[untyped] + + # : (ForwardingSuperNode) -> Array[untyped] + def visit_forwarding_super_node: (ForwardingSuperNode) -> Array[untyped] + + # : (GlobalVariableAndWriteNode) -> Array[untyped] + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> Array[untyped] + + # : (GlobalVariableOperatorWriteNode) -> Array[untyped] + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> Array[untyped] + + # : (GlobalVariableOrWriteNode) -> Array[untyped] + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> Array[untyped] + + # : (GlobalVariableReadNode) -> Array[untyped] + def visit_global_variable_read_node: (GlobalVariableReadNode) -> Array[untyped] + + # : (GlobalVariableTargetNode) -> Array[untyped] + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> Array[untyped] + + # : (GlobalVariableWriteNode) -> Array[untyped] + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> Array[untyped] + + # : (HashNode) -> Array[untyped] + def visit_hash_node: (HashNode) -> Array[untyped] + + # : (HashPatternNode) -> Array[untyped] + def visit_hash_pattern_node: (HashPatternNode) -> Array[untyped] + + # : (IfNode) -> Array[untyped] + def visit_if_node: (IfNode) -> Array[untyped] + + # : (ImaginaryNode) -> Array[untyped] + def visit_imaginary_node: (ImaginaryNode) -> Array[untyped] + + # : (ImplicitNode) -> Array[untyped] + def visit_implicit_node: (ImplicitNode) -> Array[untyped] + + # : (ImplicitRestNode) -> Array[untyped] + def visit_implicit_rest_node: (ImplicitRestNode) -> Array[untyped] + + # : (InNode) -> Array[untyped] + def visit_in_node: (InNode) -> Array[untyped] + + # : (IndexAndWriteNode) -> Array[untyped] + def visit_index_and_write_node: (IndexAndWriteNode) -> Array[untyped] + + # : (IndexOperatorWriteNode) -> Array[untyped] + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> Array[untyped] + + # : (IndexOrWriteNode) -> Array[untyped] + def visit_index_or_write_node: (IndexOrWriteNode) -> Array[untyped] + + # : (IndexTargetNode) -> Array[untyped] + def visit_index_target_node: (IndexTargetNode) -> Array[untyped] + + # : (InstanceVariableAndWriteNode) -> Array[untyped] + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> Array[untyped] + + # : (InstanceVariableOperatorWriteNode) -> Array[untyped] + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> Array[untyped] + + # : (InstanceVariableOrWriteNode) -> Array[untyped] + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> Array[untyped] + + # : (InstanceVariableReadNode) -> Array[untyped] + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> Array[untyped] + + # : (InstanceVariableTargetNode) -> Array[untyped] + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> Array[untyped] + + # : (InstanceVariableWriteNode) -> Array[untyped] + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> Array[untyped] + + # : (IntegerNode) -> Array[untyped] + def visit_integer_node: (IntegerNode) -> Array[untyped] + + # : (InterpolatedMatchLastLineNode) -> Array[untyped] + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> Array[untyped] + + # : (InterpolatedRegularExpressionNode) -> Array[untyped] + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> Array[untyped] + + # : (InterpolatedStringNode) -> Array[untyped] + def visit_interpolated_string_node: (InterpolatedStringNode) -> Array[untyped] + + # : (InterpolatedSymbolNode) -> Array[untyped] + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> Array[untyped] + + # : (InterpolatedXStringNode) -> Array[untyped] + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> Array[untyped] + + # : (ItLocalVariableReadNode) -> Array[untyped] + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> Array[untyped] + + # : (ItParametersNode) -> Array[untyped] + def visit_it_parameters_node: (ItParametersNode) -> Array[untyped] + + # : (KeywordHashNode) -> Array[untyped] + def visit_keyword_hash_node: (KeywordHashNode) -> Array[untyped] + + # : (KeywordRestParameterNode) -> Array[untyped] + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> Array[untyped] + + # : (LambdaNode) -> Array[untyped] + def visit_lambda_node: (LambdaNode) -> Array[untyped] + + # : (LocalVariableAndWriteNode) -> Array[untyped] + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> Array[untyped] + + # : (LocalVariableOperatorWriteNode) -> Array[untyped] + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> Array[untyped] + + # : (LocalVariableOrWriteNode) -> Array[untyped] + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> Array[untyped] + + # : (LocalVariableReadNode) -> Array[untyped] + def visit_local_variable_read_node: (LocalVariableReadNode) -> Array[untyped] + + # : (LocalVariableTargetNode) -> Array[untyped] + def visit_local_variable_target_node: (LocalVariableTargetNode) -> Array[untyped] + + # : (LocalVariableWriteNode) -> Array[untyped] + def visit_local_variable_write_node: (LocalVariableWriteNode) -> Array[untyped] + + # : (MatchLastLineNode) -> Array[untyped] + def visit_match_last_line_node: (MatchLastLineNode) -> Array[untyped] + + # : (MatchPredicateNode) -> Array[untyped] + def visit_match_predicate_node: (MatchPredicateNode) -> Array[untyped] + + # : (MatchRequiredNode) -> Array[untyped] + def visit_match_required_node: (MatchRequiredNode) -> Array[untyped] + + # : (MatchWriteNode) -> Array[untyped] + def visit_match_write_node: (MatchWriteNode) -> Array[untyped] + + # : (MissingNode) -> Array[untyped] + def visit_missing_node: (MissingNode) -> Array[untyped] + + # : (ModuleNode) -> Array[untyped] + def visit_module_node: (ModuleNode) -> Array[untyped] + + # : (MultiTargetNode) -> Array[untyped] + def visit_multi_target_node: (MultiTargetNode) -> Array[untyped] + + # : (MultiWriteNode) -> Array[untyped] + def visit_multi_write_node: (MultiWriteNode) -> Array[untyped] + + # : (NextNode) -> Array[untyped] + def visit_next_node: (NextNode) -> Array[untyped] + + # : (NilNode) -> Array[untyped] + def visit_nil_node: (NilNode) -> Array[untyped] + + # : (NoBlockParameterNode) -> Array[untyped] + def visit_no_block_parameter_node: (NoBlockParameterNode) -> Array[untyped] + + # : (NoKeywordsParameterNode) -> Array[untyped] + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> Array[untyped] + + # : (NumberedParametersNode) -> Array[untyped] + def visit_numbered_parameters_node: (NumberedParametersNode) -> Array[untyped] + + # : (NumberedReferenceReadNode) -> Array[untyped] + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> Array[untyped] + + # : (OptionalKeywordParameterNode) -> Array[untyped] + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> Array[untyped] + + # : (OptionalParameterNode) -> Array[untyped] + def visit_optional_parameter_node: (OptionalParameterNode) -> Array[untyped] + + # : (OrNode) -> Array[untyped] + def visit_or_node: (OrNode) -> Array[untyped] + + # : (ParametersNode) -> Array[untyped] + def visit_parameters_node: (ParametersNode) -> Array[untyped] + + # : (ParenthesesNode) -> Array[untyped] + def visit_parentheses_node: (ParenthesesNode) -> Array[untyped] + + # : (PinnedExpressionNode) -> Array[untyped] + def visit_pinned_expression_node: (PinnedExpressionNode) -> Array[untyped] + + # : (PinnedVariableNode) -> Array[untyped] + def visit_pinned_variable_node: (PinnedVariableNode) -> Array[untyped] + + # : (PostExecutionNode) -> Array[untyped] + def visit_post_execution_node: (PostExecutionNode) -> Array[untyped] + + # : (PreExecutionNode) -> Array[untyped] + def visit_pre_execution_node: (PreExecutionNode) -> Array[untyped] + + # : (ProgramNode) -> Array[untyped] + def visit_program_node: (ProgramNode) -> Array[untyped] + + # : (RangeNode) -> Array[untyped] + def visit_range_node: (RangeNode) -> Array[untyped] + + # : (RationalNode) -> Array[untyped] + def visit_rational_node: (RationalNode) -> Array[untyped] + + # : (RedoNode) -> Array[untyped] + def visit_redo_node: (RedoNode) -> Array[untyped] + + # : (RegularExpressionNode) -> Array[untyped] + def visit_regular_expression_node: (RegularExpressionNode) -> Array[untyped] + + # : (RequiredKeywordParameterNode) -> Array[untyped] + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> Array[untyped] + + # : (RequiredParameterNode) -> Array[untyped] + def visit_required_parameter_node: (RequiredParameterNode) -> Array[untyped] + + # : (RescueModifierNode) -> Array[untyped] + def visit_rescue_modifier_node: (RescueModifierNode) -> Array[untyped] + + # : (RescueNode) -> Array[untyped] + def visit_rescue_node: (RescueNode) -> Array[untyped] + + # : (RestParameterNode) -> Array[untyped] + def visit_rest_parameter_node: (RestParameterNode) -> Array[untyped] + + # : (RetryNode) -> Array[untyped] + def visit_retry_node: (RetryNode) -> Array[untyped] + + # : (ReturnNode) -> Array[untyped] + def visit_return_node: (ReturnNode) -> Array[untyped] + + # : (SelfNode) -> Array[untyped] + def visit_self_node: (SelfNode) -> Array[untyped] + + # : (ShareableConstantNode) -> Array[untyped] + def visit_shareable_constant_node: (ShareableConstantNode) -> Array[untyped] + + # : (SingletonClassNode) -> Array[untyped] + def visit_singleton_class_node: (SingletonClassNode) -> Array[untyped] + + # : (SourceEncodingNode) -> Array[untyped] + def visit_source_encoding_node: (SourceEncodingNode) -> Array[untyped] + + # : (SourceFileNode) -> Array[untyped] + def visit_source_file_node: (SourceFileNode) -> Array[untyped] + + # : (SourceLineNode) -> Array[untyped] + def visit_source_line_node: (SourceLineNode) -> Array[untyped] + + # : (SplatNode) -> Array[untyped] + def visit_splat_node: (SplatNode) -> Array[untyped] + + # : (StatementsNode) -> Array[untyped] + def visit_statements_node: (StatementsNode) -> Array[untyped] + + # : (StringNode) -> Array[untyped] + def visit_string_node: (StringNode) -> Array[untyped] + + # : (SuperNode) -> Array[untyped] + def visit_super_node: (SuperNode) -> Array[untyped] + + # : (SymbolNode) -> Array[untyped] + def visit_symbol_node: (SymbolNode) -> Array[untyped] + + # : (TrueNode) -> Array[untyped] + def visit_true_node: (TrueNode) -> Array[untyped] + + # : (UndefNode) -> Array[untyped] + def visit_undef_node: (UndefNode) -> Array[untyped] + + # : (UnlessNode) -> Array[untyped] + def visit_unless_node: (UnlessNode) -> Array[untyped] + + # : (UntilNode) -> Array[untyped] + def visit_until_node: (UntilNode) -> Array[untyped] + + # : (WhenNode) -> Array[untyped] + def visit_when_node: (WhenNode) -> Array[untyped] + + # : (WhileNode) -> Array[untyped] + def visit_while_node: (WhileNode) -> Array[untyped] + + # : (XStringNode) -> Array[untyped] + def visit_x_string_node: (XStringNode) -> Array[untyped] + + # : (YieldNode) -> Array[untyped] + def visit_yield_node: (YieldNode) -> Array[untyped] + end +end diff --git a/sig/generated/prism/desugar_compiler.rbs b/sig/generated/prism/desugar_compiler.rbs new file mode 100644 index 0000000000..d5bb07edf1 --- /dev/null +++ b/sig/generated/prism/desugar_compiler.rbs @@ -0,0 +1,305 @@ +# Generated from lib/prism/desugar_compiler.rb with RBS::Inline + +module Prism + class DesugarAndWriteNode + include DSL + + attr_reader node: ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (ClassVariableAndWriteNode | ConstantAndWriteNode | GlobalVariableAndWriteNode | InstanceVariableAndWriteNode | LocalVariableAndWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x &&= y` to `x && x = y` + # -- + # : () -> node + def compile: () -> node + end + + class DesugarOrWriteDefinedNode + include DSL + + attr_reader node: ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (ClassVariableOrWriteNode | ConstantOrWriteNode | GlobalVariableOrWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x ||= y` to `defined?(x) ? x : x = y` + # -- + # : () -> node + def compile: () -> node + end + + class DesugarOperatorWriteNode + include DSL + + attr_reader node: ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (ClassVariableOperatorWriteNode | ConstantOperatorWriteNode | GlobalVariableOperatorWriteNode | InstanceVariableOperatorWriteNode | LocalVariableOperatorWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x += y` to `x = x + y` + # -- + # : () -> node + def compile: () -> node + end + + class DesugarOrWriteNode + include DSL + + attr_reader node: InstanceVariableOrWriteNode | LocalVariableOrWriteNode + + attr_reader default_source: Source + + attr_reader read_class: Symbol + + attr_reader write_class: Symbol + + attr_reader arguments: Hash[Symbol, untyped] + + # : ((InstanceVariableOrWriteNode | LocalVariableOrWriteNode) node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + def initialize: (InstanceVariableOrWriteNode | LocalVariableOrWriteNode node, Source default_source, Symbol read_class, Symbol write_class, **untyped arguments) -> void + + # Desugar `x ||= y` to `x || x = y` + # -- + # : () -> node + def compile: () -> node + end + + class ClassVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class ClassVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class ClassVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class ConstantAndWriteNode + # : () -> node + def desugar: () -> node + end + + class ConstantOrWriteNode + # : () -> node + def desugar: () -> node + end + + class ConstantOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class GlobalVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class GlobalVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class GlobalVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class InstanceVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class InstanceVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class InstanceVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + class LocalVariableAndWriteNode + # : () -> node + def desugar: () -> node + end + + class LocalVariableOrWriteNode + # : () -> node + def desugar: () -> node + end + + class LocalVariableOperatorWriteNode + # : () -> node + def desugar: () -> node + end + + # DesugarCompiler is a compiler that desugars Ruby code into a more primitive + # form. This is useful for consumers that want to deal with fewer node types. + class DesugarCompiler < MutationCompiler + # `@@foo &&= bar` + # + # becomes + # + # `@@foo && @@foo = bar` + # -- + # : (ClassVariableAndWriteNode node) -> node + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> node + + # `@@foo ||= bar` + # + # becomes + # + # `defined?(@@foo) ? @@foo : @@foo = bar` + # -- + # : (ClassVariableOrWriteNode node) -> node + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> node + + # `@@foo += bar` + # + # becomes + # + # `@@foo = @@foo + bar` + # -- + # : (ClassVariableOperatorWriteNode node) -> node + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> node + + # `Foo &&= bar` + # + # becomes + # + # `Foo && Foo = bar` + # -- + # : (ConstantAndWriteNode node) -> node + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> node + + # `Foo ||= bar` + # + # becomes + # + # `defined?(Foo) ? Foo : Foo = bar` + # -- + # : (ConstantOrWriteNode node) -> node + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> node + + # `Foo += bar` + # + # becomes + # + # `Foo = Foo + bar` + # -- + # : (ConstantOperatorWriteNode node) -> node + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> node + + # `$foo &&= bar` + # + # becomes + # + # `$foo && $foo = bar` + # -- + # : (GlobalVariableAndWriteNode node) -> node + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> node + + # `$foo ||= bar` + # + # becomes + # + # `defined?($foo) ? $foo : $foo = bar` + # -- + # : (GlobalVariableOrWriteNode node) -> node + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> node + + # `$foo += bar` + # + # becomes + # + # `$foo = $foo + bar` + # -- + # : (GlobalVariableOperatorWriteNode node) -> node + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> node + + # `@foo &&= bar` + # + # becomes + # + # `@foo && @foo = bar` + # -- + # : (InstanceVariableAndWriteNode node) -> node + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> node + + # `@foo ||= bar` + # + # becomes + # + # `@foo || @foo = bar` + # -- + # : (InstanceVariableOrWriteNode node) -> node + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> node + + # `@foo += bar` + # + # becomes + # + # `@foo = @foo + bar` + # -- + # : (InstanceVariableOperatorWriteNode node) -> node + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> node + + # `foo &&= bar` + # + # becomes + # + # `foo && foo = bar` + # -- + # : (LocalVariableAndWriteNode node) -> node + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> node + + # `foo ||= bar` + # + # becomes + # + # `foo || foo = bar` + # -- + # : (LocalVariableOrWriteNode node) -> node + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> node + + # `foo += bar` + # + # becomes + # + # `foo = foo + bar` + # -- + # : (LocalVariableOperatorWriteNode node) -> node + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> node + end +end diff --git a/sig/generated/prism/dispatcher.rbs b/sig/generated/prism/dispatcher.rbs new file mode 100644 index 0000000000..0463d2b0ba --- /dev/null +++ b/sig/generated/prism/dispatcher.rbs @@ -0,0 +1,1292 @@ +# Generated from lib/prism/dispatcher.rb with RBS::Inline + +module Prism + # The dispatcher class fires events for nodes that are found while walking an + # AST to all registered listeners. It's useful for performing different types + # of analysis on the AST while only having to walk the tree once. + # + # To use the dispatcher, you would first instantiate it and register listeners + # for the events you're interested in: + # + # class OctalListener + # def on_integer_node_enter(node) + # if node.octal? && !node.slice.start_with?("0o") + # warn("Octal integers should be written with the 0o prefix") + # end + # end + # end + # + # listener = OctalListener.new + # dispatcher = Prism::Dispatcher.new + # dispatcher.register(listener, :on_integer_node_enter) + # + # Then, you can walk any number of trees and dispatch events to the listeners: + # + # result = Prism.parse("001 + 002 + 003") + # dispatcher.dispatch(result.value) + # + # Optionally, you can also use `#dispatch_once` to dispatch enter and leave + # events for a single node without recursing further down the tree. This can + # be useful in circumstances where you want to reuse the listeners you already + # have registers but want to stop walking the tree at a certain point. + # + # integer = result.value.statements.body.first.receiver.receiver + # dispatcher.dispatch_once(integer) + class Dispatcher < Visitor + # A hash mapping event names to arrays of listeners that should be notified + # when that event is fired. + attr_reader listeners: Hash[Symbol, Array[untyped]] + + # Initialize a new dispatcher. + # -- + # : () -> void + def initialize: () -> void + + # Register a listener for one or more events. + # -- + # : (untyped, *Symbol) -> void + def register: (untyped, *Symbol) -> void + + # Register all public methods of a listener that match the pattern + # `on__(enter|leave)`. + # -- + # : (untyped) -> void + def register_public_methods: (untyped) -> void + + # Register a listener for the given events. + # -- + # : (untyped, Array[Symbol]) -> void + private def register_events: (untyped, Array[Symbol]) -> void + + # Walks `root` dispatching events to all registered listeners. + alias dispatch visit + + # Dispatches a single event for `node` to all registered listeners. + # -- + # : (node node) -> void + def dispatch_once: (node node) -> void + + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + + class DispatchOnce < Visitor + attr_reader listeners: Hash[Symbol, Array[untyped]] + + # : (Hash[Symbol, Array[untyped]] listeners) -> void + def initialize: (Hash[Symbol, Array[untyped]] listeners) -> void + + # Dispatch enter and leave events for AliasGlobalVariableNode nodes. + # -- + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # Dispatch enter and leave events for AliasMethodNode nodes. + # -- + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # Dispatch enter and leave events for AlternationPatternNode nodes. + # -- + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # Dispatch enter and leave events for AndNode nodes. + # -- + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # Dispatch enter and leave events for ArgumentsNode nodes. + # -- + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # Dispatch enter and leave events for ArrayNode nodes. + # -- + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # Dispatch enter and leave events for ArrayPatternNode nodes. + # -- + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # Dispatch enter and leave events for AssocNode nodes. + # -- + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # Dispatch enter and leave events for AssocSplatNode nodes. + # -- + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # Dispatch enter and leave events for BackReferenceReadNode nodes. + # -- + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # Dispatch enter and leave events for BeginNode nodes. + # -- + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # Dispatch enter and leave events for BlockArgumentNode nodes. + # -- + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # Dispatch enter and leave events for BlockLocalVariableNode nodes. + # -- + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # Dispatch enter and leave events for BlockNode nodes. + # -- + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # Dispatch enter and leave events for BlockParameterNode nodes. + # -- + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # Dispatch enter and leave events for BlockParametersNode nodes. + # -- + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # Dispatch enter and leave events for BreakNode nodes. + # -- + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # Dispatch enter and leave events for CallAndWriteNode nodes. + # -- + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # Dispatch enter and leave events for CallNode nodes. + # -- + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # Dispatch enter and leave events for CallOperatorWriteNode nodes. + # -- + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # Dispatch enter and leave events for CallOrWriteNode nodes. + # -- + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # Dispatch enter and leave events for CallTargetNode nodes. + # -- + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # Dispatch enter and leave events for CapturePatternNode nodes. + # -- + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # Dispatch enter and leave events for CaseMatchNode nodes. + # -- + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # Dispatch enter and leave events for CaseNode nodes. + # -- + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # Dispatch enter and leave events for ClassNode nodes. + # -- + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # Dispatch enter and leave events for ClassVariableAndWriteNode nodes. + # -- + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for ClassVariableOperatorWriteNode nodes. + # -- + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for ClassVariableOrWriteNode nodes. + # -- + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for ClassVariableReadNode nodes. + # -- + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # Dispatch enter and leave events for ClassVariableTargetNode nodes. + # -- + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # Dispatch enter and leave events for ClassVariableWriteNode nodes. + # -- + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # Dispatch enter and leave events for ConstantAndWriteNode nodes. + # -- + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # Dispatch enter and leave events for ConstantOperatorWriteNode nodes. + # -- + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # Dispatch enter and leave events for ConstantOrWriteNode nodes. + # -- + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathAndWriteNode nodes. + # -- + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathNode nodes. + # -- + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # Dispatch enter and leave events for ConstantPathOperatorWriteNode nodes. + # -- + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathOrWriteNode nodes. + # -- + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # Dispatch enter and leave events for ConstantPathTargetNode nodes. + # -- + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # Dispatch enter and leave events for ConstantPathWriteNode nodes. + # -- + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # Dispatch enter and leave events for ConstantReadNode nodes. + # -- + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # Dispatch enter and leave events for ConstantTargetNode nodes. + # -- + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # Dispatch enter and leave events for ConstantWriteNode nodes. + # -- + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # Dispatch enter and leave events for DefNode nodes. + # -- + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # Dispatch enter and leave events for DefinedNode nodes. + # -- + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # Dispatch enter and leave events for ElseNode nodes. + # -- + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # Dispatch enter and leave events for EmbeddedStatementsNode nodes. + # -- + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # Dispatch enter and leave events for EmbeddedVariableNode nodes. + # -- + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # Dispatch enter and leave events for EnsureNode nodes. + # -- + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # Dispatch enter and leave events for FalseNode nodes. + # -- + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # Dispatch enter and leave events for FindPatternNode nodes. + # -- + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # Dispatch enter and leave events for FlipFlopNode nodes. + # -- + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # Dispatch enter and leave events for FloatNode nodes. + # -- + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # Dispatch enter and leave events for ForNode nodes. + # -- + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # Dispatch enter and leave events for ForwardingArgumentsNode nodes. + # -- + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # Dispatch enter and leave events for ForwardingParameterNode nodes. + # -- + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # Dispatch enter and leave events for ForwardingSuperNode nodes. + # -- + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # Dispatch enter and leave events for GlobalVariableAndWriteNode nodes. + # -- + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for GlobalVariableOperatorWriteNode nodes. + # -- + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for GlobalVariableOrWriteNode nodes. + # -- + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for GlobalVariableReadNode nodes. + # -- + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # Dispatch enter and leave events for GlobalVariableTargetNode nodes. + # -- + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # Dispatch enter and leave events for GlobalVariableWriteNode nodes. + # -- + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # Dispatch enter and leave events for HashNode nodes. + # -- + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # Dispatch enter and leave events for HashPatternNode nodes. + # -- + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # Dispatch enter and leave events for IfNode nodes. + # -- + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # Dispatch enter and leave events for ImaginaryNode nodes. + # -- + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # Dispatch enter and leave events for ImplicitNode nodes. + # -- + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # Dispatch enter and leave events for ImplicitRestNode nodes. + # -- + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # Dispatch enter and leave events for InNode nodes. + # -- + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # Dispatch enter and leave events for IndexAndWriteNode nodes. + # -- + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # Dispatch enter and leave events for IndexOperatorWriteNode nodes. + # -- + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # Dispatch enter and leave events for IndexOrWriteNode nodes. + # -- + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # Dispatch enter and leave events for IndexTargetNode nodes. + # -- + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # Dispatch enter and leave events for InstanceVariableAndWriteNode nodes. + # -- + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for InstanceVariableOperatorWriteNode nodes. + # -- + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for InstanceVariableOrWriteNode nodes. + # -- + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for InstanceVariableReadNode nodes. + # -- + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # Dispatch enter and leave events for InstanceVariableTargetNode nodes. + # -- + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # Dispatch enter and leave events for InstanceVariableWriteNode nodes. + # -- + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # Dispatch enter and leave events for IntegerNode nodes. + # -- + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # Dispatch enter and leave events for InterpolatedMatchLastLineNode nodes. + # -- + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # Dispatch enter and leave events for InterpolatedRegularExpressionNode nodes. + # -- + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # Dispatch enter and leave events for InterpolatedStringNode nodes. + # -- + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # Dispatch enter and leave events for InterpolatedSymbolNode nodes. + # -- + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # Dispatch enter and leave events for InterpolatedXStringNode nodes. + # -- + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # Dispatch enter and leave events for ItLocalVariableReadNode nodes. + # -- + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # Dispatch enter and leave events for ItParametersNode nodes. + # -- + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # Dispatch enter and leave events for KeywordHashNode nodes. + # -- + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # Dispatch enter and leave events for KeywordRestParameterNode nodes. + # -- + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # Dispatch enter and leave events for LambdaNode nodes. + # -- + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # Dispatch enter and leave events for LocalVariableAndWriteNode nodes. + # -- + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # Dispatch enter and leave events for LocalVariableOperatorWriteNode nodes. + # -- + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # Dispatch enter and leave events for LocalVariableOrWriteNode nodes. + # -- + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # Dispatch enter and leave events for LocalVariableReadNode nodes. + # -- + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # Dispatch enter and leave events for LocalVariableTargetNode nodes. + # -- + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # Dispatch enter and leave events for LocalVariableWriteNode nodes. + # -- + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # Dispatch enter and leave events for MatchLastLineNode nodes. + # -- + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # Dispatch enter and leave events for MatchPredicateNode nodes. + # -- + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # Dispatch enter and leave events for MatchRequiredNode nodes. + # -- + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # Dispatch enter and leave events for MatchWriteNode nodes. + # -- + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # Dispatch enter and leave events for MissingNode nodes. + # -- + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # Dispatch enter and leave events for ModuleNode nodes. + # -- + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # Dispatch enter and leave events for MultiTargetNode nodes. + # -- + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # Dispatch enter and leave events for MultiWriteNode nodes. + # -- + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # Dispatch enter and leave events for NextNode nodes. + # -- + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # Dispatch enter and leave events for NilNode nodes. + # -- + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # Dispatch enter and leave events for NoBlockParameterNode nodes. + # -- + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # Dispatch enter and leave events for NoKeywordsParameterNode nodes. + # -- + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # Dispatch enter and leave events for NumberedParametersNode nodes. + # -- + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # Dispatch enter and leave events for NumberedReferenceReadNode nodes. + # -- + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # Dispatch enter and leave events for OptionalKeywordParameterNode nodes. + # -- + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # Dispatch enter and leave events for OptionalParameterNode nodes. + # -- + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # Dispatch enter and leave events for OrNode nodes. + # -- + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # Dispatch enter and leave events for ParametersNode nodes. + # -- + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # Dispatch enter and leave events for ParenthesesNode nodes. + # -- + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # Dispatch enter and leave events for PinnedExpressionNode nodes. + # -- + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # Dispatch enter and leave events for PinnedVariableNode nodes. + # -- + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # Dispatch enter and leave events for PostExecutionNode nodes. + # -- + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # Dispatch enter and leave events for PreExecutionNode nodes. + # -- + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # Dispatch enter and leave events for ProgramNode nodes. + # -- + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # Dispatch enter and leave events for RangeNode nodes. + # -- + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # Dispatch enter and leave events for RationalNode nodes. + # -- + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # Dispatch enter and leave events for RedoNode nodes. + # -- + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # Dispatch enter and leave events for RegularExpressionNode nodes. + # -- + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # Dispatch enter and leave events for RequiredKeywordParameterNode nodes. + # -- + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # Dispatch enter and leave events for RequiredParameterNode nodes. + # -- + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # Dispatch enter and leave events for RescueModifierNode nodes. + # -- + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # Dispatch enter and leave events for RescueNode nodes. + # -- + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # Dispatch enter and leave events for RestParameterNode nodes. + # -- + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # Dispatch enter and leave events for RetryNode nodes. + # -- + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # Dispatch enter and leave events for ReturnNode nodes. + # -- + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # Dispatch enter and leave events for SelfNode nodes. + # -- + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # Dispatch enter and leave events for ShareableConstantNode nodes. + # -- + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # Dispatch enter and leave events for SingletonClassNode nodes. + # -- + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # Dispatch enter and leave events for SourceEncodingNode nodes. + # -- + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # Dispatch enter and leave events for SourceFileNode nodes. + # -- + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # Dispatch enter and leave events for SourceLineNode nodes. + # -- + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # Dispatch enter and leave events for SplatNode nodes. + # -- + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # Dispatch enter and leave events for StatementsNode nodes. + # -- + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # Dispatch enter and leave events for StringNode nodes. + # -- + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # Dispatch enter and leave events for SuperNode nodes. + # -- + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # Dispatch enter and leave events for SymbolNode nodes. + # -- + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # Dispatch enter and leave events for TrueNode nodes. + # -- + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # Dispatch enter and leave events for UndefNode nodes. + # -- + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # Dispatch enter and leave events for UnlessNode nodes. + # -- + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # Dispatch enter and leave events for UntilNode nodes. + # -- + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # Dispatch enter and leave events for WhenNode nodes. + # -- + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # Dispatch enter and leave events for WhileNode nodes. + # -- + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # Dispatch enter and leave events for XStringNode nodes. + # -- + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # Dispatch enter and leave events for YieldNode nodes. + # -- + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + end + end +end diff --git a/sig/generated/prism/dot_visitor.rbs b/sig/generated/prism/dot_visitor.rbs new file mode 100644 index 0000000000..b471ec741f --- /dev/null +++ b/sig/generated/prism/dot_visitor.rbs @@ -0,0 +1,635 @@ +# Generated from lib/prism/dot_visitor.rb with RBS::Inline + +module Prism + # This visitor provides the ability to call Node#to_dot, which converts a + # subtree into a graphviz dot graph. + class DotVisitor < Visitor + class Field + # :nodoc: + attr_reader name: String + + attr_reader value: String? + + attr_reader port: bool + + # : (String name, String? value, bool port) -> void + def initialize: (String name, String? value, bool port) -> void + + # : () -> String + def to_dot: () -> String + end + + class Table + # :nodoc: + attr_reader name: String + + attr_reader fields: Array[Field] + + # : (String name) -> void + def initialize: (String name) -> void + + # : (String name, ?String? value, ?port: bool) -> void + def field: (String name, ?String? value, ?port: bool) -> void + + # : () -> String + def to_dot: () -> String + end + + class Digraph + # :nodoc: + attr_reader nodes: Array[String] + + # :nodoc: + attr_reader waypoints: Array[String] + + # :nodoc: + attr_reader edges: Array[String] + + # : () -> void + def initialize: () -> void + + # : (String value) -> void + def node: (String value) -> void + + # : (String value) -> void + def waypoint: (String value) -> void + + # : (String value) -> void + def edge: (String value) -> void + + # : () -> String + def to_dot: () -> String + end + + # The digraph that is being built. + attr_reader digraph: Digraph + + # Initialize a new dot visitor. + # -- + # : () -> void + def initialize: () -> void + + # Convert this visitor into a graphviz dot graph string. + # -- + # : () -> String + def to_dot: () -> String + + # (AliasGlobalVariableNode) -> void + def visit_alias_global_variable_node: (untyped node) -> untyped + + # (AliasMethodNode) -> void + def visit_alias_method_node: (untyped node) -> untyped + + # (AlternationPatternNode) -> void + def visit_alternation_pattern_node: (untyped node) -> untyped + + # (AndNode) -> void + def visit_and_node: (untyped node) -> untyped + + # (ArgumentsNode) -> void + def visit_arguments_node: (untyped node) -> untyped + + # (ArrayNode) -> void + def visit_array_node: (untyped node) -> untyped + + # (ArrayPatternNode) -> void + def visit_array_pattern_node: (untyped node) -> untyped + + # (AssocNode) -> void + def visit_assoc_node: (untyped node) -> untyped + + # (AssocSplatNode) -> void + def visit_assoc_splat_node: (untyped node) -> untyped + + # (BackReferenceReadNode) -> void + def visit_back_reference_read_node: (untyped node) -> untyped + + # (BeginNode) -> void + def visit_begin_node: (untyped node) -> untyped + + # (BlockArgumentNode) -> void + def visit_block_argument_node: (untyped node) -> untyped + + # (BlockLocalVariableNode) -> void + def visit_block_local_variable_node: (untyped node) -> untyped + + # (BlockNode) -> void + def visit_block_node: (untyped node) -> untyped + + # (BlockParameterNode) -> void + def visit_block_parameter_node: (untyped node) -> untyped + + # (BlockParametersNode) -> void + def visit_block_parameters_node: (untyped node) -> untyped + + # (BreakNode) -> void + def visit_break_node: (untyped node) -> untyped + + # (CallAndWriteNode) -> void + def visit_call_and_write_node: (untyped node) -> untyped + + # (CallNode) -> void + def visit_call_node: (untyped node) -> untyped + + # (CallOperatorWriteNode) -> void + def visit_call_operator_write_node: (untyped node) -> untyped + + # (CallOrWriteNode) -> void + def visit_call_or_write_node: (untyped node) -> untyped + + # (CallTargetNode) -> void + def visit_call_target_node: (untyped node) -> untyped + + # (CapturePatternNode) -> void + def visit_capture_pattern_node: (untyped node) -> untyped + + # (CaseMatchNode) -> void + def visit_case_match_node: (untyped node) -> untyped + + # (CaseNode) -> void + def visit_case_node: (untyped node) -> untyped + + # (ClassNode) -> void + def visit_class_node: (untyped node) -> untyped + + # (ClassVariableAndWriteNode) -> void + def visit_class_variable_and_write_node: (untyped node) -> untyped + + # (ClassVariableOperatorWriteNode) -> void + def visit_class_variable_operator_write_node: (untyped node) -> untyped + + # (ClassVariableOrWriteNode) -> void + def visit_class_variable_or_write_node: (untyped node) -> untyped + + # (ClassVariableReadNode) -> void + def visit_class_variable_read_node: (untyped node) -> untyped + + # (ClassVariableTargetNode) -> void + def visit_class_variable_target_node: (untyped node) -> untyped + + # (ClassVariableWriteNode) -> void + def visit_class_variable_write_node: (untyped node) -> untyped + + # (ConstantAndWriteNode) -> void + def visit_constant_and_write_node: (untyped node) -> untyped + + # (ConstantOperatorWriteNode) -> void + def visit_constant_operator_write_node: (untyped node) -> untyped + + # (ConstantOrWriteNode) -> void + def visit_constant_or_write_node: (untyped node) -> untyped + + # (ConstantPathAndWriteNode) -> void + def visit_constant_path_and_write_node: (untyped node) -> untyped + + # (ConstantPathNode) -> void + def visit_constant_path_node: (untyped node) -> untyped + + # (ConstantPathOperatorWriteNode) -> void + def visit_constant_path_operator_write_node: (untyped node) -> untyped + + # (ConstantPathOrWriteNode) -> void + def visit_constant_path_or_write_node: (untyped node) -> untyped + + # (ConstantPathTargetNode) -> void + def visit_constant_path_target_node: (untyped node) -> untyped + + # (ConstantPathWriteNode) -> void + def visit_constant_path_write_node: (untyped node) -> untyped + + # (ConstantReadNode) -> void + def visit_constant_read_node: (untyped node) -> untyped + + # (ConstantTargetNode) -> void + def visit_constant_target_node: (untyped node) -> untyped + + # (ConstantWriteNode) -> void + def visit_constant_write_node: (untyped node) -> untyped + + # (DefNode) -> void + def visit_def_node: (untyped node) -> untyped + + # (DefinedNode) -> void + def visit_defined_node: (untyped node) -> untyped + + # (ElseNode) -> void + def visit_else_node: (untyped node) -> untyped + + # (EmbeddedStatementsNode) -> void + def visit_embedded_statements_node: (untyped node) -> untyped + + # (EmbeddedVariableNode) -> void + def visit_embedded_variable_node: (untyped node) -> untyped + + # (EnsureNode) -> void + def visit_ensure_node: (untyped node) -> untyped + + # (FalseNode) -> void + def visit_false_node: (untyped node) -> untyped + + # (FindPatternNode) -> void + def visit_find_pattern_node: (untyped node) -> untyped + + # (FlipFlopNode) -> void + def visit_flip_flop_node: (untyped node) -> untyped + + # (FloatNode) -> void + def visit_float_node: (untyped node) -> untyped + + # (ForNode) -> void + def visit_for_node: (untyped node) -> untyped + + # (ForwardingArgumentsNode) -> void + def visit_forwarding_arguments_node: (untyped node) -> untyped + + # (ForwardingParameterNode) -> void + def visit_forwarding_parameter_node: (untyped node) -> untyped + + # (ForwardingSuperNode) -> void + def visit_forwarding_super_node: (untyped node) -> untyped + + # (GlobalVariableAndWriteNode) -> void + def visit_global_variable_and_write_node: (untyped node) -> untyped + + # (GlobalVariableOperatorWriteNode) -> void + def visit_global_variable_operator_write_node: (untyped node) -> untyped + + # (GlobalVariableOrWriteNode) -> void + def visit_global_variable_or_write_node: (untyped node) -> untyped + + # (GlobalVariableReadNode) -> void + def visit_global_variable_read_node: (untyped node) -> untyped + + # (GlobalVariableTargetNode) -> void + def visit_global_variable_target_node: (untyped node) -> untyped + + # (GlobalVariableWriteNode) -> void + def visit_global_variable_write_node: (untyped node) -> untyped + + # (HashNode) -> void + def visit_hash_node: (untyped node) -> untyped + + # (HashPatternNode) -> void + def visit_hash_pattern_node: (untyped node) -> untyped + + # (IfNode) -> void + def visit_if_node: (untyped node) -> untyped + + # (ImaginaryNode) -> void + def visit_imaginary_node: (untyped node) -> untyped + + # (ImplicitNode) -> void + def visit_implicit_node: (untyped node) -> untyped + + # (ImplicitRestNode) -> void + def visit_implicit_rest_node: (untyped node) -> untyped + + # (InNode) -> void + def visit_in_node: (untyped node) -> untyped + + # (IndexAndWriteNode) -> void + def visit_index_and_write_node: (untyped node) -> untyped + + # (IndexOperatorWriteNode) -> void + def visit_index_operator_write_node: (untyped node) -> untyped + + # (IndexOrWriteNode) -> void + def visit_index_or_write_node: (untyped node) -> untyped + + # (IndexTargetNode) -> void + def visit_index_target_node: (untyped node) -> untyped + + # (InstanceVariableAndWriteNode) -> void + def visit_instance_variable_and_write_node: (untyped node) -> untyped + + # (InstanceVariableOperatorWriteNode) -> void + def visit_instance_variable_operator_write_node: (untyped node) -> untyped + + # (InstanceVariableOrWriteNode) -> void + def visit_instance_variable_or_write_node: (untyped node) -> untyped + + # (InstanceVariableReadNode) -> void + def visit_instance_variable_read_node: (untyped node) -> untyped + + # (InstanceVariableTargetNode) -> void + def visit_instance_variable_target_node: (untyped node) -> untyped + + # (InstanceVariableWriteNode) -> void + def visit_instance_variable_write_node: (untyped node) -> untyped + + # (IntegerNode) -> void + def visit_integer_node: (untyped node) -> untyped + + # (InterpolatedMatchLastLineNode) -> void + def visit_interpolated_match_last_line_node: (untyped node) -> untyped + + # (InterpolatedRegularExpressionNode) -> void + def visit_interpolated_regular_expression_node: (untyped node) -> untyped + + # (InterpolatedStringNode) -> void + def visit_interpolated_string_node: (untyped node) -> untyped + + # (InterpolatedSymbolNode) -> void + def visit_interpolated_symbol_node: (untyped node) -> untyped + + # (InterpolatedXStringNode) -> void + def visit_interpolated_x_string_node: (untyped node) -> untyped + + # (ItLocalVariableReadNode) -> void + def visit_it_local_variable_read_node: (untyped node) -> untyped + + # (ItParametersNode) -> void + def visit_it_parameters_node: (untyped node) -> untyped + + # (KeywordHashNode) -> void + def visit_keyword_hash_node: (untyped node) -> untyped + + # (KeywordRestParameterNode) -> void + def visit_keyword_rest_parameter_node: (untyped node) -> untyped + + # (LambdaNode) -> void + def visit_lambda_node: (untyped node) -> untyped + + # (LocalVariableAndWriteNode) -> void + def visit_local_variable_and_write_node: (untyped node) -> untyped + + # (LocalVariableOperatorWriteNode) -> void + def visit_local_variable_operator_write_node: (untyped node) -> untyped + + # (LocalVariableOrWriteNode) -> void + def visit_local_variable_or_write_node: (untyped node) -> untyped + + # (LocalVariableReadNode) -> void + def visit_local_variable_read_node: (untyped node) -> untyped + + # (LocalVariableTargetNode) -> void + def visit_local_variable_target_node: (untyped node) -> untyped + + # (LocalVariableWriteNode) -> void + def visit_local_variable_write_node: (untyped node) -> untyped + + # (MatchLastLineNode) -> void + def visit_match_last_line_node: (untyped node) -> untyped + + # (MatchPredicateNode) -> void + def visit_match_predicate_node: (untyped node) -> untyped + + # (MatchRequiredNode) -> void + def visit_match_required_node: (untyped node) -> untyped + + # (MatchWriteNode) -> void + def visit_match_write_node: (untyped node) -> untyped + + # (MissingNode) -> void + def visit_missing_node: (untyped node) -> untyped + + # (ModuleNode) -> void + def visit_module_node: (untyped node) -> untyped + + # (MultiTargetNode) -> void + def visit_multi_target_node: (untyped node) -> untyped + + # (MultiWriteNode) -> void + def visit_multi_write_node: (untyped node) -> untyped + + # (NextNode) -> void + def visit_next_node: (untyped node) -> untyped + + # (NilNode) -> void + def visit_nil_node: (untyped node) -> untyped + + # (NoBlockParameterNode) -> void + def visit_no_block_parameter_node: (untyped node) -> untyped + + # (NoKeywordsParameterNode) -> void + def visit_no_keywords_parameter_node: (untyped node) -> untyped + + # (NumberedParametersNode) -> void + def visit_numbered_parameters_node: (untyped node) -> untyped + + # (NumberedReferenceReadNode) -> void + def visit_numbered_reference_read_node: (untyped node) -> untyped + + # (OptionalKeywordParameterNode) -> void + def visit_optional_keyword_parameter_node: (untyped node) -> untyped + + # (OptionalParameterNode) -> void + def visit_optional_parameter_node: (untyped node) -> untyped + + # (OrNode) -> void + def visit_or_node: (untyped node) -> untyped + + # (ParametersNode) -> void + def visit_parameters_node: (untyped node) -> untyped + + # (ParenthesesNode) -> void + def visit_parentheses_node: (untyped node) -> untyped + + # (PinnedExpressionNode) -> void + def visit_pinned_expression_node: (untyped node) -> untyped + + # (PinnedVariableNode) -> void + def visit_pinned_variable_node: (untyped node) -> untyped + + # (PostExecutionNode) -> void + def visit_post_execution_node: (untyped node) -> untyped + + # (PreExecutionNode) -> void + def visit_pre_execution_node: (untyped node) -> untyped + + # (ProgramNode) -> void + def visit_program_node: (untyped node) -> untyped + + # (RangeNode) -> void + def visit_range_node: (untyped node) -> untyped + + # (RationalNode) -> void + def visit_rational_node: (untyped node) -> untyped + + # (RedoNode) -> void + def visit_redo_node: (untyped node) -> untyped + + # (RegularExpressionNode) -> void + def visit_regular_expression_node: (untyped node) -> untyped + + # (RequiredKeywordParameterNode) -> void + def visit_required_keyword_parameter_node: (untyped node) -> untyped + + # (RequiredParameterNode) -> void + def visit_required_parameter_node: (untyped node) -> untyped + + # (RescueModifierNode) -> void + def visit_rescue_modifier_node: (untyped node) -> untyped + + # (RescueNode) -> void + def visit_rescue_node: (untyped node) -> untyped + + # (RestParameterNode) -> void + def visit_rest_parameter_node: (untyped node) -> untyped + + # (RetryNode) -> void + def visit_retry_node: (untyped node) -> untyped + + # (ReturnNode) -> void + def visit_return_node: (untyped node) -> untyped + + # (SelfNode) -> void + def visit_self_node: (untyped node) -> untyped + + # (ShareableConstantNode) -> void + def visit_shareable_constant_node: (untyped node) -> untyped + + # (SingletonClassNode) -> void + def visit_singleton_class_node: (untyped node) -> untyped + + # (SourceEncodingNode) -> void + def visit_source_encoding_node: (untyped node) -> untyped + + # (SourceFileNode) -> void + def visit_source_file_node: (untyped node) -> untyped + + # (SourceLineNode) -> void + def visit_source_line_node: (untyped node) -> untyped + + # (SplatNode) -> void + def visit_splat_node: (untyped node) -> untyped + + # (StatementsNode) -> void + def visit_statements_node: (untyped node) -> untyped + + # (StringNode) -> void + def visit_string_node: (untyped node) -> untyped + + # (SuperNode) -> void + def visit_super_node: (untyped node) -> untyped + + # (SymbolNode) -> void + def visit_symbol_node: (untyped node) -> untyped + + # (TrueNode) -> void + def visit_true_node: (untyped node) -> untyped + + # (UndefNode) -> void + def visit_undef_node: (untyped node) -> untyped + + # (UnlessNode) -> void + def visit_unless_node: (untyped node) -> untyped + + # (UntilNode) -> void + def visit_until_node: (untyped node) -> untyped + + # (WhenNode) -> void + def visit_when_node: (untyped node) -> untyped + + # (WhileNode) -> void + def visit_while_node: (untyped node) -> untyped + + # (XStringNode) -> void + def visit_x_string_node: (untyped node) -> untyped + + # (YieldNode) -> void + def visit_yield_node: (untyped node) -> untyped + + private + + # Generate a unique node ID for a node throughout the digraph. + # -- + # : (node) -> String + def node_id: (node) -> String + + # Inspect a location to display the start and end line and columns in bytes. + # -- + # : (Location) -> String + def location_inspect: (Location) -> String + + # Inspect a node that has arguments_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ArgumentsNode node) -> String + def arguments_node_flags_inspect: (ArgumentsNode node) -> String + + # Inspect a node that has array_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ArrayNode node) -> String + def array_node_flags_inspect: (ArrayNode node) -> String + + # Inspect a node that has call_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (CallAndWriteNode | CallNode | CallOperatorWriteNode | CallOrWriteNode | CallTargetNode | IndexAndWriteNode | IndexOperatorWriteNode | IndexOrWriteNode | IndexTargetNode node) -> String + def call_node_flags_inspect: (CallAndWriteNode | CallNode | CallOperatorWriteNode | CallOrWriteNode | CallTargetNode | IndexAndWriteNode | IndexOperatorWriteNode | IndexOrWriteNode | IndexTargetNode node) -> String + + # Inspect a node that has encoding_flags flags to display the flags as a + # comma-separated list. + # -- + # : (XStringNode node) -> String + def encoding_flags_inspect: (XStringNode node) -> String + + # Inspect a node that has integer_base_flags flags to display the flags as a + # comma-separated list. + # -- + # : (IntegerNode | RationalNode node) -> String + def integer_base_flags_inspect: (IntegerNode | RationalNode node) -> String + + # Inspect a node that has interpolated_string_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (InterpolatedStringNode node) -> String + def interpolated_string_node_flags_inspect: (InterpolatedStringNode node) -> String + + # Inspect a node that has keyword_hash_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (KeywordHashNode node) -> String + def keyword_hash_node_flags_inspect: (KeywordHashNode node) -> String + + # Inspect a node that has loop_flags flags to display the flags as a + # comma-separated list. + # -- + # : (UntilNode | WhileNode node) -> String + def loop_flags_inspect: (UntilNode | WhileNode node) -> String + + # Inspect a node that has parameter_flags flags to display the flags as a + # comma-separated list. + # -- + # : (BlockLocalVariableNode | BlockParameterNode | KeywordRestParameterNode | OptionalKeywordParameterNode | OptionalParameterNode | RequiredKeywordParameterNode | RequiredParameterNode | RestParameterNode node) -> String + def parameter_flags_inspect: (BlockLocalVariableNode | BlockParameterNode | KeywordRestParameterNode | OptionalKeywordParameterNode | OptionalParameterNode | RequiredKeywordParameterNode | RequiredParameterNode | RestParameterNode node) -> String + + # Inspect a node that has parentheses_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ParenthesesNode node) -> String + def parentheses_node_flags_inspect: (ParenthesesNode node) -> String + + # Inspect a node that has range_flags flags to display the flags as a + # comma-separated list. + # -- + # : (FlipFlopNode | RangeNode node) -> String + def range_flags_inspect: (FlipFlopNode | RangeNode node) -> String + + # Inspect a node that has regular_expression_flags flags to display the flags as a + # comma-separated list. + # -- + # : (InterpolatedMatchLastLineNode | InterpolatedRegularExpressionNode | MatchLastLineNode | RegularExpressionNode node) -> String + def regular_expression_flags_inspect: (InterpolatedMatchLastLineNode | InterpolatedRegularExpressionNode | MatchLastLineNode | RegularExpressionNode node) -> String + + # Inspect a node that has shareable_constant_node_flags flags to display the flags as a + # comma-separated list. + # -- + # : (ShareableConstantNode node) -> String + def shareable_constant_node_flags_inspect: (ShareableConstantNode node) -> String + + # Inspect a node that has string_flags flags to display the flags as a + # comma-separated list. + # -- + # : (SourceFileNode | StringNode node) -> String + def string_flags_inspect: (SourceFileNode | StringNode node) -> String + + # Inspect a node that has symbol_flags flags to display the flags as a + # comma-separated list. + # -- + # : (SymbolNode node) -> String + def symbol_flags_inspect: (SymbolNode node) -> String + end +end diff --git a/sig/generated/prism/dsl.rbs b/sig/generated/prism/dsl.rbs new file mode 100644 index 0000000000..6b5e4bbc75 --- /dev/null +++ b/sig/generated/prism/dsl.rbs @@ -0,0 +1,921 @@ +# Generated from lib/prism/dsl.rb with RBS::Inline + +module Prism + # The DSL module provides a set of methods that can be used to create prism + # nodes in a more concise manner. For example, instead of writing: + # + # source = Prism::Source.for("[1]") + # + # Prism::ArrayNode.new( + # source, + # 0, + # Prism::Location.new(source, 0, 3), + # 0, + # [ + # Prism::IntegerNode.new( + # source, + # 0, + # Prism::Location.new(source, 1, 1), + # Prism::IntegerBaseFlags::DECIMAL, + # 1 + # ) + # ], + # Prism::Location.new(source, 0, 1), + # Prism::Location.new(source, 2, 1) + # ) + # + # you could instead write: + # + # class Builder + # include Prism::DSL + # + # attr_reader :default_source + # + # def initialize + # @default_source = source("[1]") + # end + # + # def build + # array_node( + # location: location(start_offset: 0, length: 3), + # elements: [ + # integer_node( + # location: location(start_offset: 1, length: 1), + # flags: integer_base_flag(:decimal), + # value: 1 + # ) + # ], + # opening_loc: location(start_offset: 0, length: 1), + # closing_loc: location(start_offset: 2, length: 1) + # ) + # end + # end + # + # This is mostly helpful in the context of generating trees programmatically. + module DSL + # Create a new Source object. + # -- + # : (String string) -> Source + def source: (String string) -> Source + + # Create a new Location object. + # -- + # : (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + def location: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + + # Create a new AliasGlobalVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode), ?old_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode), ?keyword_loc: Location) -> AliasGlobalVariableNode + def alias_global_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode, ?old_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode, ?keyword_loc: Location) -> AliasGlobalVariableNode + + # Create a new AliasMethodNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (SymbolNode | InterpolatedSymbolNode), ?old_name: (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode), ?keyword_loc: Location) -> AliasMethodNode + def alias_method_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: SymbolNode | InterpolatedSymbolNode, ?old_name: SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode, ?keyword_loc: Location) -> AliasMethodNode + + # Create a new AlternationPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + def alternation_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + + # Create a new AndNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + def and_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + + # Create a new ArgumentsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + def arguments_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + + # Create a new ArrayNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + def array_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + + # Create a new ArrayPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + def array_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + + # Create a new AssocNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + def assoc_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + + # Create a new AssocSplatNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + def assoc_splat_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + + # Create a new BackReferenceReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + def back_reference_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + + # Create a new BeginNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + def begin_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + + # Create a new BlockArgumentNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + def block_argument_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + + # Create a new BlockLocalVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + def block_local_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + + # Create a new BlockNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + def block_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + + # Create a new BlockParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + def block_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + + # Create a new BlockParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + def block_parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + + # Create a new BreakNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + def break_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + + # Create a new CallAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + def call_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + + # Create a new CallNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + def call_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + + # Create a new CallOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + def call_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + + # Create a new CallOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + def call_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + + # Create a new CallTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + def call_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + + # Create a new CapturePatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + def capture_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + + # Create a new CaseMatchNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + def case_match_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + + # Create a new CaseNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + def case_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + + # Create a new ClassNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | CallNode), ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + def class_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | CallNode, ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + + # Create a new ClassVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + def class_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + + # Create a new ClassVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + def class_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + + # Create a new ClassVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + def class_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + + # Create a new ClassVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + def class_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + + # Create a new ClassVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + def class_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + + # Create a new ClassVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + def class_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + + # Create a new ConstantAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + def constant_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + + # Create a new ConstantOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + def constant_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + + # Create a new ConstantOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + def constant_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + + # Create a new ConstantPathAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + def constant_path_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + + # Create a new ConstantPathNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + def constant_path_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + + # Create a new ConstantPathOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + def constant_path_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + + # Create a new ConstantPathOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + def constant_path_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + + # Create a new ConstantPathTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + def constant_path_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + + # Create a new ConstantPathWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + def constant_path_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + + # Create a new ConstantReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + def constant_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + + # Create a new ConstantTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + def constant_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + + # Create a new ConstantWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + def constant_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + + # Create a new DefNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + def def_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + + # Create a new DefinedNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + def defined_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + + # Create a new ElseNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + def else_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + + # Create a new EmbeddedStatementsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + def embedded_statements_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + + # Create a new EmbeddedVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode)) -> EmbeddedVariableNode + def embedded_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) -> EmbeddedVariableNode + + # Create a new EnsureNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + def ensure_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + + # Create a new FalseNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> FalseNode + def false_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> FalseNode + + # Create a new FindPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: (SplatNode | MissingNode), ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + def find_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: SplatNode | MissingNode, ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + + # Create a new FlipFlopNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + def flip_flop_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + + # Create a new FloatNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + def float_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + + # Create a new ForNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?index: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode), ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + def for_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?index: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode, ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + + # Create a new ForwardingArgumentsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingArgumentsNode + def forwarding_arguments_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingArgumentsNode + + # Create a new ForwardingParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingParameterNode + def forwarding_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingParameterNode + + # Create a new ForwardingSuperNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + def forwarding_super_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + + # Create a new GlobalVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + def global_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + + # Create a new GlobalVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + def global_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + + # Create a new GlobalVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + def global_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + + # Create a new GlobalVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + def global_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + + # Create a new GlobalVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + def global_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + + # Create a new GlobalVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + def global_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + + # Create a new HashNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + def hash_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + + # Create a new HashPatternNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + def hash_pattern_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + + # Create a new IfNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + def if_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + + # Create a new ImaginaryNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: (FloatNode | IntegerNode | RationalNode)) -> ImaginaryNode + def imaginary_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: FloatNode | IntegerNode | RationalNode) -> ImaginaryNode + + # Create a new ImplicitNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode)) -> ImplicitNode + def implicit_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) -> ImplicitNode + + # Create a new ImplicitRestNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ImplicitRestNode + def implicit_rest_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ImplicitRestNode + + # Create a new InNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + def in_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + + # Create a new IndexAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + def index_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + + # Create a new IndexOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + def index_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + + # Create a new IndexOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + def index_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + + # Create a new IndexTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + def index_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + + # Create a new InstanceVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + def instance_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + + # Create a new InstanceVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + def instance_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + + # Create a new InstanceVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + def instance_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + + # Create a new InstanceVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + def instance_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + + # Create a new InstanceVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + def instance_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + + # Create a new InstanceVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + def instance_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + + # Create a new IntegerNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + def integer_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + + # Create a new InterpolatedMatchLastLineNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + def interpolated_match_last_line_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + + # Create a new InterpolatedRegularExpressionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + def interpolated_regular_expression_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + + # Create a new InterpolatedStringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + def interpolated_string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + + # Create a new InterpolatedSymbolNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + def interpolated_symbol_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + + # Create a new InterpolatedXStringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + def interpolated_x_string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + + # Create a new ItLocalVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItLocalVariableReadNode + def it_local_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItLocalVariableReadNode + + # Create a new ItParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItParametersNode + def it_parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> ItParametersNode + + # Create a new KeywordHashNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + def keyword_hash_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + + # Create a new KeywordRestParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + def keyword_rest_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + + # Create a new LambdaNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + def lambda_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + + # Create a new LocalVariableAndWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + def local_variable_and_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + + # Create a new LocalVariableOperatorWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + def local_variable_operator_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + + # Create a new LocalVariableOrWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + def local_variable_or_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + + # Create a new LocalVariableReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + def local_variable_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + + # Create a new LocalVariableTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + def local_variable_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + + # Create a new LocalVariableWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + def local_variable_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + + # Create a new MatchLastLineNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + def match_last_line_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + + # Create a new MatchPredicateNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + def match_predicate_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + + # Create a new MatchRequiredNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + def match_required_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + + # Create a new MatchWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + def match_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + + # Create a new MissingNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> MissingNode + def missing_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> MissingNode + + # Create a new ModuleNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | MissingNode), ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + def module_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | MissingNode, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + + # Create a new MultiTargetNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + def multi_target_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + + # Create a new MultiWriteNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + def multi_write_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + + # Create a new NextNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + def next_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + + # Create a new NilNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> NilNode + def nil_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> NilNode + + # Create a new NoBlockParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + def no_block_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + + # Create a new NoKeywordsParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + def no_keywords_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + + # Create a new NumberedParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + def numbered_parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + + # Create a new NumberedReferenceReadNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + def numbered_reference_read_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + + # Create a new OptionalKeywordParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + def optional_keyword_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + + # Create a new OptionalParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + def optional_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + + # Create a new OrNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + def or_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + + # Create a new ParametersNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + def parameters_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + + # Create a new ParenthesesNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + def parentheses_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + + # Create a new PinnedExpressionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + def pinned_expression_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + + # Create a new PinnedVariableNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode), ?operator_loc: Location) -> PinnedVariableNode + def pinned_variable_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode, ?operator_loc: Location) -> PinnedVariableNode + + # Create a new PostExecutionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + def post_execution_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + + # Create a new PreExecutionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + def pre_execution_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + + # Create a new ProgramNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + def program_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + + # Create a new RangeNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + def range_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + + # Create a new RationalNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + def rational_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + + # Create a new RedoNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RedoNode + def redo_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RedoNode + + # Create a new RegularExpressionNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + def regular_expression_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + + # Create a new RequiredKeywordParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + def required_keyword_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + + # Create a new RequiredParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + def required_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + + # Create a new RescueModifierNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + def rescue_modifier_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + + # Create a new RescueNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + def rescue_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + + # Create a new RestParameterNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + def rest_parameter_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + + # Create a new RetryNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RetryNode + def retry_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> RetryNode + + # Create a new ReturnNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + def return_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + + # Create a new SelfNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SelfNode + def self_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SelfNode + + # Create a new ShareableConstantNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?write: (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode)) -> ShareableConstantNode + def shareable_constant_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?write: ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) -> ShareableConstantNode + + # Create a new SingletonClassNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + def singleton_class_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + + # Create a new SourceEncodingNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceEncodingNode + def source_encoding_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceEncodingNode + + # Create a new SourceFileNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + def source_file_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + + # Create a new SourceLineNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceLineNode + def source_line_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceLineNode + + # Create a new SplatNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + def splat_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + + # Create a new StatementsNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + def statements_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + + # Create a new StringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + def string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + + # Create a new SuperNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + def super_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + + # Create a new SymbolNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + def symbol_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + + # Create a new TrueNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> TrueNode + def true_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer) -> TrueNode + + # Create a new UndefNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + def undef_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + + # Create a new UnlessNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + def unless_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + + # Create a new UntilNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + def until_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + + # Create a new WhenNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + def when_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + + # Create a new WhileNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + def while_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + + # Create a new XStringNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + def x_string_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + + # Create a new YieldNode node. + # -- + # : (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + def yield_node: (?source: Source, ?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + + # Retrieve the value of one of the ArgumentsNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def arguments_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ArrayNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def array_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the CallNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def call_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the EncodingFlags flags. + # -- + # : (Symbol name) -> Integer + def encoding_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the IntegerBaseFlags flags. + # -- + # : (Symbol name) -> Integer + def integer_base_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the InterpolatedStringNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def interpolated_string_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the KeywordHashNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def keyword_hash_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the LoopFlags flags. + # -- + # : (Symbol name) -> Integer + def loop_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ParameterFlags flags. + # -- + # : (Symbol name) -> Integer + def parameter_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ParenthesesNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def parentheses_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the RangeFlags flags. + # -- + # : (Symbol name) -> Integer + def range_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the RegularExpressionFlags flags. + # -- + # : (Symbol name) -> Integer + def regular_expression_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the ShareableConstantNodeFlags flags. + # -- + # : (Symbol name) -> Integer + def shareable_constant_node_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the StringFlags flags. + # -- + # : (Symbol name) -> Integer + def string_flag: (Symbol name) -> Integer + + # Retrieve the value of one of the SymbolFlags flags. + # -- + # : (Symbol name) -> Integer + def symbol_flag: (Symbol name) -> Integer + + private + + # The default source object that gets attached to nodes and locations if no + # source is specified. + # -- + # : () -> Source + def default_source: () -> Source + + # The default location object that gets attached to nodes if no location is + # specified, which uses the given source. + # -- + # : () -> Location + def default_location: () -> Location + + # The default node that gets attached to nodes if no node is specified for a + # required node field. + # -- + # : (Source source, Location location) -> node + def default_node: (Source source, Location location) -> node + end +end diff --git a/sig/generated/prism/inspect_visitor.rbs b/sig/generated/prism/inspect_visitor.rbs new file mode 100644 index 0000000000..1219427ceb --- /dev/null +++ b/sig/generated/prism/inspect_visitor.rbs @@ -0,0 +1,509 @@ +# Generated from lib/prism/inspect_visitor.rb with RBS::Inline + +module Prism + # This visitor is responsible for composing the strings that get returned by + # the various #inspect methods defined on each of the nodes. + class InspectVisitor < Visitor + # Most of the time, we can simply pass down the indent to the next node. + # However, when we are inside a list we want some extra special formatting + # when we hit an element in that list. In this case, we have a special + # command that replaces the subsequent indent with the given value. + class Replace + # :nodoc: + attr_reader value: String + + # : (String value) -> void + def initialize: (String value) -> void + end + + # The current prefix string. + # :stopdoc: + attr_reader indent: String + + # The list of commands that we need to execute in order to compose the + # final string. + # : stopdoc: + attr_reader commands: Array[[ String | node | Replace, String ]] + + # : (?String indent) -> void + def initialize: (?String indent) -> void + + # Compose an inspect string for the given node. + # -- + # : (node node) -> String + def self.compose: (node node) -> String + + # Compose the final string. + # -- + # : () -> String + def compose: () -> String + + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + + private + + # Compose a header for the given node. + # -- + # : (String name, node node) -> String + def inspect_node: (String name, node node) -> String + + # Compose a string representing the given inner location field. + # -- + # : (Location? location) -> String + def inspect_location: (Location? location) -> String + end +end diff --git a/sig/generated/prism/lex_compat.rbs b/sig/generated/prism/lex_compat.rbs new file mode 100644 index 0000000000..4c9e6d9c16 --- /dev/null +++ b/sig/generated/prism/lex_compat.rbs @@ -0,0 +1,151 @@ +# Generated from lib/prism/lex_compat.rb with RBS::Inline + +module Prism + module Translation + class Ripper + EXPR_BEG: Integer + + class Lexer < Ripper + class State + def self.[]: (Integer value) -> State + end + end + end + end + + # This class is responsible for lexing the source using prism and then + # converting those tokens to be compatible with Ripper. In the vast majority + # of cases, this is a one-to-one mapping of the token type. Everything else + # generally lines up. However, there are a few cases that require special + # handling. + class LexCompat + # A token produced by the Ripper lexer that Prism is replicating. + type lex_compat_token = [ [ Integer, Integer ], Symbol, String, untyped ] + + # A result class specialized for holding tokens produced by the lexer. + class Result < Prism::Result + # The list of tokens that were produced by the lexer. + attr_reader value: Array[lex_compat_token] + + # Create a new lex compat result object with the given values. + # -- + # : (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + def initialize: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + + # Implement the hash pattern matching interface for Result. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + end + + # This is a mapping of prism token types to Ripper token types. This is a + # many-to-one mapping because we split up our token types, whereas Ripper + # tends to group them. + RIPPER: untyped + + # A heredoc in this case is a list of tokens that belong to the body of the + # heredoc that should be appended onto the list of tokens when the heredoc + # closes. + module Heredoc + # Heredocs that are no dash or tilde heredocs are just a list of tokens. + # We need to keep them around so that we can insert them in the correct + # order back into the token stream and set the state of the last token to + # the state that the heredoc was opened in. + class PlainHeredoc + # :nodoc: + attr_reader tokens: Array[lex_compat_token] + + # : () -> void + def initialize: () -> void + + # : (lex_compat_token token) -> void + def <<: (lex_compat_token token) -> void + + # : () -> Array[lex_compat_token] + def to_a: () -> Array[lex_compat_token] + end + + # Dash heredocs are a little more complicated. They are a list of tokens + # that need to be split on "\\\n" to mimic Ripper's behavior. We also need + # to keep track of the state that the heredoc was opened in. + class DashHeredoc + # :nodoc: + attr_reader split: bool + + attr_reader tokens: Array[lex_compat_token] + + # : (bool split) -> void + def initialize: (bool split) -> void + + # : (lex_compat_token token) -> void + def <<: (lex_compat_token token) -> void + + # : () -> Array[lex_compat_token] + def to_a: () -> Array[lex_compat_token] + end + + # Heredocs that are dedenting heredocs are a little more complicated. + # Ripper outputs on_ignored_sp tokens for the whitespace that is being + # removed from the output. prism only modifies the node itself and keeps + # the token the same. This simplifies prism, but makes comparing against + # Ripper much harder because there is a length mismatch. + # + # Fortunately, we already have to pull out the heredoc tokens in order to + # insert them into the stream in the correct order. As such, we can do + # some extra manipulation on the tokens to make them match Ripper's + # output by mirroring the dedent logic that Ripper uses. + class DedentingHeredoc + # :nodoc: + TAB_WIDTH: ::Integer + + attr_reader tokens: Array[lex_compat_token] + + attr_reader dedent_next: bool + + attr_reader dedent: Integer? + + attr_reader embexpr_balance: Integer + + @ended_on_newline: bool + + # : () -> void + def initialize: () -> void + + # As tokens are coming in, we track the minimum amount of common leading + # whitespace on plain string content tokens. This allows us to later + # remove that amount of whitespace from the beginning of each line. + # + # : (lex_compat_token token) -> void + def <<: (lex_compat_token token) -> void + + # : () -> Array[lex_compat_token] + def to_a: () -> Array[lex_compat_token] + end + + # Here we will split between the two types of heredocs and return the + # object that will store their tokens. + # -- + # : (lex_compat_token opening) -> (PlainHeredoc | DashHeredoc | DedentingHeredoc) + def self.build: (lex_compat_token opening) -> (PlainHeredoc | DashHeredoc | DedentingHeredoc) + end + + # In previous versions of Ruby, Ripper wouldn't flush the bom before the + # first token, so we had to have a hack in place to account for that. + BOM_FLUSHED: untyped + + attr_reader options: Hash[Symbol, untyped] + + @source: String + + # : (String source, **untyped options) -> void + def initialize: (String source, **untyped options) -> void + + # : () -> Result + def result: () -> Result + + private + + # : (Array[lex_compat_token] tokens, Source source, Location? data_loc, bool bom, Token? eof_token) -> Array[lex_compat_token] + def post_process_tokens: (Array[lex_compat_token] tokens, Source source, Location? data_loc, bool bom, Token? eof_token) -> Array[lex_compat_token] + end +end diff --git a/sig/generated/prism/mutation_compiler.rbs b/sig/generated/prism/mutation_compiler.rbs new file mode 100644 index 0000000000..e79f254372 --- /dev/null +++ b/sig/generated/prism/mutation_compiler.rbs @@ -0,0 +1,464 @@ +# Generated from lib/prism/mutation_compiler.rb with RBS::Inline + +module Prism + # This visitor walks through the tree and copies each node as it is being + # visited. This is useful for consumers that want to mutate the tree, as you + # can change subtrees in place without effecting the rest of the tree. + class MutationCompiler < Compiler + # : (AliasGlobalVariableNode) -> node? + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> node? + + # : (AliasMethodNode) -> node? + def visit_alias_method_node: (AliasMethodNode) -> node? + + # : (AlternationPatternNode) -> node? + def visit_alternation_pattern_node: (AlternationPatternNode) -> node? + + # : (AndNode) -> node? + def visit_and_node: (AndNode) -> node? + + # : (ArgumentsNode) -> node? + def visit_arguments_node: (ArgumentsNode) -> node? + + # : (ArrayNode) -> node? + def visit_array_node: (ArrayNode) -> node? + + # : (ArrayPatternNode) -> node? + def visit_array_pattern_node: (ArrayPatternNode) -> node? + + # : (AssocNode) -> node? + def visit_assoc_node: (AssocNode) -> node? + + # : (AssocSplatNode) -> node? + def visit_assoc_splat_node: (AssocSplatNode) -> node? + + # : (BackReferenceReadNode) -> node? + def visit_back_reference_read_node: (BackReferenceReadNode) -> node? + + # : (BeginNode) -> node? + def visit_begin_node: (BeginNode) -> node? + + # : (BlockArgumentNode) -> node? + def visit_block_argument_node: (BlockArgumentNode) -> node? + + # : (BlockLocalVariableNode) -> node? + def visit_block_local_variable_node: (BlockLocalVariableNode) -> node? + + # : (BlockNode) -> node? + def visit_block_node: (BlockNode) -> node? + + # : (BlockParameterNode) -> node? + def visit_block_parameter_node: (BlockParameterNode) -> node? + + # : (BlockParametersNode) -> node? + def visit_block_parameters_node: (BlockParametersNode) -> node? + + # : (BreakNode) -> node? + def visit_break_node: (BreakNode) -> node? + + # : (CallAndWriteNode) -> node? + def visit_call_and_write_node: (CallAndWriteNode) -> node? + + # : (CallNode) -> node? + def visit_call_node: (CallNode) -> node? + + # : (CallOperatorWriteNode) -> node? + def visit_call_operator_write_node: (CallOperatorWriteNode) -> node? + + # : (CallOrWriteNode) -> node? + def visit_call_or_write_node: (CallOrWriteNode) -> node? + + # : (CallTargetNode) -> node? + def visit_call_target_node: (CallTargetNode) -> node? + + # : (CapturePatternNode) -> node? + def visit_capture_pattern_node: (CapturePatternNode) -> node? + + # : (CaseMatchNode) -> node? + def visit_case_match_node: (CaseMatchNode) -> node? + + # : (CaseNode) -> node? + def visit_case_node: (CaseNode) -> node? + + # : (ClassNode) -> node? + def visit_class_node: (ClassNode) -> node? + + # : (ClassVariableAndWriteNode) -> node? + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> node? + + # : (ClassVariableOperatorWriteNode) -> node? + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> node? + + # : (ClassVariableOrWriteNode) -> node? + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> node? + + # : (ClassVariableReadNode) -> node? + def visit_class_variable_read_node: (ClassVariableReadNode) -> node? + + # : (ClassVariableTargetNode) -> node? + def visit_class_variable_target_node: (ClassVariableTargetNode) -> node? + + # : (ClassVariableWriteNode) -> node? + def visit_class_variable_write_node: (ClassVariableWriteNode) -> node? + + # : (ConstantAndWriteNode) -> node? + def visit_constant_and_write_node: (ConstantAndWriteNode) -> node? + + # : (ConstantOperatorWriteNode) -> node? + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> node? + + # : (ConstantOrWriteNode) -> node? + def visit_constant_or_write_node: (ConstantOrWriteNode) -> node? + + # : (ConstantPathAndWriteNode) -> node? + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> node? + + # : (ConstantPathNode) -> node? + def visit_constant_path_node: (ConstantPathNode) -> node? + + # : (ConstantPathOperatorWriteNode) -> node? + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> node? + + # : (ConstantPathOrWriteNode) -> node? + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> node? + + # : (ConstantPathTargetNode) -> node? + def visit_constant_path_target_node: (ConstantPathTargetNode) -> node? + + # : (ConstantPathWriteNode) -> node? + def visit_constant_path_write_node: (ConstantPathWriteNode) -> node? + + # : (ConstantReadNode) -> node? + def visit_constant_read_node: (ConstantReadNode) -> node? + + # : (ConstantTargetNode) -> node? + def visit_constant_target_node: (ConstantTargetNode) -> node? + + # : (ConstantWriteNode) -> node? + def visit_constant_write_node: (ConstantWriteNode) -> node? + + # : (DefNode) -> node? + def visit_def_node: (DefNode) -> node? + + # : (DefinedNode) -> node? + def visit_defined_node: (DefinedNode) -> node? + + # : (ElseNode) -> node? + def visit_else_node: (ElseNode) -> node? + + # : (EmbeddedStatementsNode) -> node? + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> node? + + # : (EmbeddedVariableNode) -> node? + def visit_embedded_variable_node: (EmbeddedVariableNode) -> node? + + # : (EnsureNode) -> node? + def visit_ensure_node: (EnsureNode) -> node? + + # : (FalseNode) -> node? + def visit_false_node: (FalseNode) -> node? + + # : (FindPatternNode) -> node? + def visit_find_pattern_node: (FindPatternNode) -> node? + + # : (FlipFlopNode) -> node? + def visit_flip_flop_node: (FlipFlopNode) -> node? + + # : (FloatNode) -> node? + def visit_float_node: (FloatNode) -> node? + + # : (ForNode) -> node? + def visit_for_node: (ForNode) -> node? + + # : (ForwardingArgumentsNode) -> node? + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> node? + + # : (ForwardingParameterNode) -> node? + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> node? + + # : (ForwardingSuperNode) -> node? + def visit_forwarding_super_node: (ForwardingSuperNode) -> node? + + # : (GlobalVariableAndWriteNode) -> node? + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> node? + + # : (GlobalVariableOperatorWriteNode) -> node? + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> node? + + # : (GlobalVariableOrWriteNode) -> node? + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> node? + + # : (GlobalVariableReadNode) -> node? + def visit_global_variable_read_node: (GlobalVariableReadNode) -> node? + + # : (GlobalVariableTargetNode) -> node? + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> node? + + # : (GlobalVariableWriteNode) -> node? + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> node? + + # : (HashNode) -> node? + def visit_hash_node: (HashNode) -> node? + + # : (HashPatternNode) -> node? + def visit_hash_pattern_node: (HashPatternNode) -> node? + + # : (IfNode) -> node? + def visit_if_node: (IfNode) -> node? + + # : (ImaginaryNode) -> node? + def visit_imaginary_node: (ImaginaryNode) -> node? + + # : (ImplicitNode) -> node? + def visit_implicit_node: (ImplicitNode) -> node? + + # : (ImplicitRestNode) -> node? + def visit_implicit_rest_node: (ImplicitRestNode) -> node? + + # : (InNode) -> node? + def visit_in_node: (InNode) -> node? + + # : (IndexAndWriteNode) -> node? + def visit_index_and_write_node: (IndexAndWriteNode) -> node? + + # : (IndexOperatorWriteNode) -> node? + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> node? + + # : (IndexOrWriteNode) -> node? + def visit_index_or_write_node: (IndexOrWriteNode) -> node? + + # : (IndexTargetNode) -> node? + def visit_index_target_node: (IndexTargetNode) -> node? + + # : (InstanceVariableAndWriteNode) -> node? + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> node? + + # : (InstanceVariableOperatorWriteNode) -> node? + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> node? + + # : (InstanceVariableOrWriteNode) -> node? + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> node? + + # : (InstanceVariableReadNode) -> node? + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> node? + + # : (InstanceVariableTargetNode) -> node? + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> node? + + # : (InstanceVariableWriteNode) -> node? + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> node? + + # : (IntegerNode) -> node? + def visit_integer_node: (IntegerNode) -> node? + + # : (InterpolatedMatchLastLineNode) -> node? + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> node? + + # : (InterpolatedRegularExpressionNode) -> node? + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> node? + + # : (InterpolatedStringNode) -> node? + def visit_interpolated_string_node: (InterpolatedStringNode) -> node? + + # : (InterpolatedSymbolNode) -> node? + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> node? + + # : (InterpolatedXStringNode) -> node? + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> node? + + # : (ItLocalVariableReadNode) -> node? + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> node? + + # : (ItParametersNode) -> node? + def visit_it_parameters_node: (ItParametersNode) -> node? + + # : (KeywordHashNode) -> node? + def visit_keyword_hash_node: (KeywordHashNode) -> node? + + # : (KeywordRestParameterNode) -> node? + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> node? + + # : (LambdaNode) -> node? + def visit_lambda_node: (LambdaNode) -> node? + + # : (LocalVariableAndWriteNode) -> node? + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> node? + + # : (LocalVariableOperatorWriteNode) -> node? + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> node? + + # : (LocalVariableOrWriteNode) -> node? + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> node? + + # : (LocalVariableReadNode) -> node? + def visit_local_variable_read_node: (LocalVariableReadNode) -> node? + + # : (LocalVariableTargetNode) -> node? + def visit_local_variable_target_node: (LocalVariableTargetNode) -> node? + + # : (LocalVariableWriteNode) -> node? + def visit_local_variable_write_node: (LocalVariableWriteNode) -> node? + + # : (MatchLastLineNode) -> node? + def visit_match_last_line_node: (MatchLastLineNode) -> node? + + # : (MatchPredicateNode) -> node? + def visit_match_predicate_node: (MatchPredicateNode) -> node? + + # : (MatchRequiredNode) -> node? + def visit_match_required_node: (MatchRequiredNode) -> node? + + # : (MatchWriteNode) -> node? + def visit_match_write_node: (MatchWriteNode) -> node? + + # : (MissingNode) -> node? + def visit_missing_node: (MissingNode) -> node? + + # : (ModuleNode) -> node? + def visit_module_node: (ModuleNode) -> node? + + # : (MultiTargetNode) -> node? + def visit_multi_target_node: (MultiTargetNode) -> node? + + # : (MultiWriteNode) -> node? + def visit_multi_write_node: (MultiWriteNode) -> node? + + # : (NextNode) -> node? + def visit_next_node: (NextNode) -> node? + + # : (NilNode) -> node? + def visit_nil_node: (NilNode) -> node? + + # : (NoBlockParameterNode) -> node? + def visit_no_block_parameter_node: (NoBlockParameterNode) -> node? + + # : (NoKeywordsParameterNode) -> node? + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> node? + + # : (NumberedParametersNode) -> node? + def visit_numbered_parameters_node: (NumberedParametersNode) -> node? + + # : (NumberedReferenceReadNode) -> node? + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> node? + + # : (OptionalKeywordParameterNode) -> node? + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> node? + + # : (OptionalParameterNode) -> node? + def visit_optional_parameter_node: (OptionalParameterNode) -> node? + + # : (OrNode) -> node? + def visit_or_node: (OrNode) -> node? + + # : (ParametersNode) -> node? + def visit_parameters_node: (ParametersNode) -> node? + + # : (ParenthesesNode) -> node? + def visit_parentheses_node: (ParenthesesNode) -> node? + + # : (PinnedExpressionNode) -> node? + def visit_pinned_expression_node: (PinnedExpressionNode) -> node? + + # : (PinnedVariableNode) -> node? + def visit_pinned_variable_node: (PinnedVariableNode) -> node? + + # : (PostExecutionNode) -> node? + def visit_post_execution_node: (PostExecutionNode) -> node? + + # : (PreExecutionNode) -> node? + def visit_pre_execution_node: (PreExecutionNode) -> node? + + # : (ProgramNode) -> node? + def visit_program_node: (ProgramNode) -> node? + + # : (RangeNode) -> node? + def visit_range_node: (RangeNode) -> node? + + # : (RationalNode) -> node? + def visit_rational_node: (RationalNode) -> node? + + # : (RedoNode) -> node? + def visit_redo_node: (RedoNode) -> node? + + # : (RegularExpressionNode) -> node? + def visit_regular_expression_node: (RegularExpressionNode) -> node? + + # : (RequiredKeywordParameterNode) -> node? + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> node? + + # : (RequiredParameterNode) -> node? + def visit_required_parameter_node: (RequiredParameterNode) -> node? + + # : (RescueModifierNode) -> node? + def visit_rescue_modifier_node: (RescueModifierNode) -> node? + + # : (RescueNode) -> node? + def visit_rescue_node: (RescueNode) -> node? + + # : (RestParameterNode) -> node? + def visit_rest_parameter_node: (RestParameterNode) -> node? + + # : (RetryNode) -> node? + def visit_retry_node: (RetryNode) -> node? + + # : (ReturnNode) -> node? + def visit_return_node: (ReturnNode) -> node? + + # : (SelfNode) -> node? + def visit_self_node: (SelfNode) -> node? + + # : (ShareableConstantNode) -> node? + def visit_shareable_constant_node: (ShareableConstantNode) -> node? + + # : (SingletonClassNode) -> node? + def visit_singleton_class_node: (SingletonClassNode) -> node? + + # : (SourceEncodingNode) -> node? + def visit_source_encoding_node: (SourceEncodingNode) -> node? + + # : (SourceFileNode) -> node? + def visit_source_file_node: (SourceFileNode) -> node? + + # : (SourceLineNode) -> node? + def visit_source_line_node: (SourceLineNode) -> node? + + # : (SplatNode) -> node? + def visit_splat_node: (SplatNode) -> node? + + # : (StatementsNode) -> node? + def visit_statements_node: (StatementsNode) -> node? + + # : (StringNode) -> node? + def visit_string_node: (StringNode) -> node? + + # : (SuperNode) -> node? + def visit_super_node: (SuperNode) -> node? + + # : (SymbolNode) -> node? + def visit_symbol_node: (SymbolNode) -> node? + + # : (TrueNode) -> node? + def visit_true_node: (TrueNode) -> node? + + # : (UndefNode) -> node? + def visit_undef_node: (UndefNode) -> node? + + # : (UnlessNode) -> node? + def visit_unless_node: (UnlessNode) -> node? + + # : (UntilNode) -> node? + def visit_until_node: (UntilNode) -> node? + + # : (WhenNode) -> node? + def visit_when_node: (WhenNode) -> node? + + # : (WhileNode) -> node? + def visit_while_node: (WhileNode) -> node? + + # : (XStringNode) -> node? + def visit_x_string_node: (XStringNode) -> node? + + # : (YieldNode) -> node? + def visit_yield_node: (YieldNode) -> node? + end +end diff --git a/sig/generated/prism/node.rbs b/sig/generated/prism/node.rbs new file mode 100644 index 0000000000..032c26056a --- /dev/null +++ b/sig/generated/prism/node.rbs @@ -0,0 +1,20896 @@ +# Generated from lib/prism/node.rb with RBS::Inline + +module Prism + interface _Repository + def enter: (Integer node_id, Symbol field_name) -> Relocation::Entry + end + + interface _Node + def deconstruct: () -> Array[Prism::node?] + + def inspect: () -> String + end + + type node = Node & _Node + + # This represents a node in the tree. It is the parent class of all of the + # various node types. + class Node + # A pointer to the source that this node was created from. + # :stopdoc: + attr_reader source: Source + + # A unique identifier for this node. This is used in a very specific + # use case where you want to keep around a reference to a node without + # having to keep around the syntax tree in memory. This unique identifier + # will be consistent across multiple parses of the same source code. + attr_reader node_id: Integer + + @location: Location | Integer + + # Save this node using a saved source so that it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save: (_Repository repository) -> Relocation::Entry + + # A Location instance that represents the location of this node in the + # source. + # -- + # : () -> Location + def location: () -> Location + + # Save the location using a saved source so that it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_location: (_Repository repository) -> Relocation::Entry + + # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. + # -- + # : () -> Integer + def start_line: () -> Integer + + # Delegates to [`end_line`](rdoc-ref:Location#end_line) of the associated location object. + # -- + # : () -> Integer + def end_line: () -> Integer + + # Delegates to [`start_offset`](rdoc-ref:Location#start_offset) of the associated location object. + # -- + # : () -> Integer + def start_offset: () -> Integer + + # Delegates to [`end_offset`](rdoc-ref:Location#end_offset) of the associated location object. + # -- + # : () -> Integer + def end_offset: () -> Integer + + # Delegates to [`start_character_offset`](rdoc-ref:Location#start_character_offset) + # of the associated location object. + # -- + # : () -> Integer + def start_character_offset: () -> Integer + + # Delegates to [`end_character_offset`](rdoc-ref:Location#end_character_offset) + # of the associated location object. + # -- + # : () -> Integer + def end_character_offset: () -> Integer + + # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. + # -- + # : () -> Integer + def start_column: () -> Integer + + # Delegates to [`end_column`](rdoc-ref:Location#end_column) of the associated location object. + # -- + # : () -> Integer + def end_column: () -> Integer + + # Delegates to [`start_character_column`](rdoc-ref:Location#start_character_column) + # of the associated location object. + # -- + # : () -> Integer + def start_character_column: () -> Integer + + # Delegates to [`end_character_column`](rdoc-ref:Location#end_character_column) + # of the associated location object. + # -- + # : () -> Integer + def end_character_column: () -> Integer + + # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) + # of the associated location object. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + + # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. + # -- + # : () -> Array[Comment] + def leading_comments: () -> Array[Comment] + + # Delegates to [`trailing_comments`](rdoc-ref:Location#trailing_comments) of the associated location object. + # -- + # : () -> Array[Comment] + def trailing_comments: () -> Array[Comment] + + # Delegates to [`comments`](rdoc-ref:Location#comments) of the associated location object. + # -- + # : () -> Array[Comment] + def comments: () -> Array[Comment] + + # Returns all of the lines of the source code associated with this node. + # -- + # : () -> Array[String] + def source_lines: () -> Array[String] + + # An alias for source_lines, used to mimic the API from + # RubyVM::AbstractSyntaxTree to make it easier to migrate. + alias script_lines source_lines + + # Slice the location of the node from the source. + # -- + # : () -> String + def slice: () -> String + + # Slice the location of the node from the source, starting at the beginning + # of the line that the location starts on, ending at the end of the line + # that the location ends on. + # -- + # : () -> String + def slice_lines: () -> String + + # An bitset of flags for this node. There are certain flags that are common + # for all nodes, and then some nodes have specific flags. + # :stopdoc: + attr_reader flags: Integer + + # Returns true if the node has the newline flag set. + # -- + # : () -> bool + def newline?: () -> bool + + # Returns true if the node has the static literal flag set. + # -- + # : () -> bool + def static_literal?: () -> bool + + # Similar to inspect, but respects the current level of indentation given by + # the pretty print object. + # -- + # : (PP q) -> void + def pretty_print: (PP q) -> void + + # Convert this node into a graphviz dot graph string. + # -- + # : () -> String + def to_dot: () -> String + + # Returns a list of nodes that are descendants of this node that contain the + # given line and column. This is useful for locating a node that is selected + # based on the line and column of the source code. + # + # Important to note is that the column given to this method should be in + # bytes, as opposed to characters or code units. + # -- + # : (Integer line, Integer column) -> Array[node] + def tunnel: (Integer line, Integer column) -> Array[node] + + # Returns the first node that matches the given block when visited in a + # breadth-first search. This is useful for finding a node that matches a + # particular condition. + # + # node.breadth_first_search { |node| node.node_id == node_id } + # -- + # : () { (node) -> bool } -> node? + def breadth_first_search: () { (node) -> bool } -> node? + + alias find breadth_first_search + + # Returns all of the nodes that match the given block when visited in a + # breadth-first search. This is useful for finding all nodes that match a + # particular condition. + # + # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } + # -- + # : () { (node) -> bool } -> Array[node] + def breadth_first_search_all: () { (node) -> bool } -> Array[node] + + alias find_all breadth_first_search_all + + # Returns a list of the fields that exist for this node class. Fields + # describe the structure of the node. This kind of reflection is useful for + # things like recursively visiting each node _and_ field in the tree. + # -- + # : () -> Array[Reflection::Field] + def self.fields: () -> Array[Reflection::Field] + + # Accepts a visitor and calls back into the specialized visit function. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # Returns an array of child nodes, including `nil`s in the place of optional + # nodes that were not present. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + alias deconstruct child_nodes + + # With a block given, yields each child node. Without a block, returns + # an enumerator that contains each child node. Excludes any `nil`s in + # the place of optional nodes that were not present. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # Returns an array of child nodes, excluding any `nil`s in the place of + # optional nodes that were not present. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # Returns an array of child nodes and locations that could potentially have + # comments attached to them. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # Returns a string representation of the node. + # -- + # : () -> String + def inspect: () -> String + + # Sometimes you want to check an instance of a node against a list of + # classes to see what kind of behavior to perform. Usually this is done by + # calling `[cls1, cls2].include?(node.class)` or putting the node into a + # case statement and doing `case node; when cls1; when cls2; end`. Both of + # these approaches are relatively slow because of the constant lookups, + # method calls, and/or array allocations. + # + # Instead, you can call #type, which will return to you a symbol that you + # can use for comparison. This is faster than the other approaches because + # it uses a single integer comparison, but also because if you're on CRuby + # you can take advantage of the fact that case statements with all symbol + # keys will use a jump table. + # -- + # : () -> Symbol + def type: () -> Symbol + + # Similar to #type, this method returns a symbol that you can use for + # splitting on the type of the node without having to do a long === chain. + # Note that like #type, it will still be slower than using == for a single + # class, but should be faster in a case statement or an array comparison. + # -- + # : () -> Symbol + def self.type: () -> Symbol + end + + # Represents the use of the `alias` keyword to alias a global variable. + # + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + class AliasGlobalVariableNode < Node + @keyword_loc: Location + + @old_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode + + @new_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + + # Initialize a new AliasGlobalVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) new_name, (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode) old_name, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode new_name, GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode old_name, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AliasGlobalVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode), ?old_name: (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode), ?keyword_loc: Location) -> AliasGlobalVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode, ?old_name: GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode, ?keyword_loc: Location) -> AliasGlobalVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :alias_global_variable_node + def type: () -> :alias_global_variable_node + + # See `Node.type`. + # -- + # : () -> :alias_global_variable_node + def self.type: () -> :alias_global_variable_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # new_name -> GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + # + # Represents the new name of the global variable that can be used after aliasing. + # + # alias $foo $bar + # ^^^^ + # -- + # : () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + def new_name: () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + + # :call-seq: + # old_name -> GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode + # + # Represents the old name of the global variable that can be used before aliasing. + # + # alias $foo $bar + # ^^^^ + # -- + # : () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode) + def old_name: () -> (GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | SymbolNode | MissingNode) + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # The Location of the `alias` keyword. + # + # alias $foo $bar + # ^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `alias` keyword to alias a method. + # + # alias foo bar + # ^^^^^^^^^^^^^ + class AliasMethodNode < Node + @keyword_loc: Location + + @old_name: SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode + + @new_name: SymbolNode | InterpolatedSymbolNode + + # Initialize a new AliasMethodNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (SymbolNode | InterpolatedSymbolNode) new_name, (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode) old_name, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, SymbolNode | InterpolatedSymbolNode new_name, SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode old_name, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AliasMethodNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: (SymbolNode | InterpolatedSymbolNode), ?old_name: (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode), ?keyword_loc: Location) -> AliasMethodNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?new_name: SymbolNode | InterpolatedSymbolNode, ?old_name: SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode, ?keyword_loc: Location) -> AliasMethodNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :alias_method_node + def type: () -> :alias_method_node + + # See `Node.type`. + # -- + # : () -> :alias_method_node + def self.type: () -> :alias_method_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # new_name -> SymbolNode | InterpolatedSymbolNode + # + # Represents the new name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + # -- + # : () -> (SymbolNode | InterpolatedSymbolNode) + def new_name: () -> (SymbolNode | InterpolatedSymbolNode) + + # :call-seq: + # old_name -> SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode + # + # Represents the old name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + # -- + # : () -> (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode) + def old_name: () -> (SymbolNode | InterpolatedSymbolNode | GlobalVariableReadNode | MissingNode) + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Represents the Location of the `alias` keyword. + # + # alias foo bar + # ^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an alternation pattern in pattern matching. + # + # foo => bar | baz + # ^^^^^^^^^ + class AlternationPatternNode < Node + @operator_loc: Location + + @right: Prism::node + + @left: Prism::node + + # Initialize a new AlternationPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AlternationPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AlternationPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :alternation_pattern_node + def type: () -> :alternation_pattern_node + + # See `Node.type`. + # -- + # : () -> :alternation_pattern_node + def self.type: () -> :alternation_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # left -> Node + # + # Represents the left side of the expression. + # + # foo => bar | baz + # ^^^ + # -- + # : () -> Prism::node + def left: () -> Prism::node + + # :call-seq: + # right -> Node + # + # Represents the right side of the expression. + # + # foo => bar | baz + # ^^^ + # -- + # : () -> Prism::node + def right: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the alternation operator Location. + # + # foo => bar | baz + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&` operator or the `and` keyword. + # + # left and right + # ^^^^^^^^^^^^^^ + class AndNode < Node + @operator_loc: Location + + @right: Prism::node + + @left: Prism::node + + # Initialize a new AndNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AndNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> AndNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :and_node + def type: () -> :and_node + + # See `Node.type`. + # -- + # : () -> :and_node + def self.type: () -> :and_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # left -> Node + # + # Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # left and right + # ^^^^ + # + # 1 && 2 + # ^ + # -- + # : () -> Prism::node + def left: () -> Prism::node + + # :call-seq: + # right -> Node + # + # Represents the right side of the expression. + # + # left && right + # ^^^^^ + # + # 1 and 2 + # ^ + # -- + # : () -> Prism::node + def right: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `and` keyword or the `&&` operator. + # + # left and right + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a set of arguments to a method or a keyword. + # + # return foo, bar, baz + # ^^^^^^^^^^^^^ + class ArgumentsNode < Node + @arguments: Array[Prism::node] + + # Initialize a new ArgumentsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] arguments) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] arguments) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ArgumentsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: Array[Prism::node]) -> ArgumentsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :arguments_node + def type: () -> :arguments_node + + # See `Node.type`. + # -- + # : () -> :arguments_node + def self.type: () -> :arguments_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # if the arguments contain forwarding + # -- + # : () -> bool + def contains_forwarding?: () -> bool + + # :category: Flags + # if the arguments contain keywords + # -- + # : () -> bool + def contains_keywords?: () -> bool + + # :category: Flags + # if the arguments contain a keyword splat + # -- + # : () -> bool + def contains_keyword_splat?: () -> bool + + # :category: Flags + # if the arguments contain a splat + # -- + # : () -> bool + def contains_splat?: () -> bool + + # :category: Flags + # if the arguments contain multiple splats + # -- + # : () -> bool + def contains_multiple_splats?: () -> bool + + # :call-seq: + # arguments -> Array[Node] + # + # The list of arguments, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar, baz) + # ^^^^^^^^ + # -- + # : () -> Array[Prism::node] + def arguments: () -> Array[Prism::node] + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i. + # + # [1, 2, 3] + # ^^^^^^^^^ + class ArrayNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @elements: Array[Prism::node] + + # Initialize a new ArrayNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] elements, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] elements, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ArrayNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :array_node + def type: () -> :array_node + + # See `Node.type`. + # -- + # : () -> :array_node + def self.type: () -> :array_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # if array contains splat nodes + # -- + # : () -> bool + def contains_splat?: () -> bool + + # :call-seq: + # elements -> Array[Node] + # + # Represent the list of zero or more [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression) within the array. + # -- + # : () -> Array[Prism::node] + def elements: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the optional source Location for the opening token. + # + # [1,2,3] # "[" + # %w[foo bar baz] # "%w[" + # %I(apple orange banana) # "%I(" + # foo = 1, 2, 3 # nil + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the optional source Location for the closing token. + # + # [1,2,3] # "]" + # %w[foo bar baz] # "]" + # %I(apple orange banana) # ")" + # foo = 1, 2, 3 # nil + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an array pattern in pattern matching. + # + # foo in 1, 2 + # ^^^^^^^^^^^ + # + # foo in [1, 2] + # ^^^^^^^^^^^^^ + # + # foo in *bar + # ^^^^^^^^^^^ + # + # foo in Bar[] + # ^^^^^^^^^^^^ + # + # foo in Bar[1, 2, 3] + # ^^^^^^^^^^^^^^^^^^^ + class ArrayPatternNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @posts: Array[Prism::node] + + @rest: Prism::node? + + @requireds: Array[Prism::node] + + @constant: (ConstantPathNode | ConstantReadNode)? + + # Initialize a new ArrayPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[Prism::node] requireds, Prism::node? rest, Array[Prism::node] posts, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[Prism::node] requireds, Prism::node? rest, Array[Prism::node] posts, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ArrayPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?requireds: Array[Prism::node], ?rest: Prism::node?, ?posts: Array[Prism::node], ?opening_loc: Location?, ?closing_loc: Location?) -> ArrayPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :array_pattern_node + def type: () -> :array_pattern_node + + # See `Node.type`. + # -- + # : () -> :array_pattern_node + def self.type: () -> :array_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # constant -> ConstantPathNode | ConstantReadNode | nil + # + # Represents the optional constant preceding the Array + # + # foo in Bar[] + # ^^^ + # + # foo in Bar[1, 2, 3] + # ^^^ + # + # foo in Bar::Baz[1, 2, 3] + # ^^^^^^^^ + # -- + # : () -> (ConstantPathNode | ConstantReadNode)? + def constant: () -> (ConstantPathNode | ConstantReadNode)? + + # :call-seq: + # requireds -> Array[Node] + # + # Represents the required elements of the array pattern. + # + # foo in [1, 2] + # ^ ^ + # -- + # : () -> Array[Prism::node] + def requireds: () -> Array[Prism::node] + + # :call-seq: + # rest -> Node | nil + # + # Represents the rest element of the array pattern. + # + # foo in *bar + # ^^^^ + # -- + # : () -> Prism::node? + def rest: () -> Prism::node? + + # :call-seq: + # posts -> Array[Node] + # + # Represents the elements after the rest element of the array pattern. + # + # foo in *bar, baz + # ^^^ + # -- + # : () -> Array[Prism::node] + def posts: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the opening Location of the array pattern. + # + # foo in [1, 2] + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the closing Location of the array pattern. + # + # foo in [1, 2] + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a hash key/value pair. + # + # { a => b } + # ^^^^^^ + class AssocNode < Node + @operator_loc: Location? + + @value: Prism::node + + @key: Prism::node + + # Initialize a new AssocNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node key, Prism::node value, Location? operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node key, Prism::node value, Location? operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AssocNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?key: Prism::node, ?value: Prism::node, ?operator_loc: Location?) -> AssocNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :assoc_node + def type: () -> :assoc_node + + # See `Node.type`. + # -- + # : () -> :assoc_node + def self.type: () -> :assoc_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # key -> Node + # + # The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # { a: b } + # ^ + # + # { foo => bar } + # ^^^ + # + # { def a; end => 1 } + # ^^^^^^^^^^ + # -- + # : () -> Prism::node + def key: () -> Prism::node + + # :call-seq: + # value -> Node + # + # The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # { foo => bar } + # ^^^ + # + # { x: 1 } + # ^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location | nil + # + # The Location of the `=>` operator, if present. + # + # { foo => bar } + # ^^ + # -- + # : () -> Location? + def operator_loc: () -> Location? + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # operator -> String | nil + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String? + def operator: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a splat in a hash literal. + # + # { **foo } + # ^^^^^ + class AssocSplatNode < Node + @operator_loc: Location + + @value: Prism::node? + + # Initialize a new AssocSplatNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> AssocSplatNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node?, ?operator_loc: Location) -> AssocSplatNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :assoc_splat_node + def type: () -> :assoc_splat_node + + # See `Node.type`. + # -- + # : () -> :assoc_splat_node + def self.type: () -> :assoc_splat_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node | nil + # + # The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used. + # + # { **foo } + # ^^^ + # -- + # : () -> Prism::node? + def value: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `**` operator. + # + # { **x } + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents reading a reference to a field in the previous match. + # + # $' + # ^^ + class BackReferenceReadNode < Node + @name: Symbol + + # Initialize a new BackReferenceReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BackReferenceReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BackReferenceReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :back_reference_read_node + def type: () -> :back_reference_read_node + + # See `Node.type`. + # -- + # : () -> :back_reference_read_node + def self.type: () -> :back_reference_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the back-reference variable, including the leading `$`. + # + # $& # name `:$&` + # + # $+ # name `:$+` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a begin statement. + # + # begin + # foo + # end + # ^^^^^ + class BeginNode < Node + @end_keyword_loc: Location? + + @ensure_clause: EnsureNode? + + @else_clause: ElseNode? + + @rescue_clause: RescueNode? + + @statements: StatementsNode? + + @begin_keyword_loc: Location? + + # Initialize a new BeginNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? begin_keyword_loc, StatementsNode? statements, RescueNode? rescue_clause, ElseNode? else_clause, EnsureNode? ensure_clause, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? begin_keyword_loc, StatementsNode? statements, RescueNode? rescue_clause, ElseNode? else_clause, EnsureNode? ensure_clause, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BeginNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?begin_keyword_loc: Location?, ?statements: StatementsNode?, ?rescue_clause: RescueNode?, ?else_clause: ElseNode?, ?ensure_clause: EnsureNode?, ?end_keyword_loc: Location?) -> BeginNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :begin_node + def type: () -> :begin_node + + # See `Node.type`. + # -- + # : () -> :begin_node + def self.type: () -> :begin_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # begin_keyword_loc -> Location | nil + # + # Represents the Location of the `begin` keyword. + # + # begin x end + # ^^^^^ + # -- + # : () -> Location? + def begin_keyword_loc: () -> Location? + + # :category: Repository + # Save the begin_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_begin_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Represents the statements within the begin block. + # + # begin x end + # ^ + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # rescue_clause -> RescueNode | nil + # + # Represents the rescue clause within the begin block. + # + # begin x; rescue y; end + # ^^^^^^^^ + # -- + # : () -> RescueNode? + def rescue_clause: () -> RescueNode? + + # :call-seq: + # else_clause -> ElseNode | nil + # + # Represents the else clause within the begin block. + # + # begin x; rescue y; else z; end + # ^^^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :call-seq: + # ensure_clause -> EnsureNode | nil + # + # Represents the ensure clause within the begin block. + # + # begin x; ensure y; end + # ^^^^^^^^ + # -- + # : () -> EnsureNode? + def ensure_clause: () -> EnsureNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # Represents the Location of the `end` keyword. + # + # begin x end + # ^^^ + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # begin_keyword -> String | nil + # + # Slice the location of begin_keyword_loc from the source. + # -- + # : () -> String? + def begin_keyword: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a block argument using `&`. + # + # bar(&args) + # ^^^^^^^^^^ + class BlockArgumentNode < Node + @operator_loc: Location + + @expression: Prism::node? + + # Initialize a new BlockArgumentNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? expression, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? expression, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockArgumentNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node?, ?operator_loc: Location) -> BlockArgumentNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_argument_node + def type: () -> :block_argument_node + + # See `Node.type`. + # -- + # : () -> :block_argument_node + def self.type: () -> :block_argument_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # expression -> Node | nil + # + # The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(&args) + # ^^^^^ + # -- + # : () -> Prism::node? + def expression: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `&` operator. + # + # foo(&args) + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a block local variable. + # + # a { |; b| } + # ^ + class BlockLocalVariableNode < Node + @name: Symbol + + # Initialize a new BlockLocalVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockLocalVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> BlockLocalVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_local_variable_node + def type: () -> :block_local_variable_node + + # See `Node.type`. + # -- + # : () -> :block_local_variable_node + def self.type: () -> :block_local_variable_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # The name of the block local variable. + # + # a { |; b| } # name `:b` + # ^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a block of ruby code. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^^^^^^^^^ + class BlockNode < Node + @closing_loc: Location + + @opening_loc: Location + + @body: (StatementsNode | BeginNode)? + + @parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + @locals: Array[Symbol] + + # Initialize a new BlockNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?, ?opening_loc: Location, ?closing_loc: Location) -> BlockNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_node + def type: () -> :block_node + + # See `Node.type`. + # -- + # : () -> :block_node + def self.type: () -> :block_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # The local variables declared in the block. + # + # [1, 2, 3].each { |i| puts x } # locals: [:i] + # ^ + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :call-seq: + # parameters -> BlockParametersNode | NumberedParametersNode | ItParametersNode | nil + # + # The parameters of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^ + # [1, 2, 3].each { puts _1 } + # ^^^^^^^^^^^ + # [1, 2, 3].each { puts it } + # ^^^^^^^^^^^ + # -- + # : () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + def parameters: () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # The body of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^ + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Represents the Location of the opening `{` or `do`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Represents the Location of the closing `}` or `end`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a block parameter of a method, block, or lambda definition. + # + # def a(&b) + # ^^ + # end + class BlockParameterNode < Node + @operator_loc: Location + + @name_loc: Location? + + @name: Symbol? + + # Initialize a new BlockParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> BlockParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_parameter_node + def type: () -> :block_parameter_node + + # See `Node.type`. + # -- + # : () -> :block_parameter_node + def self.type: () -> :block_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol | nil + # + # The name of the block parameter. + # + # def a(&b) # name `:b` + # ^ + # end + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # name_loc -> Location | nil + # + # Represents the Location of the block parameter name. + # + # def a(&b) + # ^ + # -- + # : () -> Location? + def name_loc: () -> Location? + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_name_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `&` operator. + # + # def a(&b) + # ^ + # end + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a block's parameters declaration. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^^^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^^^^^^^^^^ + # end + class BlockParametersNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @locals: Array[BlockLocalVariableNode] + + @parameters: ParametersNode? + + # Initialize a new BlockParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ParametersNode? parameters, Array[BlockLocalVariableNode] locals, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ParametersNode? parameters, Array[BlockLocalVariableNode] locals, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BlockParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?parameters: ParametersNode?, ?locals: Array[BlockLocalVariableNode], ?opening_loc: Location?, ?closing_loc: Location?) -> BlockParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :block_parameters_node + def type: () -> :block_parameters_node + + # See `Node.type`. + # -- + # : () -> :block_parameters_node + def self.type: () -> :block_parameters_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # parameters -> ParametersNode | nil + # + # Represents the parameters of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^ + # end + # -- + # : () -> ParametersNode? + def parameters: () -> ParametersNode? + + # :call-seq: + # locals -> Array[BlockLocalVariableNode] + # + # Represents the local variables of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^ + # end + # -- + # : () -> Array[BlockLocalVariableNode] + def locals: () -> Array[BlockLocalVariableNode] + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the opening Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the closing Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `break` keyword. + # + # break foo + # ^^^^^^^^^ + class BreakNode < Node + @keyword_loc: Location + + @arguments: ArgumentsNode? + + # Initialize a new BreakNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> BreakNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> BreakNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :break_node + def type: () -> :break_node + + # See `Node.type`. + # -- + # : () -> :break_node + def self.type: () -> :break_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # The arguments to the break statement, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # break foo + # ^^^ + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # The Location of the `break` keyword. + # + # break foo + # ^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator on a call. + # + # foo.bar &&= value + # ^^^^^^^^^^^^^^^^^ + class CallAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @write_name: Symbol + + @read_name: Symbol + + @message_loc: Location? + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_and_write_node + def type: () -> :call_and_write_node + + # See `Node.type`. + # -- + # : () -> :call_and_write_node + def self.type: () -> :call_and_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar &&= value + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar &&= value + # ^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar &&= value + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # read_name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar &&= value # read_name `:bar` + # ^^^ + # -- + # : () -> Symbol + def read_name: () -> Symbol + + # :call-seq: + # write_name -> Symbol + # + # Represents the name of the method being written to. + # + # foo.bar &&= value # write_name `:bar=` + # ^^^ + # -- + # : () -> Symbol + def write_name: () -> Symbol + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the operator. + # + # foo.bar &&= value + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. + # + # foo.bar &&= value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a method call, in all of the various forms that can take. + # + # foo + # ^^^ + # + # foo() + # ^^^^^ + # + # +foo + # ^^^^ + # + # foo + bar + # ^^^^^^^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo&.bar + # ^^^^^^^^ + class CallNode < Node + @block: (BlockNode | BlockArgumentNode)? + + @equal_loc: Location? + + @closing_loc: Location? + + @arguments: ArgumentsNode? + + @opening_loc: Location? + + @message_loc: Location? + + @name: Symbol + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Symbol name, Location? message_loc, Location? opening_loc, ArgumentsNode? arguments, Location? closing_loc, Location? equal_loc, (BlockNode | BlockArgumentNode)? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Symbol name, Location? message_loc, Location? opening_loc, ArgumentsNode? arguments, Location? closing_loc, Location? equal_loc, (BlockNode | BlockArgumentNode)? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?name: Symbol, ?message_loc: Location?, ?opening_loc: Location?, ?arguments: ArgumentsNode?, ?closing_loc: Location?, ?equal_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> CallNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_node + def type: () -> :call_node + + # See `Node.type`. + # -- + # : () -> :call_node + def self.type: () -> :call_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar + # ^^^ + # + # +foo + # ^^^ + # + # foo + bar + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar + # ^ + # + # foo&.bar + # ^^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar # name `:foo` + # ^^^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Represents the Location of the left parenthesis. + # + # foo(bar) + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar) + # ^^^ + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Represents the Location of the right parenthesis. + # + # foo(bar) + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # equal_loc -> Location | nil + # + # Represents the Location of the equal sign, in the case that this is an attribute write. + # + # foo.bar = value + # ^ + # + # foo[bar] = value + # ^ + # -- + # : () -> Location? + def equal_loc: () -> Location? + + # :category: Repository + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_equal_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # block -> BlockNode | BlockArgumentNode | nil + # + # Represents the block that is being passed to the method. + # + # foo { |a| a } + # ^^^^^^^^^ + # -- + # : () -> (BlockNode | BlockArgumentNode)? + def block: () -> (BlockNode | BlockArgumentNode)? + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # :call-seq: + # equal -> String | nil + # + # Slice the location of equal_loc from the source. + # -- + # : () -> String? + def equal: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of an assignment operator on a call. + # + # foo.bar += baz + # ^^^^^^^^^^^^^^ + class CallOperatorWriteNode < Node + @value: Prism::node + + @binary_operator_loc: Location + + @binary_operator: Symbol + + @write_name: Symbol + + @read_name: Symbol + + @message_loc: Location? + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> CallOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_operator_write_node + def type: () -> :call_operator_write_node + + # See `Node.type`. + # -- + # : () -> :call_operator_write_node + def self.type: () -> :call_operator_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar += value + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar += value + # ^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar += value + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # read_name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar += value # read_name `:bar` + # ^^^ + # -- + # : () -> Symbol + def read_name: () -> Symbol + + # :call-seq: + # write_name -> Symbol + # + # Represents the name of the method being written to. + # + # foo.bar += value # write_name `:bar=` + # ^^^ + # -- + # : () -> Symbol + def write_name: () -> Symbol + + # :call-seq: + # binary_operator -> Symbol + # + # Represents the binary operator being used. + # + # foo.bar += value # binary_operator `:+` + # ^ + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Represents the Location of the binary operator. + # + # foo.bar += value + # ^^ + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. + # + # foo.bar += value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator on a call. + # + # foo.bar ||= value + # ^^^^^^^^^^^^^^^^^ + class CallOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @write_name: Symbol + + @read_name: Symbol + + @message_loc: Location? + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new CallOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location? message_loc, Symbol read_name, Symbol write_name, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?message_loc: Location?, ?read_name: Symbol, ?write_name: Symbol, ?operator_loc: Location, ?value: Prism::node) -> CallOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_or_write_node + def type: () -> :call_or_write_node + + # See `Node.type`. + # -- + # : () -> :call_or_write_node + def self.type: () -> :call_or_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar ||= value + # ^^^ + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Represents the Location of the call operator. + # + # foo.bar ||= value + # ^ + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # message_loc -> Location | nil + # + # Represents the Location of the message. + # + # foo.bar ||= value + # ^^^ + # -- + # : () -> Location? + def message_loc: () -> Location? + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_message_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # read_name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar ||= value # read_name `:bar` + # ^^^ + # -- + # : () -> Symbol + def read_name: () -> Symbol + + # :call-seq: + # write_name -> Symbol + # + # Represents the name of the method being written to. + # + # foo.bar ||= value # write_name `:bar=` + # ^^^ + # -- + # : () -> Symbol + def write_name: () -> Symbol + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the operator. + # + # foo.bar ||= value + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. + # + # foo.bar ||= value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # message -> String | nil + # + # Slice the location of message_loc from the source. + # -- + # : () -> String? + def message: () -> String? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to a method call. + # + # foo.bar, = 1 + # ^^^^^^^ + # + # begin + # rescue => foo.bar + # ^^^^^^^ + # end + # + # for foo.bar in baz do end + # ^^^^^^^ + class CallTargetNode < Node + @message_loc: Location + + @name: Symbol + + @call_operator_loc: Location + + @receiver: Prism::node + + # Initialize a new CallTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location call_operator_loc, Symbol name, Location message_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location call_operator_loc, Symbol name, Location message_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CallTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?call_operator_loc: Location, ?name: Symbol, ?message_loc: Location) -> CallTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :call_target_node + def type: () -> :call_target_node + + # See `Node.type`. + # -- + # : () -> :call_target_node + def self.type: () -> :call_target_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node + # + # The object that the method is being called on. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar = 1 + # ^^^ + # -- + # : () -> Prism::node + def receiver: () -> Prism::node + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location + # + # Represents the Location of the call operator. + # + # foo.bar = 1 + # ^ + # -- + # : () -> Location + def call_operator_loc: () -> Location + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # name -> Symbol + # + # Represents the name of the method being called. + # + # foo.bar = 1 # name `:foo` + # ^^^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # message_loc -> Location + # + # Represents the Location of the message. + # + # foo.bar = 1 + # ^^^ + # -- + # : () -> Location + def message_loc: () -> Location + + # :category: Repository + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_message_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # call_operator -> String + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String + def call_operator: () -> String + + # :call-seq: + # message -> String + # + # Slice the location of message_loc from the source. + # -- + # : () -> String + def message: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to a local variable in pattern matching. + # + # foo => [bar => baz] + # ^^^^^^^^^^^^ + class CapturePatternNode < Node + @operator_loc: Location + + @target: LocalVariableTargetNode + + @value: Prism::node + + # Initialize a new CapturePatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node value, LocalVariableTargetNode target, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node value, LocalVariableTargetNode target, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CapturePatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?target: LocalVariableTargetNode, ?operator_loc: Location) -> CapturePatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :capture_pattern_node + def type: () -> :capture_pattern_node + + # See `Node.type`. + # -- + # : () -> :capture_pattern_node + def self.type: () -> :capture_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node + # + # Represents the value to capture. + # + # foo => bar + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # target -> LocalVariableTargetNode + # + # Represents the target of the capture. + # + # foo => bar + # ^^^ + # -- + # : () -> LocalVariableTargetNode + def target: () -> LocalVariableTargetNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `=>` operator. + # + # foo => bar + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of a case statement for pattern matching. + # + # case true + # in false + # end + # ^^^^^^^^^ + class CaseMatchNode < Node + @end_keyword_loc: Location + + @case_keyword_loc: Location + + @else_clause: ElseNode? + + @conditions: Array[InNode] + + @predicate: Prism::node? + + # Initialize a new CaseMatchNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[InNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[InNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CaseMatchNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[InNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseMatchNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :case_match_node + def type: () -> :case_match_node + + # See `Node.type`. + # -- + # : () -> :case_match_node + def self.type: () -> :case_match_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # predicate -> Node | nil + # + # Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; in false; end + # ^^^^ + # -- + # : () -> Prism::node? + def predicate: () -> Prism::node? + + # :call-seq: + # conditions -> Array[InNode] + # + # Represents the conditions of the case match. + # + # case true; in false; end + # ^^^^^^^^ + # -- + # : () -> Array[InNode] + def conditions: () -> Array[InNode] + + # :call-seq: + # else_clause -> ElseNode | nil + # + # Represents the else clause of the case match. + # + # case true; in false; else; end + # ^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :category: Locations + # :call-seq: + # case_keyword_loc -> Location + # + # Represents the Location of the `case` keyword. + # + # case true; in false; end + # ^^^^ + # -- + # : () -> Location + def case_keyword_loc: () -> Location + + # :category: Repository + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_case_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Represents the Location of the `end` keyword. + # + # case true; in false; end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # case_keyword -> String + # + # Slice the location of case_keyword_loc from the source. + # -- + # : () -> String + def case_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of a case statement. + # + # case true + # when false + # end + # ^^^^^^^^^^ + class CaseNode < Node + @end_keyword_loc: Location + + @case_keyword_loc: Location + + @else_clause: ElseNode? + + @conditions: Array[WhenNode] + + @predicate: Prism::node? + + # Initialize a new CaseNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[WhenNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? predicate, Array[WhenNode] conditions, ElseNode? else_clause, Location case_keyword_loc, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> CaseNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?predicate: Prism::node?, ?conditions: Array[WhenNode], ?else_clause: ElseNode?, ?case_keyword_loc: Location, ?end_keyword_loc: Location) -> CaseNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :case_node + def type: () -> :case_node + + # See `Node.type`. + # -- + # : () -> :case_node + def self.type: () -> :case_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # predicate -> Node | nil + # + # Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; when false; end + # ^^^^ + # -- + # : () -> Prism::node? + def predicate: () -> Prism::node? + + # :call-seq: + # conditions -> Array[WhenNode] + # + # Represents the conditions of the case statement. + # + # case true; when false; end + # ^^^^^^^^^^ + # -- + # : () -> Array[WhenNode] + def conditions: () -> Array[WhenNode] + + # :call-seq: + # else_clause -> ElseNode | nil + # + # Represents the else clause of the case statement. + # + # case true; when false; else; end + # ^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :category: Locations + # :call-seq: + # case_keyword_loc -> Location + # + # Represents the Location of the `case` keyword. + # + # case true; when false; end + # ^^^^ + # -- + # : () -> Location + def case_keyword_loc: () -> Location + + # :category: Repository + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_case_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Represents the Location of the `end` keyword. + # + # case true; when false; end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # case_keyword -> String + # + # Slice the location of case_keyword_loc from the source. + # -- + # : () -> String + def case_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a class declaration involving the `class` keyword. + # + # class Foo end + # ^^^^^^^^^^^^^ + class ClassNode < Node + @name: Symbol + + @end_keyword_loc: Location + + @body: (StatementsNode | BeginNode)? + + @superclass: Prism::node? + + @inheritance_operator_loc: Location? + + @constant_path: ConstantReadNode | ConstantPathNode | CallNode + + @class_keyword_loc: Location + + @locals: Array[Symbol] + + # Initialize a new ClassNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, (ConstantReadNode | ConstantPathNode | CallNode) constant_path, Location? inheritance_operator_loc, Prism::node? superclass, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, ConstantReadNode | ConstantPathNode | CallNode constant_path, Location? inheritance_operator_loc, Prism::node? superclass, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | CallNode), ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | CallNode, ?inheritance_operator_loc: Location?, ?superclass: Prism::node?, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ClassNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_node + def type: () -> :class_node + + # See `Node.type`. + # -- + # : () -> :class_node + def self.type: () -> :class_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # class_keyword_loc -> Location + # + # Represents the Location of the `class` keyword. + # + # class Foo end + # ^^^^^ + # -- + # : () -> Location + def class_keyword_loc: () -> Location + + # :category: Repository + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_class_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # constant_path -> ConstantReadNode | ConstantPathNode | CallNode + # + # Returns the `constant_path` attribute. + # -- + # : () -> (ConstantReadNode | ConstantPathNode | CallNode) + def constant_path: () -> (ConstantReadNode | ConstantPathNode | CallNode) + + # :category: Locations + # :call-seq: + # inheritance_operator_loc -> Location | nil + # + # Represents the Location of the `<` operator. + # + # class Foo < Bar + # ^ + # -- + # : () -> Location? + def inheritance_operator_loc: () -> Location? + + # :category: Repository + # Save the inheritance_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_inheritance_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # superclass -> Node | nil + # + # Represents the superclass of the class. + # + # class Foo < Bar + # ^^^ + # -- + # : () -> Prism::node? + def superclass: () -> Prism::node? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Represents the body of the class. + # + # class Foo + # foo + # ^^^ + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Represents the Location of the `end` keyword. + # + # class Foo end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # name -> Symbol + # + # The name of the class. + # + # class Foo end # name `:Foo` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # class_keyword -> String + # + # Slice the location of class_keyword_loc from the source. + # -- + # : () -> String + def class_keyword: () -> String + + # :call-seq: + # inheritance_operator -> String | nil + # + # Slice the location of inheritance_operator_loc from the source. + # -- + # : () -> String? + def inheritance_operator: () -> String? + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator for assignment to a class variable. + # + # @@target &&= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_and_write_node + def type: () -> :class_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_and_write_node + def self.type: () -> :class_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@target &&= value # name `:@@target` + # ^^^^^^^^ + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Represents the Location of the variable name. + # + # @@target &&= value + # ^^^^^^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Represents the Location of the `&&=` operator. + # + # @@target &&= value + # ^^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @@target &&= value + # ^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to a class variable using an operator that isn't `=`. + # + # @@target += value + # ^^^^^^^^^^^^^^^^^ + class ClassVariableOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ClassVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_operator_write_node + def type: () -> :class_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_operator_write_node + def self.type: () -> :class_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator for assignment to a class variable. + # + # @@target ||= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ClassVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_or_write_node + def type: () -> :class_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_or_write_node + def self.type: () -> :class_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents referencing a class variable. + # + # @@foo + # ^^^^^ + class ClassVariableReadNode < Node + @name: Symbol + + # Initialize a new ClassVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_read_node + def type: () -> :class_variable_read_node + + # See `Node.type`. + # -- + # : () -> :class_variable_read_node + def self.type: () -> :class_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc # name `:@@abc` + # + # @@_test # name `:@@_test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a class variable in a context that doesn't have an explicit value. + # + # @@foo, @@bar = baz + # ^^^^^ ^^^^^ + class ClassVariableTargetNode < Node + @name: Symbol + + # Initialize a new ClassVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ClassVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_target_node + def type: () -> :class_variable_target_node + + # See `Node.type`. + # -- + # : () -> :class_variable_target_node + def self.type: () -> :class_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a class variable. + # + # @@foo = 1 + # ^^^^^^^^^ + class ClassVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new ClassVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ClassVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ClassVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :class_variable_write_node + def type: () -> :class_variable_write_node + + # See `Node.type`. + # -- + # : () -> :class_variable_write_node + def self.type: () -> :class_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc = 123 # name `@@abc` + # + # @@_test = :test # name `@@_test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the variable name. + # + # @@foo = :bar + # ^^^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # The value to write to the class variable. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @@foo = :bar + # ^^^^ + # + # @@_xyz = 123 + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # @@foo = :bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator for assignment to a constant. + # + # Target &&= value + # ^^^^^^^^^^^^^^^^ + class ConstantAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_and_write_node + def type: () -> :constant_and_write_node + + # See `Node.type`. + # -- + # : () -> :constant_and_write_node + def self.type: () -> :constant_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to a constant using an operator that isn't `=`. + # + # Target += value + # ^^^^^^^^^^^^^^^ + class ConstantOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_operator_write_node + def type: () -> :constant_operator_write_node + + # See `Node.type`. + # -- + # : () -> :constant_operator_write_node + def self.type: () -> :constant_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator for assignment to a constant. + # + # Target ||= value + # ^^^^^^^^^^^^^^^^ + class ConstantOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> ConstantOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_or_write_node + def type: () -> :constant_or_write_node + + # See `Node.type`. + # -- + # : () -> :constant_or_write_node + def self.type: () -> :constant_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator for assignment to a constant path. + # + # Parent::Child &&= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_and_write_node + def type: () -> :constant_path_and_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_and_write_node + def self.type: () -> :constant_path_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # Returns the `target` attribute. + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents accessing a constant through a path of `::` operators. + # + # Foo::Bar + # ^^^^^^^^ + class ConstantPathNode < Node + @name_loc: Location + + @delimiter_loc: Location + + @name: Symbol? + + @parent: Prism::node? + + # Initialize a new ConstantPathNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_node + def type: () -> :constant_path_node + + # See `Node.type`. + # -- + # : () -> :constant_path_node + def self.type: () -> :constant_path_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # parent -> Node | nil + # + # The left-hand node of the path, if present. It can be `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It will be `nil` when the constant lookup is at the root of the module tree. + # + # Foo::Bar + # ^^^ + # + # self::Test + # ^^^^ + # + # a.b::C + # ^^^ + # -- + # : () -> Prism::node? + def parent: () -> Prism::node? + + # :call-seq: + # name -> Symbol | nil + # + # The name of the constant being accessed. This could be `nil` in the event of a syntax error. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # delimiter_loc -> Location + # + # The Location of the `::` delimiter. + # + # ::Foo + # ^^ + # + # One::Two + # ^^ + # -- + # : () -> Location + def delimiter_loc: () -> Location + + # :category: Repository + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_delimiter_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the name of the constant. + # + # ::Foo + # ^^^ + # + # One::Two + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # delimiter -> String + # + # Slice the location of delimiter_loc from the source. + # -- + # : () -> String + def delimiter: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to a constant path using an operator that isn't `=`. + # + # Parent::Child += value + # ^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> ConstantPathOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_operator_write_node + def type: () -> :constant_path_operator_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_operator_write_node + def self.type: () -> :constant_path_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # Returns the `target` attribute. + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator for assignment to a constant path. + # + # Parent::Child ||= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_or_write_node + def type: () -> :constant_path_or_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_or_write_node + def self.type: () -> :constant_path_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # Returns the `target` attribute. + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a constant path in a context that doesn't have an explicit value. + # + # Foo::Foo, Bar::Bar = baz + # ^^^^^^^^ ^^^^^^^^ + class ConstantPathTargetNode < Node + @name_loc: Location + + @delimiter_loc: Location + + @name: Symbol? + + @parent: Prism::node? + + # Initialize a new ConstantPathTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? parent, Symbol? name, Location delimiter_loc, Location name_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?parent: Prism::node?, ?name: Symbol?, ?delimiter_loc: Location, ?name_loc: Location) -> ConstantPathTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_target_node + def type: () -> :constant_path_target_node + + # See `Node.type`. + # -- + # : () -> :constant_path_target_node + def self.type: () -> :constant_path_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # parent -> Node | nil + # + # Returns the `parent` attribute. + # -- + # : () -> Prism::node? + def parent: () -> Prism::node? + + # :call-seq: + # name -> Symbol | nil + # + # Returns the `name` attribute. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # delimiter_loc -> Location + # + # Returns the Location represented by `delimiter_loc`. + # -- + # : () -> Location + def delimiter_loc: () -> Location + + # :category: Repository + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_delimiter_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # delimiter -> String + # + # Slice the location of delimiter_loc from the source. + # -- + # : () -> String + def delimiter: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a constant path. + # + # ::Foo = 1 + # ^^^^^^^^^ + # + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # ::Foo::Bar = 1 + # ^^^^^^^^^^^^^^ + class ConstantPathWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @target: ConstantPathNode + + # Initialize a new ConstantPathWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantPathNode target, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantPathWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?target: ConstantPathNode, ?operator_loc: Location, ?value: Prism::node) -> ConstantPathWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_path_write_node + def type: () -> :constant_path_write_node + + # See `Node.type`. + # -- + # : () -> :constant_path_write_node + def self.type: () -> :constant_path_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # target -> ConstantPathNode + # + # A node representing the constant path being written to. + # + # Foo::Bar = 1 + # ^^^^^^^^ + # + # ::Foo = :abc + # ^^^^^ + # -- + # : () -> ConstantPathNode + def target: () -> ConstantPathNode + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # ::ABC = 123 + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # The value to write to the constant path. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # FOO::BAR = :abc + # ^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents referencing a constant. + # + # Foo + # ^^^ + class ConstantReadNode < Node + @name: Symbol + + # Initialize a new ConstantReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_read_node + def type: () -> :constant_read_node + + # See `Node.type`. + # -- + # : () -> :constant_read_node + def self.type: () -> :constant_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # X # name `:X` + # + # SOME_CONSTANT # name `:SOME_CONSTANT` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a constant in a context that doesn't have an explicit value. + # + # Foo, Bar = baz + # ^^^ ^^^ + class ConstantTargetNode < Node + @name: Symbol + + # Initialize a new ConstantTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> ConstantTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_target_node + def type: () -> :constant_target_node + + # See `Node.type`. + # -- + # : () -> :constant_target_node + def self.type: () -> :constant_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a constant. + # + # Foo = 1 + # ^^^^^^^ + class ConstantWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new ConstantWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ConstantWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> ConstantWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :constant_write_node + def type: () -> :constant_write_node + + # See `Node.type`. + # -- + # : () -> :constant_write_node + def self.type: () -> :constant_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # Foo = :bar # name `:Foo` + # + # XYZ = 1 # name `:XYZ` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the constant name. + # + # FOO = 1 + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # The value to write to the constant. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # FOO = :bar + # ^^^^ + # + # MyClass = Class.new + # ^^^^^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # FOO = :bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a method definition. + # + # def method + # end + # ^^^^^^^^^^ + class DefNode < Node + @end_keyword_loc: Location? + + @equal_loc: Location? + + @rparen_loc: Location? + + @lparen_loc: Location? + + @operator_loc: Location? + + @def_keyword_loc: Location + + @locals: Array[Symbol] + + @body: (StatementsNode | BeginNode)? + + @parameters: ParametersNode? + + @receiver: Prism::node? + + @name_loc: Location + + @name: Symbol + + # Initialize a new DefNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node? receiver, ParametersNode? parameters, (StatementsNode | BeginNode)? body, Array[Symbol] locals, Location def_keyword_loc, Location? operator_loc, Location? lparen_loc, Location? rparen_loc, Location? equal_loc, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node? receiver, ParametersNode? parameters, (StatementsNode | BeginNode)? body, Array[Symbol] locals, Location def_keyword_loc, Location? operator_loc, Location? lparen_loc, Location? rparen_loc, Location? equal_loc, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> DefNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?receiver: Prism::node?, ?parameters: ParametersNode?, ?body: (StatementsNode | BeginNode)?, ?locals: Array[Symbol], ?def_keyword_loc: Location, ?operator_loc: Location?, ?lparen_loc: Location?, ?rparen_loc: Location?, ?equal_loc: Location?, ?end_keyword_loc: Location?) -> DefNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :def_node + def type: () -> :def_node + + # See `Node.type`. + # -- + # : () -> :def_node + def self.type: () -> :def_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :call-seq: + # parameters -> ParametersNode | nil + # + # Returns the `parameters` attribute. + # -- + # : () -> ParametersNode? + def parameters: () -> ParametersNode? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # def_keyword_loc -> Location + # + # Returns the Location represented by `def_keyword_loc`. + # -- + # : () -> Location + def def_keyword_loc: () -> Location + + # :category: Repository + # Save the def_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_def_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location | nil + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location? + def operator_loc: () -> Location? + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # equal_loc -> Location | nil + # + # Returns the Location represented by `equal_loc`. + # -- + # : () -> Location? + def equal_loc: () -> Location? + + # :category: Repository + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_equal_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # def_keyword -> String + # + # Slice the location of def_keyword_loc from the source. + # -- + # : () -> String + def def_keyword: () -> String + + # :call-seq: + # operator -> String | nil + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String? + def operator: () -> String? + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # :call-seq: + # equal -> String | nil + # + # Slice the location of equal_loc from the source. + # -- + # : () -> String? + def equal: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `defined?` keyword. + # + # defined?(a) + # ^^^^^^^^^^^ + class DefinedNode < Node + @keyword_loc: Location + + @rparen_loc: Location? + + @value: Prism::node + + @lparen_loc: Location? + + # Initialize a new DefinedNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? lparen_loc, Prism::node value, Location? rparen_loc, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? lparen_loc, Prism::node value, Location? rparen_loc, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> DefinedNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?lparen_loc: Location?, ?value: Prism::node, ?rparen_loc: Location?, ?keyword_loc: Location) -> DefinedNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :defined_node + def type: () -> :defined_node + + # See `Node.type`. + # -- + # : () -> :defined_node + def self.type: () -> :defined_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an `else` clause in a `case`, `if`, or `unless` statement. + # + # if a then b else c end + # ^^^^^^^^^^ + class ElseNode < Node + @end_keyword_loc: Location? + + @statements: StatementsNode? + + @else_keyword_loc: Location + + # Initialize a new ElseNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location else_keyword_loc, StatementsNode? statements, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location else_keyword_loc, StatementsNode? statements, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ElseNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?else_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location?) -> ElseNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :else_node + def type: () -> :else_node + + # See `Node.type`. + # -- + # : () -> :else_node + def self.type: () -> :else_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # else_keyword_loc -> Location + # + # Returns the Location represented by `else_keyword_loc`. + # -- + # : () -> Location + def else_keyword_loc: () -> Location + + # :category: Repository + # Save the else_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_else_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # else_keyword -> String + # + # Slice the location of else_keyword_loc from the source. + # -- + # : () -> String + def else_keyword: () -> String + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an interpolated set of statements. + # + # "foo #{bar}" + # ^^^^^^ + class EmbeddedStatementsNode < Node + @closing_loc: Location + + @statements: StatementsNode? + + @opening_loc: Location + + # Initialize a new EmbeddedStatementsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, StatementsNode? statements, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, StatementsNode? statements, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> EmbeddedStatementsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?statements: StatementsNode?, ?closing_loc: Location) -> EmbeddedStatementsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :embedded_statements_node + def type: () -> :embedded_statements_node + + # See `Node.type`. + # -- + # : () -> :embedded_statements_node + def self.type: () -> :embedded_statements_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an interpolated variable. + # + # "foo #@bar" + # ^^^^^ + class EmbeddedVariableNode < Node + @variable: InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + + @operator_loc: Location + + # Initialize a new EmbeddedVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) variable) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode variable) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> EmbeddedVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode)) -> EmbeddedVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?variable: InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) -> EmbeddedVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :embedded_variable_node + def type: () -> :embedded_variable_node + + # See `Node.type`. + # -- + # : () -> :embedded_variable_node + def self.type: () -> :embedded_variable_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # variable -> InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode + # + # Returns the `variable` attribute. + # -- + # : () -> (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + def variable: () -> (InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode) + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an `ensure` clause in a `begin` statement. + # + # begin + # foo + # ensure + # ^^^^^^ + # bar + # end + class EnsureNode < Node + @end_keyword_loc: Location + + @statements: StatementsNode? + + @ensure_keyword_loc: Location + + # Initialize a new EnsureNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location ensure_keyword_loc, StatementsNode? statements, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location ensure_keyword_loc, StatementsNode? statements, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> EnsureNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?ensure_keyword_loc: Location, ?statements: StatementsNode?, ?end_keyword_loc: Location) -> EnsureNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :ensure_node + def type: () -> :ensure_node + + # See `Node.type`. + # -- + # : () -> :ensure_node + def self.type: () -> :ensure_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # ensure_keyword_loc -> Location + # + # Returns the Location represented by `ensure_keyword_loc`. + # -- + # : () -> Location + def ensure_keyword_loc: () -> Location + + # :category: Repository + # Save the ensure_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_ensure_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # ensure_keyword -> String + # + # Slice the location of ensure_keyword_loc from the source. + # -- + # : () -> String + def ensure_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the literal `false` keyword. + # + # false + # ^^^^^ + class FalseNode < Node + # Initialize a new FalseNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FalseNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> FalseNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> FalseNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :false_node + def type: () -> :false_node + + # See `Node.type`. + # -- + # : () -> :false_node + def self.type: () -> :false_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a find pattern in pattern matching. + # + # foo in *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + # + # foo in [*bar, baz, *qux] + # ^^^^^^^^^^^^^^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^^^^^^^^^^^^^^^^^ + # + # foo => *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + class FindPatternNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @right: SplatNode | MissingNode + + @requireds: Array[Prism::node] + + @left: SplatNode + + @constant: (ConstantPathNode | ConstantReadNode)? + + # Initialize a new FindPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, SplatNode left, Array[Prism::node] requireds, (SplatNode | MissingNode) right, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, SplatNode left, Array[Prism::node] requireds, SplatNode | MissingNode right, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FindPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: (SplatNode | MissingNode), ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?left: SplatNode, ?requireds: Array[Prism::node], ?right: SplatNode | MissingNode, ?opening_loc: Location?, ?closing_loc: Location?) -> FindPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :find_pattern_node + def type: () -> :find_pattern_node + + # See `Node.type`. + # -- + # : () -> :find_pattern_node + def self.type: () -> :find_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # constant -> ConstantPathNode | ConstantReadNode | nil + # + # Represents the optional constant preceding the pattern + # + # foo in Foo(*bar, baz, *qux) + # ^^^ + # -- + # : () -> (ConstantPathNode | ConstantReadNode)? + def constant: () -> (ConstantPathNode | ConstantReadNode)? + + # :call-seq: + # left -> SplatNode + # + # Represents the first wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + # -- + # : () -> SplatNode + def left: () -> SplatNode + + # :call-seq: + # requireds -> Array[Node] + # + # Represents the nodes in between the wildcards. + # + # foo in *bar, baz, *qux + # ^^^ + # + # foo in Foo(*bar, baz, 1, *qux) + # ^^^^^^ + # -- + # : () -> Array[Prism::node] + def requireds: () -> Array[Prism::node] + + # :call-seq: + # right -> SplatNode | MissingNode + # + # Represents the second wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + # -- + # : () -> (SplatNode | MissingNode) + def right: () -> (SplatNode | MissingNode) + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # The Location of the opening brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # The Location of the closing brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `..` or `...` operators to create flip flops. + # + # baz if foo .. bar + # ^^^^^^^^^^ + class FlipFlopNode < Node + @operator_loc: Location + + @right: Prism::node? + + @left: Prism::node? + + # Initialize a new FlipFlopNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FlipFlopNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> FlipFlopNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :flip_flop_node + def type: () -> :flip_flop_node + + # See `Node.type`. + # -- + # : () -> :flip_flop_node + def self.type: () -> :flip_flop_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # ... operator + # -- + # : () -> bool + def exclude_end?: () -> bool + + # :call-seq: + # left -> Node | nil + # + # Returns the `left` attribute. + # -- + # : () -> Prism::node? + def left: () -> Prism::node? + + # :call-seq: + # right -> Node | nil + # + # Returns the `right` attribute. + # -- + # : () -> Prism::node? + def right: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a floating point number literal. + # + # 1.0 + # ^^^ + class FloatNode < Node + @value: Float + + # Initialize a new FloatNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Float value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Float value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> FloatNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Float) -> FloatNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :float_node + def type: () -> :float_node + + # See `Node.type`. + # -- + # : () -> :float_node + def self.type: () -> :float_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Float + # + # The value of the floating point number as a Float. + # -- + # : () -> Float + def value: () -> Float + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `for` keyword. + # + # for i in a end + # ^^^^^^^^^^^^^^ + class ForNode < Node + @end_keyword_loc: Location + + @do_keyword_loc: Location? + + @in_keyword_loc: Location + + @for_keyword_loc: Location + + @statements: StatementsNode? + + @collection: Prism::node + + @index: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode + + # Initialize a new ForNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode) index, Prism::node collection, StatementsNode? statements, Location for_keyword_loc, Location in_keyword_loc, Location? do_keyword_loc, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode index, Prism::node collection, StatementsNode? statements, Location for_keyword_loc, Location in_keyword_loc, Location? do_keyword_loc, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?index: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode), ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?index: LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode, ?collection: Prism::node, ?statements: StatementsNode?, ?for_keyword_loc: Location, ?in_keyword_loc: Location, ?do_keyword_loc: Location?, ?end_keyword_loc: Location) -> ForNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :for_node + def type: () -> :for_node + + # See `Node.type`. + # -- + # : () -> :for_node + def self.type: () -> :for_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # index -> LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode + # + # The index expression for `for` loops. + # + # for i in a end + # ^ + # -- + # : () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode) + def index: () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode) + + # :call-seq: + # collection -> Node + # + # The collection to iterate over. + # + # for i in a end + # ^ + # -- + # : () -> Prism::node + def collection: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Represents the body of statements to execute for each iteration of the loop. + # + # for i in a + # foo(i) + # ^^^^^^ + # end + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # for_keyword_loc -> Location + # + # The Location of the `for` keyword. + # + # for i in a end + # ^^^ + # -- + # : () -> Location + def for_keyword_loc: () -> Location + + # :category: Repository + # Save the for_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_for_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # in_keyword_loc -> Location + # + # The Location of the `in` keyword. + # + # for i in a end + # ^^ + # -- + # : () -> Location + def in_keyword_loc: () -> Location + + # :category: Repository + # Save the in_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_in_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # do_keyword_loc -> Location | nil + # + # The Location of the `do` keyword, if present. + # + # for i in a do end + # ^^ + # -- + # : () -> Location? + def do_keyword_loc: () -> Location? + + # :category: Repository + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_do_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # The Location of the `end` keyword. + # + # for i in a end + # ^^^ + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # for_keyword -> String + # + # Slice the location of for_keyword_loc from the source. + # -- + # : () -> String + def for_keyword: () -> String + + # :call-seq: + # in_keyword -> String + # + # Slice the location of in_keyword_loc from the source. + # -- + # : () -> String + def in_keyword: () -> String + + # :call-seq: + # do_keyword -> String | nil + # + # Slice the location of do_keyword_loc from the source. + # -- + # : () -> String? + def do_keyword: () -> String? + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents forwarding all arguments to this method to another method. + # + # def foo(...) + # bar(...) + # ^^^ + # end + class ForwardingArgumentsNode < Node + # Initialize a new ForwardingArgumentsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForwardingArgumentsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ForwardingArgumentsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingArgumentsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :forwarding_arguments_node + def type: () -> :forwarding_arguments_node + + # See `Node.type`. + # -- + # : () -> :forwarding_arguments_node + def self.type: () -> :forwarding_arguments_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the forwarding parameter in a method, block, or lambda declaration. + # + # def foo(...) + # ^^^ + # end + class ForwardingParameterNode < Node + # Initialize a new ForwardingParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForwardingParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ForwardingParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ForwardingParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :forwarding_parameter_node + def type: () -> :forwarding_parameter_node + + # See `Node.type`. + # -- + # : () -> :forwarding_parameter_node + def self.type: () -> :forwarding_parameter_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `super` keyword without parentheses or arguments, but which might have a block. + # + # super + # ^^^^^ + # + # super { 123 } + # ^^^^^^^^^^^^^ + # + # If it has any other arguments, it would be a `SuperNode` instead. + class ForwardingSuperNode < Node + @block: BlockNode? + + # Initialize a new ForwardingSuperNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, BlockNode? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, BlockNode? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ForwardingSuperNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?block: BlockNode?) -> ForwardingSuperNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :forwarding_super_node + def type: () -> :forwarding_super_node + + # See `Node.type`. + # -- + # : () -> :forwarding_super_node + def self.type: () -> :forwarding_super_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # block -> BlockNode | nil + # + # All other arguments are forwarded as normal, except the original block is replaced with the new block. + # -- + # : () -> BlockNode? + def block: () -> BlockNode? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator for assignment to a global variable. + # + # $target &&= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_and_write_node + def type: () -> :global_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_and_write_node + def self.type: () -> :global_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to a global variable using an operator that isn't `=`. + # + # $target += value + # ^^^^^^^^^^^^^^^^ + class GlobalVariableOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> GlobalVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_operator_write_node + def type: () -> :global_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_operator_write_node + def self.type: () -> :global_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator for assignment to a global variable. + # + # $target ||= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> GlobalVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_or_write_node + def type: () -> :global_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_or_write_node + def self.type: () -> :global_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents referencing a global variable. + # + # $foo + # ^^^^ + class GlobalVariableReadNode < Node + @name: Symbol + + # Initialize a new GlobalVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_read_node + def type: () -> :global_variable_read_node + + # See `Node.type`. + # -- + # : () -> :global_variable_read_node + def self.type: () -> :global_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo # name `:$foo` + # + # $_Test # name `:$_Test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a global variable in a context that doesn't have an explicit value. + # + # $foo, $bar = baz + # ^^^^ ^^^^ + class GlobalVariableTargetNode < Node + @name: Symbol + + # Initialize a new GlobalVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> GlobalVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_target_node + def type: () -> :global_variable_target_node + + # See `Node.type`. + # -- + # : () -> :global_variable_target_node + def self.type: () -> :global_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a global variable. + # + # $foo = 1 + # ^^^^^^^^ + class GlobalVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new GlobalVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> GlobalVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> GlobalVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :global_variable_write_node + def type: () -> :global_variable_write_node + + # See `Node.type`. + # -- + # : () -> :global_variable_write_node + def self.type: () -> :global_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo = :bar # name `:$foo` + # + # $_Test = 123 # name `:$_Test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the global variable's name. + # + # $foo = :bar + # ^^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # The value to write to the global variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # $foo = :bar + # ^^^^ + # + # $-xyz = 123 + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # $foo = :bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a hash literal. + # + # { a => b } + # ^^^^^^^^^^ + class HashNode < Node + @closing_loc: Location + + @elements: Array[AssocNode | AssocSplatNode] + + @opening_loc: Location + + # Initialize a new HashNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[AssocNode | AssocSplatNode] elements, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[AssocNode | AssocSplatNode] elements, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> HashNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?elements: Array[AssocNode | AssocSplatNode], ?closing_loc: Location) -> HashNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :hash_node + def type: () -> :hash_node + + # See `Node.type`. + # -- + # : () -> :hash_node + def self.type: () -> :hash_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # The Location of the opening brace. + # + # { a => b } + # ^ + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # elements -> Array[AssocNode | AssocSplatNode] + # + # The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s. + # + # { a: b } + # ^^^^ + # + # { **foo } + # ^^^^^ + # -- + # : () -> Array[AssocNode | AssocSplatNode] + def elements: () -> Array[AssocNode | AssocSplatNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # The Location of the closing brace. + # + # { a => b } + # ^ + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a hash pattern in pattern matching. + # + # foo => { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + # + # foo => { a: 1, b: 2, **c } + # ^^^^^^^^^^^^^^^^^^^ + # + # foo => Bar[a: 1, b: 2] + # ^^^^^^^^^^^^^^^ + # + # foo in { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + class HashPatternNode < Node + @closing_loc: Location? + + @opening_loc: Location? + + @rest: (AssocSplatNode | NoKeywordsParameterNode)? + + @elements: Array[AssocNode] + + @constant: (ConstantPathNode | ConstantReadNode)? + + # Initialize a new HashPatternNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[AssocNode] elements, (AssocSplatNode | NoKeywordsParameterNode)? rest, Location? opening_loc, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, (ConstantPathNode | ConstantReadNode)? constant, Array[AssocNode] elements, (AssocSplatNode | NoKeywordsParameterNode)? rest, Location? opening_loc, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> HashPatternNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?constant: (ConstantPathNode | ConstantReadNode)?, ?elements: Array[AssocNode], ?rest: (AssocSplatNode | NoKeywordsParameterNode)?, ?opening_loc: Location?, ?closing_loc: Location?) -> HashPatternNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :hash_pattern_node + def type: () -> :hash_pattern_node + + # See `Node.type`. + # -- + # : () -> :hash_pattern_node + def self.type: () -> :hash_pattern_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # constant -> ConstantPathNode | ConstantReadNode | nil + # + # Represents the optional constant preceding the Hash. + # + # foo => Bar[a: 1, b: 2] + # ^^^ + # + # foo => Bar::Baz[a: 1, b: 2] + # ^^^^^^^^ + # -- + # : () -> (ConstantPathNode | ConstantReadNode)? + def constant: () -> (ConstantPathNode | ConstantReadNode)? + + # :call-seq: + # elements -> Array[AssocNode] + # + # Represents the explicit named hash keys and values. + # + # foo => { a: 1, b:, ** } + # ^^^^^^^^ + # -- + # : () -> Array[AssocNode] + def elements: () -> Array[AssocNode] + + # :call-seq: + # rest -> AssocSplatNode | NoKeywordsParameterNode | nil + # + # Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`. + # + # foo => { a: 1, b:, **c } + # ^^^ + # + # foo => { a: 1, b:, ** } + # ^^ + # + # foo => { a: 1, b:, **nil } + # ^^^^^ + # -- + # : () -> (AssocSplatNode | NoKeywordsParameterNode)? + def rest: () -> (AssocSplatNode | NoKeywordsParameterNode)? + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # The Location of the opening brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # The Location of the closing brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `if` keyword, either in the block form or the modifier form, or a ternary expression. + # + # bar if foo + # ^^^^^^^^^^ + # + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + class IfNode < Node + @end_keyword_loc: Location? + + @subsequent: (ElseNode | IfNode)? + + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @predicate: Prism::node + + @if_keyword_loc: Location? + + # Initialize a new IfNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? if_keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, (ElseNode | IfNode)? subsequent, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? if_keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, (ElseNode | IfNode)? subsequent, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IfNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?if_keyword_loc: Location?, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: (ElseNode | IfNode)?, ?end_keyword_loc: Location?) -> IfNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :if_node + def type: () -> :if_node + + # See `Node.type`. + # -- + # : () -> :if_node + def self.type: () -> :if_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # if_keyword_loc -> Location | nil + # + # The Location of the `if` keyword if present. + # + # bar if foo + # ^^ + # + # The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression. + # -- + # : () -> Location? + def if_keyword_loc: () -> Location? + + # :category: Repository + # Save the if_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_if_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # predicate -> Node + # + # The node for the condition the `IfNode` is testing. + # + # if foo + # ^^^ + # bar + # end + # + # bar if foo + # ^^^ + # + # foo ? bar : baz + # ^^^ + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # The Location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. + # + # if foo then bar end + # ^^^^ + # + # a ? b : c + # ^ + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Represents the body of statements that will be executed when the predicate is evaluated as truthy. Will be `nil` when no body is provided. + # + # if foo + # bar + # ^^^ + # baz + # ^^^ + # end + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # subsequent -> ElseNode | IfNode | nil + # + # Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement. + # + # if foo + # bar + # elsif baz + # ^^^^^^^^^ + # qux + # ^^^ + # end + # ^^^ + # + # if foo then bar else baz end + # ^^^^^^^^^^^^ + # -- + # : () -> (ElseNode | IfNode)? + def subsequent: () -> (ElseNode | IfNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # The Location of the `end` keyword if present, `nil` otherwise. + # + # if foo + # bar + # end + # ^^^ + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # if_keyword -> String | nil + # + # Slice the location of if_keyword_loc from the source. + # -- + # : () -> String? + def if_keyword: () -> String? + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an imaginary number literal. + # + # 1.0i + # ^^^^ + class ImaginaryNode < Node + @numeric: FloatNode | IntegerNode | RationalNode + + # Initialize a new ImaginaryNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (FloatNode | IntegerNode | RationalNode) numeric) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, FloatNode | IntegerNode | RationalNode numeric) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ImaginaryNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: (FloatNode | IntegerNode | RationalNode)) -> ImaginaryNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?numeric: FloatNode | IntegerNode | RationalNode) -> ImaginaryNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :imaginary_node + def type: () -> :imaginary_node + + # See `Node.type`. + # -- + # : () -> :imaginary_node + def self.type: () -> :imaginary_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # numeric -> FloatNode | IntegerNode | RationalNode + # + # Returns the `numeric` attribute. + # -- + # : () -> (FloatNode | IntegerNode | RationalNode) + def numeric: () -> (FloatNode | IntegerNode | RationalNode) + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source. + # + # { foo: } + # ^^^^ + # + # { Foo: } + # ^^^^ + # + # foo in { bar: } + # ^^^^ + class ImplicitNode < Node + @value: LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode + + # Initialize a new ImplicitNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ImplicitNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode)) -> ImplicitNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) -> ImplicitNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :implicit_node + def type: () -> :implicit_node + + # See `Node.type`. + # -- + # : () -> :implicit_node + def self.type: () -> :implicit_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode + # + # Returns the `value` attribute. + # -- + # : () -> (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) + def value: () -> (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents using a trailing comma to indicate an implicit rest parameter. + # + # foo { |bar,| } + # ^ + # + # foo in [bar,] + # ^ + # + # for foo, in bar do end + # ^ + # + # foo, = bar + # ^ + class ImplicitRestNode < Node + # Initialize a new ImplicitRestNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ImplicitRestNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ImplicitRestNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ImplicitRestNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :implicit_rest_node + def type: () -> :implicit_rest_node + + # See `Node.type`. + # -- + # : () -> :implicit_rest_node + def self.type: () -> :implicit_rest_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `in` keyword in a case statement. + # + # case a; in b then c end + # ^^^^^^^^^^^ + class InNode < Node + @then_loc: Location? + + @in_loc: Location + + @statements: StatementsNode? + + @pattern: Prism::node + + # Initialize a new InNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node pattern, StatementsNode? statements, Location in_loc, Location? then_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node pattern, StatementsNode? statements, Location in_loc, Location? then_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?pattern: Prism::node, ?statements: StatementsNode?, ?in_loc: Location, ?then_loc: Location?) -> InNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :in_node + def type: () -> :in_node + + # See `Node.type`. + # -- + # : () -> :in_node + def self.type: () -> :in_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # pattern -> Node + # + # Returns the `pattern` attribute. + # -- + # : () -> Prism::node + def pattern: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # in_loc -> Location + # + # Returns the Location represented by `in_loc`. + # -- + # : () -> Location + def in_loc: () -> Location + + # :category: Repository + # Save the in_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_in_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # then_loc -> Location | nil + # + # Returns the Location represented by `then_loc`. + # -- + # : () -> Location? + def then_loc: () -> Location? + + # :category: Repository + # Save the then_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # in -> String + # + # Slice the location of in_loc from the source. + # -- + # : () -> String + def in: () -> String + + # :call-seq: + # then -> String | nil + # + # Slice the location of then_loc from the source. + # -- + # : () -> String? + def then: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator on a call to the `[]` method. + # + # foo.bar[baz] &&= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new IndexAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_and_write_node + def type: () -> :index_and_write_node + + # See `Node.type`. + # -- + # : () -> :index_and_write_node + def self.type: () -> :index_and_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Returns the Location represented by `call_operator_loc`. + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of an assignment operator on a call to `[]`. + # + # foo.bar[baz] += value + # ^^^^^^^^^^^^^^^^^^^^^ + class IndexOperatorWriteNode < Node + @value: Prism::node + + @binary_operator_loc: Location + + @binary_operator: Symbol + + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new IndexOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Symbol binary_operator, Location binary_operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?binary_operator: Symbol, ?binary_operator_loc: Location, ?value: Prism::node) -> IndexOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_operator_write_node + def type: () -> :index_operator_write_node + + # See `Node.type`. + # -- + # : () -> :index_operator_write_node + def self.type: () -> :index_operator_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Returns the Location represented by `call_operator_loc`. + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator on a call to `[]`. + # + # foo.bar[baz] ||= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @call_operator_loc: Location? + + @receiver: Prism::node? + + # Initialize a new IndexOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? receiver, Location? call_operator_loc, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node?, ?call_operator_loc: Location?, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?, ?operator_loc: Location, ?value: Prism::node) -> IndexOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_or_write_node + def type: () -> :index_or_write_node + + # See `Node.type`. + # -- + # : () -> :index_or_write_node + def self.type: () -> :index_or_write_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node | nil + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node? + def receiver: () -> Prism::node? + + # :category: Locations + # :call-seq: + # call_operator_loc -> Location | nil + # + # Returns the Location represented by `call_operator_loc`. + # -- + # : () -> Location? + def call_operator_loc: () -> Location? + + # :category: Repository + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_call_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # call_operator -> String | nil + # + # Slice the location of call_operator_loc from the source. + # -- + # : () -> String? + def call_operator: () -> String? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to an index. + # + # foo[bar], = 1 + # ^^^^^^^^ + # + # begin + # rescue => foo[bar] + # ^^^^^^^^ + # end + # + # for foo[bar] in baz do end + # ^^^^^^^^ + class IndexTargetNode < Node + @block: BlockArgumentNode? + + @closing_loc: Location + + @arguments: ArgumentsNode? + + @opening_loc: Location + + @receiver: Prism::node + + # Initialize a new IndexTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node receiver, Location opening_loc, ArgumentsNode? arguments, Location closing_loc, BlockArgumentNode? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IndexTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?receiver: Prism::node, ?opening_loc: Location, ?arguments: ArgumentsNode?, ?closing_loc: Location, ?block: BlockArgumentNode?) -> IndexTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :index_target_node + def type: () -> :index_target_node + + # See `Node.type`. + # -- + # : () -> :index_target_node + def self.type: () -> :index_target_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # &. operator + # -- + # : () -> bool + def safe_navigation?: () -> bool + + # :category: Flags + # a call that could have been a local variable + # -- + # : () -> bool + def variable_call?: () -> bool + + # :category: Flags + # a call that is an attribute write, so the value being written should be returned + # -- + # : () -> bool + def attribute_write?: () -> bool + + # :category: Flags + # a call that ignores method visibility + # -- + # : () -> bool + def ignore_visibility?: () -> bool + + # :call-seq: + # receiver -> Node + # + # Returns the `receiver` attribute. + # -- + # : () -> Prism::node + def receiver: () -> Prism::node + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # block -> BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> BlockArgumentNode? + def block: () -> BlockArgumentNode? + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator for assignment to an instance variable. + # + # @target &&= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableAndWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_and_write_node + def type: () -> :instance_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_and_write_node + def self.type: () -> :instance_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to an instance variable using an operator that isn't `=`. + # + # @target += value + # ^^^^^^^^^^^^^^^^ + class InstanceVariableOperatorWriteNode < Node + @binary_operator: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol binary_operator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?binary_operator: Symbol) -> InstanceVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_operator_write_node + def type: () -> :instance_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_operator_write_node + def self.type: () -> :instance_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator for assignment to an instance variable. + # + # @target ||= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableOrWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> InstanceVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_or_write_node + def type: () -> :instance_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_or_write_node + def self.type: () -> :instance_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents referencing an instance variable. + # + # @foo + # ^^^^ + class InstanceVariableReadNode < Node + @name: Symbol + + # Initialize a new InstanceVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_read_node + def type: () -> :instance_variable_read_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_read_node + def self.type: () -> :instance_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x # name `:@x` + # + # @_test # name `:@_test` + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to an instance variable in a context that doesn't have an explicit value. + # + # @foo, @bar = baz + # ^^^^ ^^^^ + class InstanceVariableTargetNode < Node + @name: Symbol + + # Initialize a new InstanceVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> InstanceVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_target_node + def type: () -> :instance_variable_target_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_target_node + def self.type: () -> :instance_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to an instance variable. + # + # @foo = 1 + # ^^^^^^^^ + class InstanceVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new InstanceVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InstanceVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> InstanceVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :instance_variable_write_node + def type: () -> :instance_variable_write_node + + # See `Node.type`. + # -- + # : () -> :instance_variable_write_node + def self.type: () -> :instance_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x = :y # name `:@x` + # + # @_foo = "bar" # name `@_foo` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the variable name. + # + # @_x = 1 + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # The value to write to the instance variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @foo = :bar + # ^^^^ + # + # @_x = 1234 + # ^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # @x = y + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an integer number literal. + # + # 1 + # ^ + class IntegerNode < Node + @value: Integer + + # Initialize a new IntegerNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> IntegerNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Integer) -> IntegerNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :integer_node + def type: () -> :integer_node + + # See `Node.type`. + # -- + # : () -> :integer_node + def self.type: () -> :integer_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # 0b prefix + # -- + # : () -> bool + def binary?: () -> bool + + # :category: Flags + # 0d or no prefix + # -- + # : () -> bool + def decimal?: () -> bool + + # :category: Flags + # 0o or 0 prefix + # -- + # : () -> bool + def octal?: () -> bool + + # :category: Flags + # 0x prefix + # -- + # : () -> bool + def hexadecimal?: () -> bool + + # :call-seq: + # value -> Integer + # + # The value of the integer literal as a number. + # -- + # : () -> Integer + def value: () -> Integer + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo #{bar} baz/ then end + # ^^^^^^^^^^^^^^^^ + class InterpolatedMatchLastLineNode < Node + @closing_loc: Location + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location + + # Initialize a new InterpolatedMatchLastLineNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedMatchLastLineNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedMatchLastLineNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_match_last_line_node + def type: () -> :interpolated_match_last_line_node + + # See `Node.type`. + # -- + # : () -> :interpolated_match_last_line_node + def self.type: () -> :interpolated_match_last_line_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a regular expression literal that contains interpolation. + # + # /foo #{bar} baz/ + # ^^^^^^^^^^^^^^^^ + class InterpolatedRegularExpressionNode < Node + @closing_loc: Location + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location + + # Initialize a new InterpolatedRegularExpressionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedRegularExpressionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedRegularExpressionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_regular_expression_node + def type: () -> :interpolated_regular_expression_node + + # See `Node.type`. + # -- + # : () -> :interpolated_regular_expression_node + def self.type: () -> :interpolated_regular_expression_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a string literal that contains interpolation. + # + # "foo #{bar} baz" + # ^^^^^^^^^^^^^^^^ + class InterpolatedStringNode < Node + @closing_loc: Location? + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + + @opening_loc: Location? + + # Initialize a new InterpolatedStringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] parts, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] parts, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedStringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode], ?closing_loc: Location?) -> InterpolatedStringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_string_node + def type: () -> :interpolated_string_node + + # See `Node.type`. + # -- + # : () -> :interpolated_string_node + def self.type: () -> :interpolated_string_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + # -- + # : () -> bool + def frozen?: () -> bool + + # :category: Flags + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + # -- + # : () -> bool + def mutable?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode | InterpolatedStringNode | XStringNode | InterpolatedXStringNode | SymbolNode | InterpolatedSymbolNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a symbol literal that contains interpolation. + # + # :"foo #{bar} baz" + # ^^^^^^^^^^^^^^^^^ + class InterpolatedSymbolNode < Node + @closing_loc: Location? + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location? + + # Initialize a new InterpolatedSymbolNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location? closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location? closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedSymbolNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location?) -> InterpolatedSymbolNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_symbol_node + def type: () -> :interpolated_symbol_node + + # See `Node.type`. + # -- + # : () -> :interpolated_symbol_node + def self.type: () -> :interpolated_symbol_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an xstring literal that contains interpolation. + # + # `foo #{bar} baz` + # ^^^^^^^^^^^^^^^^ + class InterpolatedXStringNode < Node + @closing_loc: Location + + @parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + @opening_loc: Location + + # Initialize a new InterpolatedXStringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] parts, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> InterpolatedXStringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?parts: Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode], ?closing_loc: Location) -> InterpolatedXStringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :interpolated_x_string_node + def type: () -> :interpolated_x_string_node + + # See `Node.type`. + # -- + # : () -> :interpolated_x_string_node + def self.type: () -> :interpolated_x_string_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parts -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + # + # Returns the `parts` attribute. + # -- + # : () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + def parts: () -> Array[StringNode | EmbeddedStatementsNode | EmbeddedVariableNode] + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents reading from the implicit `it` local variable. + # + # -> { it } + # ^^ + class ItLocalVariableReadNode < Node + # Initialize a new ItLocalVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ItLocalVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ItLocalVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ItLocalVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :it_local_variable_read_node + def type: () -> :it_local_variable_read_node + + # See `Node.type`. + # -- + # : () -> :it_local_variable_read_node + def self.type: () -> :it_local_variable_read_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda. + # + # -> { it + it } + # ^^^^^^^^^^^^^^ + class ItParametersNode < Node + # Initialize a new ItParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ItParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> ItParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> ItParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :it_parameters_node + def type: () -> :it_parameters_node + + # See `Node.type`. + # -- + # : () -> :it_parameters_node + def self.type: () -> :it_parameters_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a hash literal without opening and closing braces. + # + # foo(a: b) + # ^^^^ + class KeywordHashNode < Node + @elements: Array[AssocNode | AssocSplatNode] + + # Initialize a new KeywordHashNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[AssocNode | AssocSplatNode] elements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[AssocNode | AssocSplatNode] elements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> KeywordHashNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?elements: Array[AssocNode | AssocSplatNode]) -> KeywordHashNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :keyword_hash_node + def type: () -> :keyword_hash_node + + # See `Node.type`. + # -- + # : () -> :keyword_hash_node + def self.type: () -> :keyword_hash_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + # -- + # : () -> bool + def symbol_keys?: () -> bool + + # :call-seq: + # elements -> Array[AssocNode | AssocSplatNode] + # + # Returns the `elements` attribute. + # -- + # : () -> Array[AssocNode | AssocSplatNode] + def elements: () -> Array[AssocNode | AssocSplatNode] + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a keyword rest parameter to a method, block, or lambda definition. + # + # def a(**b) + # ^^^ + # end + class KeywordRestParameterNode < Node + @operator_loc: Location + + @name_loc: Location? + + @name: Symbol? + + # Initialize a new KeywordRestParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> KeywordRestParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> KeywordRestParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :keyword_rest_parameter_node + def type: () -> :keyword_rest_parameter_node + + # See `Node.type`. + # -- + # : () -> :keyword_rest_parameter_node + def self.type: () -> :keyword_rest_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol | nil + # + # Returns the `name` attribute. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # name_loc -> Location | nil + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location? + def name_loc: () -> Location? + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_name_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents using a lambda literal (not the lambda method call). + # + # ->(value) { value * 2 } + # ^^^^^^^^^^^^^^^^^^^^^^^ + class LambdaNode < Node + @body: (StatementsNode | BeginNode)? + + @parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + @closing_loc: Location + + @opening_loc: Location + + @operator_loc: Location + + @locals: Array[Symbol] + + # Initialize a new LambdaNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location operator_loc, Location opening_loc, Location closing_loc, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location operator_loc, Location opening_loc, Location closing_loc, (BlockParametersNode | NumberedParametersNode | ItParametersNode)? parameters, (StatementsNode | BeginNode)? body) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LambdaNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?operator_loc: Location, ?opening_loc: Location, ?closing_loc: Location, ?parameters: (BlockParametersNode | NumberedParametersNode | ItParametersNode)?, ?body: (StatementsNode | BeginNode)?) -> LambdaNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :lambda_node + def type: () -> :lambda_node + + # See `Node.type`. + # -- + # : () -> :lambda_node + def self.type: () -> :lambda_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # parameters -> BlockParametersNode | NumberedParametersNode | ItParametersNode | nil + # + # Returns the `parameters` attribute. + # -- + # : () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + def parameters: () -> (BlockParametersNode | NumberedParametersNode | ItParametersNode)? + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `&&=` operator for assignment to a local variable. + # + # target &&= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableAndWriteNode < Node + @depth: Integer + + @name: Symbol + + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + # Initialize a new LocalVariableAndWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableAndWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableAndWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_and_write_node + def type: () -> :local_variable_and_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_and_write_node + def self.type: () -> :local_variable_and_write_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents assigning to a local variable using an operator that isn't `=`. + # + # target += value + # ^^^^^^^^^^^^^^^ + class LocalVariableOperatorWriteNode < Node + @depth: Integer + + @binary_operator: Symbol + + @name: Symbol + + @value: Prism::node + + @binary_operator_loc: Location + + @name_loc: Location + + # Initialize a new LocalVariableOperatorWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol name, Symbol binary_operator, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location binary_operator_loc, Prism::node value, Symbol name, Symbol binary_operator, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableOperatorWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?binary_operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?binary_operator: Symbol, ?depth: Integer) -> LocalVariableOperatorWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_operator_write_node + def type: () -> :local_variable_operator_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_operator_write_node + def self.type: () -> :local_variable_operator_write_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # binary_operator_loc -> Location + # + # Returns the Location represented by `binary_operator_loc`. + # -- + # : () -> Location + def binary_operator_loc: () -> Location + + # :category: Repository + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_binary_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # binary_operator -> Symbol + # + # Returns the `binary_operator` attribute. + # -- + # : () -> Symbol + def binary_operator: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||=` operator for assignment to a local variable. + # + # target ||= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableOrWriteNode < Node + @depth: Integer + + @name: Symbol + + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + # Initialize a new LocalVariableOrWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location name_loc, Location operator_loc, Prism::node value, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableOrWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node, ?name: Symbol, ?depth: Integer) -> LocalVariableOrWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_or_write_node + def type: () -> :local_variable_or_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_or_write_node + def self.type: () -> :local_variable_or_write_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call. + # + # foo + # ^^^ + class LocalVariableReadNode < Node + @depth: Integer + + @name: Symbol + + # Initialize a new LocalVariableReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_read_node + def type: () -> :local_variable_read_node + + # See `Node.type`. + # -- + # : () -> :local_variable_read_node + def self.type: () -> :local_variable_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # x # name `:x` + # + # _Test # name `:_Test` + # + # Note that this can also be an underscore followed by a number for the default block parameters. + # + # _1 # name `:_1` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # The number of visible scopes that should be searched to find the origin of this local variable. + # + # foo = 1; foo # depth 0 + # + # bar = 2; tap { bar } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + # -- + # : () -> Integer + def depth: () -> Integer + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a local variable in a context that doesn't have an explicit value. + # + # foo, bar = baz + # ^^^ ^^^ + # + # foo => baz + # ^^^ + class LocalVariableTargetNode < Node + @depth: Integer + + @name: Symbol + + # Initialize a new LocalVariableTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer) -> LocalVariableTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_target_node + def type: () -> :local_variable_target_node + + # See `Node.type`. + # -- + # : () -> :local_variable_target_node + def self.type: () -> :local_variable_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # Returns the `depth` attribute. + # -- + # : () -> Integer + def depth: () -> Integer + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing to a local variable. + # + # foo = 1 + # ^^^^^^^ + class LocalVariableWriteNode < Node + @operator_loc: Location + + @value: Prism::node + + @name_loc: Location + + @depth: Integer + + @name: Symbol + + # Initialize a new LocalVariableWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth, Location name_loc, Prism::node value, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Integer depth, Location name_loc, Prism::node value, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> LocalVariableWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?depth: Integer, ?name_loc: Location, ?value: Prism::node, ?operator_loc: Location) -> LocalVariableWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :local_variable_write_node + def type: () -> :local_variable_write_node + + # See `Node.type`. + # -- + # : () -> :local_variable_write_node + def self.type: () -> :local_variable_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # name -> Symbol + # + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # foo = :bar # name `:foo` + # + # abc = 123 # name `:abc` + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # depth -> Integer + # + # The number of semantic scopes we have to traverse to find the declaration of this variable. + # + # foo = 1 # depth 0 + # + # tap { foo = 1 } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + # -- + # : () -> Integer + def depth: () -> Integer + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # The Location of the variable name. + # + # foo = :bar + # ^^^ + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # The value to write to the local variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo = :bar + # ^^^^ + # + # abc = 1234 + # ^^^^ + # + # Note that since the name of a local variable is known before the value is parsed, it is valid for a local variable to appear within the value of its own write. + # + # foo = foo + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `=` operator. + # + # x = :y + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo/i then end + # ^^^^^^ + class MatchLastLineNode < Node + @unescaped: String + + @closing_loc: Location + + @content_loc: Location + + @opening_loc: Location + + # Initialize a new MatchLastLineNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchLastLineNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> MatchLastLineNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_last_line_node + def type: () -> :match_last_line_node + + # See `Node.type`. + # -- + # : () -> :match_last_line_node + def self.type: () -> :match_last_line_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the modifier `in` operator. + # + # foo in bar + # ^^^^^^^^^^ + class MatchPredicateNode < Node + @operator_loc: Location + + @pattern: Prism::node + + @value: Prism::node + + # Initialize a new MatchPredicateNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchPredicateNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchPredicateNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_predicate_node + def type: () -> :match_predicate_node + + # See `Node.type`. + # -- + # : () -> :match_predicate_node + def self.type: () -> :match_predicate_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # pattern -> Node + # + # Returns the `pattern` attribute. + # -- + # : () -> Prism::node + def pattern: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `=>` operator. + # + # foo => bar + # ^^^^^^^^^^ + class MatchRequiredNode < Node + @operator_loc: Location + + @pattern: Prism::node + + @value: Prism::node + + # Initialize a new MatchRequiredNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node value, Prism::node pattern, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchRequiredNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?value: Prism::node, ?pattern: Prism::node, ?operator_loc: Location) -> MatchRequiredNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_required_node + def type: () -> :match_required_node + + # See `Node.type`. + # -- + # : () -> :match_required_node + def self.type: () -> :match_required_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # value -> Node + # + # Represents the left-hand side of the operator. + # + # foo => bar + # ^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # pattern -> Node + # + # Represents the right-hand side of the operator. The type of the node depends on the expression. + # + # Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`. + # + # foo => a # This is equivalent to writing `a = foo` + # ^ + # + # Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant. + # + # foo => [a] + # ^^^ + # + # foo => a, b + # ^^^^ + # + # foo => Bar[a, b] + # ^^^^^^^^^ + # + # If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead. + # + # foo => *, 1, *a + # ^^^^^ + # + # Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`. + # + # foo => { a: 1, b: } + # + # foo => Bar[a: 1, b:] + # + # foo => Bar[**] + # + # To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode` + # + # foo => ^a + # ^^ + # + # Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`. + # + # foo => ^(a + 1) + # + # Anything else will result in the regular node for that expression, for example a `ConstantReadNode`. + # + # foo => CONST + # -- + # : () -> Prism::node + def pattern: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the operator. + # + # foo => bar + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents writing local variables using a regular expression match with named capture groups. + # + # /(?bar)/ =~ baz + # ^^^^^^^^^^^^^^^^^^^^ + class MatchWriteNode < Node + @targets: Array[LocalVariableTargetNode] + + @call: CallNode + + # Initialize a new MatchWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, CallNode call, Array[LocalVariableTargetNode] targets) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, CallNode call, Array[LocalVariableTargetNode] targets) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MatchWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?call: CallNode, ?targets: Array[LocalVariableTargetNode]) -> MatchWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :match_write_node + def type: () -> :match_write_node + + # See `Node.type`. + # -- + # : () -> :match_write_node + def self.type: () -> :match_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # call -> CallNode + # + # Returns the `call` attribute. + # -- + # : () -> CallNode + def call: () -> CallNode + + # :call-seq: + # targets -> Array[LocalVariableTargetNode] + # + # Returns the `targets` attribute. + # -- + # : () -> Array[LocalVariableTargetNode] + def targets: () -> Array[LocalVariableTargetNode] + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a node that is missing from the source and results in a syntax error. + class MissingNode < Node + # Initialize a new MissingNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MissingNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> MissingNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> MissingNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :missing_node + def type: () -> :missing_node + + # See `Node.type`. + # -- + # : () -> :missing_node + def self.type: () -> :missing_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a module declaration involving the `module` keyword. + # + # module Foo end + # ^^^^^^^^^^^^^^ + class ModuleNode < Node + @name: Symbol + + @end_keyword_loc: Location + + @body: (StatementsNode | BeginNode)? + + @constant_path: ConstantReadNode | ConstantPathNode | MissingNode + + @module_keyword_loc: Location + + @locals: Array[Symbol] + + # Initialize a new ModuleNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location module_keyword_loc, (ConstantReadNode | ConstantPathNode | MissingNode) constant_path, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location module_keyword_loc, ConstantReadNode | ConstantPathNode | MissingNode constant_path, (StatementsNode | BeginNode)? body, Location end_keyword_loc, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ModuleNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: (ConstantReadNode | ConstantPathNode | MissingNode), ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?module_keyword_loc: Location, ?constant_path: ConstantReadNode | ConstantPathNode | MissingNode, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location, ?name: Symbol) -> ModuleNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :module_node + def type: () -> :module_node + + # See `Node.type`. + # -- + # : () -> :module_node + def self.type: () -> :module_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # module_keyword_loc -> Location + # + # Returns the Location represented by `module_keyword_loc`. + # -- + # : () -> Location + def module_keyword_loc: () -> Location + + # :category: Repository + # Save the module_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_module_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # constant_path -> ConstantReadNode | ConstantPathNode | MissingNode + # + # Returns the `constant_path` attribute. + # -- + # : () -> (ConstantReadNode | ConstantPathNode | MissingNode) + def constant_path: () -> (ConstantReadNode | ConstantPathNode | MissingNode) + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :call-seq: + # module_keyword -> String + # + # Slice the location of module_keyword_loc from the source. + # -- + # : () -> String + def module_keyword: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a multi-target expression. + # + # a, (b, c) = 1, 2, 3 + # ^^^^^^ + # + # This can be a part of `MultiWriteNode` as above, or the target of a `for` loop + # + # for a, b in [[1, 2], [3, 4]] + # ^^^^ + class MultiTargetNode < Node + @rparen_loc: Location? + + @lparen_loc: Location? + + @rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + @rest: (ImplicitRestNode | SplatNode)? + + @lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # Initialize a new MultiTargetNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MultiTargetNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?) -> MultiTargetNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :multi_target_node + def type: () -> :multi_target_node + + # See `Node.type`. + # -- + # : () -> :multi_target_node + def self.type: () -> :multi_target_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # lefts -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # Represents the targets expressions before a splat node. + # + # a, (b, c, *) = 1, 2, 3, 4, 5 + # ^^^^ + # + # The splat node can be absent, in that case all target expressions are in the left field. + # + # a, (b, c) = 1, 2, 3, 4, 5 + # ^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + def lefts: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :call-seq: + # rest -> ImplicitRestNode | SplatNode | nil + # + # Represents a splat node in the target expression. + # + # a, (b, *c) = 1, 2, 3, 4 + # ^^ + # + # The variable can be empty, this results in a `SplatNode` with a `nil` expression field. + # + # a, (b, *) = 1, 2, 3, 4 + # ^ + # + # If the `*` is omitted, this field will contain an `ImplicitRestNode` + # + # a, (b,) = 1, 2, 3, 4 + # ^ + # -- + # : () -> (ImplicitRestNode | SplatNode)? + def rest: () -> (ImplicitRestNode | SplatNode)? + + # :call-seq: + # rights -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # Represents the targets expressions after a splat node. + # + # a, (*, b, c) = 1, 2, 3, 4, 5 + # ^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + def rights: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | RequiredParameterNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # The Location of the opening parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # The Location of the closing parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a write to a multi-target expression. + # + # a, b, c = 1, 2, 3 + # ^^^^^^^^^^^^^^^^^ + class MultiWriteNode < Node + @value: Prism::node + + @operator_loc: Location + + @rparen_loc: Location? + + @lparen_loc: Location? + + @rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + @rest: (ImplicitRestNode | SplatNode)? + + @lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # Initialize a new MultiWriteNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] lefts, (ImplicitRestNode | SplatNode)? rest, Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] rights, Location? lparen_loc, Location? rparen_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> MultiWriteNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?lefts: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?rest: (ImplicitRestNode | SplatNode)?, ?rights: Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode], ?lparen_loc: Location?, ?rparen_loc: Location?, ?operator_loc: Location, ?value: Prism::node) -> MultiWriteNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :multi_write_node + def type: () -> :multi_write_node + + # See `Node.type`. + # -- + # : () -> :multi_write_node + def self.type: () -> :multi_write_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # lefts -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # Represents the targets expressions before a splat node. + # + # a, b, * = 1, 2, 3, 4, 5 + # ^^^^ + # + # The splat node can be absent, in that case all target expressions are in the left field. + # + # a, b, c = 1, 2, 3, 4, 5 + # ^^^^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + def lefts: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :call-seq: + # rest -> ImplicitRestNode | SplatNode | nil + # + # Represents a splat node in the target expression. + # + # a, b, *c = 1, 2, 3, 4 + # ^^ + # + # The variable can be empty, this results in a `SplatNode` with a `nil` expression field. + # + # a, b, * = 1, 2, 3, 4 + # ^ + # + # If the `*` is omitted, this field will contain an `ImplicitRestNode` + # + # a, b, = 1, 2, 3, 4 + # ^ + # -- + # : () -> (ImplicitRestNode | SplatNode)? + def rest: () -> (ImplicitRestNode | SplatNode)? + + # :call-seq: + # rights -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + # + # Represents the targets expressions after a splat node. + # + # a, *, b, c = 1, 2, 3, 4, 5 + # ^^^^ + # -- + # : () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + def rights: () -> Array[LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | MultiTargetNode | BackReferenceReadNode | NumberedReferenceReadNode] + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # The Location of the opening parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # The Location of the closing parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the operator. + # + # a, b, c = 1, 2, 3 + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # The value to write to the targets. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # a, b, c = 1, 2, 3 + # ^^^^^^^ + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `next` keyword. + # + # next 1 + # ^^^^^^ + class NextNode < Node + @keyword_loc: Location + + @arguments: ArgumentsNode? + + # Initialize a new NextNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ArgumentsNode? arguments, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NextNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?arguments: ArgumentsNode?, ?keyword_loc: Location) -> NextNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :next_node + def type: () -> :next_node + + # See `Node.type`. + # -- + # : () -> :next_node + def self.type: () -> :next_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `nil` keyword. + # + # nil + # ^^^ + class NilNode < Node + # Initialize a new NilNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NilNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> NilNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> NilNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :nil_node + def type: () -> :nil_node + + # See `Node.type`. + # -- + # : () -> :nil_node + def self.type: () -> :nil_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of `&nil` inside method arguments. + # + # def a(&nil) + # ^^^^ + # end + class NoBlockParameterNode < Node + @keyword_loc: Location + + @operator_loc: Location + + # Initialize a new NoBlockParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NoBlockParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoBlockParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :no_block_parameter_node + def type: () -> :no_block_parameter_node + + # See `Node.type`. + # -- + # : () -> :no_block_parameter_node + def self.type: () -> :no_block_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of `**nil` inside method arguments. + # + # def a(**nil) + # ^^^^^ + # end + class NoKeywordsParameterNode < Node + @keyword_loc: Location + + @operator_loc: Location + + # Initialize a new NoKeywordsParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NoKeywordsParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?keyword_loc: Location) -> NoKeywordsParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :no_keywords_parameter_node + def type: () -> :no_keywords_parameter_node + + # See `Node.type`. + # -- + # : () -> :no_keywords_parameter_node + def self.type: () -> :no_keywords_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an implicit set of parameters through the use of numbered parameters within a block or lambda. + # + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + class NumberedParametersNode < Node + @maximum: Integer + + # Initialize a new NumberedParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer maximum) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer maximum) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NumberedParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?maximum: Integer) -> NumberedParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :numbered_parameters_node + def type: () -> :numbered_parameters_node + + # See `Node.type`. + # -- + # : () -> :numbered_parameters_node + def self.type: () -> :numbered_parameters_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # maximum -> Integer + # + # Returns the `maximum` attribute. + # -- + # : () -> Integer + def maximum: () -> Integer + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents reading a numbered reference to a capture in the previous match. + # + # $1 + # ^^ + class NumberedReferenceReadNode < Node + @number: Integer + + # Initialize a new NumberedReferenceReadNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer number) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer number) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> NumberedReferenceReadNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?number: Integer) -> NumberedReferenceReadNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :numbered_reference_read_node + def type: () -> :numbered_reference_read_node + + # See `Node.type`. + # -- + # : () -> :numbered_reference_read_node + def self.type: () -> :numbered_reference_read_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # number -> Integer + # + # The (1-indexed, from the left) number of the capture group. Numbered references that are too large result in this value being `0`. + # + # $1 # number `1` + # + # $5432 # number `5432` + # + # $4294967296 # number `0` + # -- + # : () -> Integer + def number: () -> Integer + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an optional keyword parameter to a method, block, or lambda definition. + # + # def a(b: 1) + # ^^^^ + # end + class OptionalKeywordParameterNode < Node + @value: Prism::node + + @name_loc: Location + + @name: Symbol + + # Initialize a new OptionalKeywordParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> OptionalKeywordParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?value: Prism::node) -> OptionalKeywordParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :optional_keyword_parameter_node + def type: () -> :optional_keyword_parameter_node + + # See `Node.type`. + # -- + # : () -> :optional_keyword_parameter_node + def self.type: () -> :optional_keyword_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an optional parameter to a method, block, or lambda definition. + # + # def a(b = 1) + # ^^^^^ + # end + class OptionalParameterNode < Node + @value: Prism::node + + @operator_loc: Location + + @name_loc: Location + + @name: Symbol + + # Initialize a new OptionalParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc, Location operator_loc, Prism::node value) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> OptionalParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location, ?operator_loc: Location, ?value: Prism::node) -> OptionalParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :optional_parameter_node + def type: () -> :optional_parameter_node + + # See `Node.type`. + # -- + # : () -> :optional_parameter_node + def self.type: () -> :optional_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # value -> Node + # + # Returns the `value` attribute. + # -- + # : () -> Prism::node + def value: () -> Prism::node + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `||` operator or the `or` keyword. + # + # left or right + # ^^^^^^^^^^^^^ + class OrNode < Node + @operator_loc: Location + + @right: Prism::node + + @left: Prism::node + + # Initialize a new OrNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node left, Prism::node right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> OrNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node, ?right: Prism::node, ?operator_loc: Location) -> OrNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :or_node + def type: () -> :or_node + + # See `Node.type`. + # -- + # : () -> :or_node + def self.type: () -> :or_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # left -> Node + # + # Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # left or right + # ^^^^ + # + # 1 || 2 + # ^ + # -- + # : () -> Prism::node + def left: () -> Prism::node + + # :call-seq: + # right -> Node + # + # Represents the right side of the expression. + # + # left || right + # ^^^^^ + # + # 1 or 2 + # ^ + # -- + # : () -> Prism::node + def right: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `or` keyword or the `||` operator. + # + # left or right + # ^^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the list of parameters on a method, block, or lambda definition. + # + # def a(b, c, d) + # ^^^^^^^ + # end + class ParametersNode < Node + @block: (BlockParameterNode | NoBlockParameterNode)? + + @keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? + + @keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + + @posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + + @rest: (RestParameterNode | ImplicitRestNode)? + + @optionals: Array[OptionalParameterNode] + + @requireds: Array[RequiredParameterNode | MultiTargetNode] + + # Initialize a new ParametersNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[RequiredParameterNode | MultiTargetNode] requireds, Array[OptionalParameterNode] optionals, (RestParameterNode | ImplicitRestNode)? rest, Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] posts, Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] keywords, (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? keyword_rest, (BlockParameterNode | NoBlockParameterNode)? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[RequiredParameterNode | MultiTargetNode] requireds, Array[OptionalParameterNode] optionals, (RestParameterNode | ImplicitRestNode)? rest, Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] posts, Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] keywords, (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? keyword_rest, (BlockParameterNode | NoBlockParameterNode)? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ParametersNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?requireds: Array[RequiredParameterNode | MultiTargetNode], ?optionals: Array[OptionalParameterNode], ?rest: (RestParameterNode | ImplicitRestNode)?, ?posts: Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode], ?keywords: Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode], ?keyword_rest: (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)?, ?block: (BlockParameterNode | NoBlockParameterNode)?) -> ParametersNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :parameters_node + def type: () -> :parameters_node + + # See `Node.type`. + # -- + # : () -> :parameters_node + def self.type: () -> :parameters_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # requireds -> Array[RequiredParameterNode | MultiTargetNode] + # + # Returns the `requireds` attribute. + # -- + # : () -> Array[RequiredParameterNode | MultiTargetNode] + def requireds: () -> Array[RequiredParameterNode | MultiTargetNode] + + # :call-seq: + # optionals -> Array[OptionalParameterNode] + # + # Returns the `optionals` attribute. + # -- + # : () -> Array[OptionalParameterNode] + def optionals: () -> Array[OptionalParameterNode] + + # :call-seq: + # rest -> RestParameterNode | ImplicitRestNode | nil + # + # Returns the `rest` attribute. + # -- + # : () -> (RestParameterNode | ImplicitRestNode)? + def rest: () -> (RestParameterNode | ImplicitRestNode)? + + # :call-seq: + # posts -> Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + # + # Returns the `posts` attribute. + # -- + # : () -> Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + def posts: () -> Array[RequiredParameterNode | MultiTargetNode | KeywordRestParameterNode | NoKeywordsParameterNode | ForwardingParameterNode | BlockParameterNode | NoBlockParameterNode] + + # :call-seq: + # keywords -> Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + # + # Returns the `keywords` attribute. + # -- + # : () -> Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + def keywords: () -> Array[RequiredKeywordParameterNode | OptionalKeywordParameterNode] + + # :call-seq: + # keyword_rest -> KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode | nil + # + # Returns the `keyword_rest` attribute. + # -- + # : () -> (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? + def keyword_rest: () -> (KeywordRestParameterNode | ForwardingParameterNode | NoKeywordsParameterNode)? + + # :call-seq: + # block -> BlockParameterNode | NoBlockParameterNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> (BlockParameterNode | NoBlockParameterNode)? + def block: () -> (BlockParameterNode | NoBlockParameterNode)? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a parenthesized expression + # + # (10 + 34) + # ^^^^^^^^^ + class ParenthesesNode < Node + @closing_loc: Location + + @opening_loc: Location + + @body: Prism::node? + + # Initialize a new ParenthesesNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? body, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? body, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ParenthesesNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Prism::node?, ?opening_loc: Location, ?closing_loc: Location) -> ParenthesesNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :parentheses_node + def type: () -> :parentheses_node + + # See `Node.type`. + # -- + # : () -> :parentheses_node + def self.type: () -> :parentheses_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # parentheses that contain multiple potentially void statements + # -- + # : () -> bool + def multiple_statements?: () -> bool + + # :call-seq: + # body -> Node | nil + # + # Returns the `body` attribute. + # -- + # : () -> Prism::node? + def body: () -> Prism::node? + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `^` operator for pinning an expression in a pattern matching expression. + # + # foo in ^(bar) + # ^^^^^^ + class PinnedExpressionNode < Node + @rparen_loc: Location + + @lparen_loc: Location + + @operator_loc: Location + + @expression: Prism::node + + # Initialize a new PinnedExpressionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location operator_loc, Location lparen_loc, Location rparen_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location operator_loc, Location lparen_loc, Location rparen_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PinnedExpressionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?operator_loc: Location, ?lparen_loc: Location, ?rparen_loc: Location) -> PinnedExpressionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :pinned_expression_node + def type: () -> :pinned_expression_node + + # See `Node.type`. + # -- + # : () -> :pinned_expression_node + def self.type: () -> :pinned_expression_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # expression -> Node + # + # The expression used in the pinned expression + # + # foo in ^(bar) + # ^^^ + # -- + # : () -> Prism::node + def expression: () -> Prism::node + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `^` operator + # + # foo in ^(bar) + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # lparen_loc -> Location + # + # The Location of the opening parenthesis. + # + # foo in ^(bar) + # ^ + # -- + # : () -> Location + def lparen_loc: () -> Location + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_lparen_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # rparen_loc -> Location + # + # The Location of the closing parenthesis. + # + # foo in ^(bar) + # ^ + # -- + # : () -> Location + def rparen_loc: () -> Location + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_rparen_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # lparen -> String + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String + def lparen: () -> String + + # :call-seq: + # rparen -> String + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String + def rparen: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `^` operator for pinning a variable in a pattern matching expression. + # + # foo in ^bar + # ^^^^ + class PinnedVariableNode < Node + @operator_loc: Location + + @variable: LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode + + # Initialize a new PinnedVariableNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode) variable, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode variable, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PinnedVariableNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode), ?operator_loc: Location) -> PinnedVariableNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?variable: LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode, ?operator_loc: Location) -> PinnedVariableNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :pinned_variable_node + def type: () -> :pinned_variable_node + + # See `Node.type`. + # -- + # : () -> :pinned_variable_node + def self.type: () -> :pinned_variable_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # variable -> LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode + # + # The variable used in the pinned expression + # + # foo in ^bar + # ^^^ + # -- + # : () -> (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode) + def variable: () -> (LocalVariableReadNode | InstanceVariableReadNode | ClassVariableReadNode | GlobalVariableReadNode | BackReferenceReadNode | NumberedReferenceReadNode | ItLocalVariableReadNode | MissingNode) + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `^` operator + # + # foo in ^bar + # ^ + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `END` keyword. + # + # END { foo } + # ^^^^^^^^^^^ + class PostExecutionNode < Node + @closing_loc: Location + + @opening_loc: Location + + @keyword_loc: Location + + @statements: StatementsNode? + + # Initialize a new PostExecutionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PostExecutionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PostExecutionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :post_execution_node + def type: () -> :post_execution_node + + # See `Node.type`. + # -- + # : () -> :post_execution_node + def self.type: () -> :post_execution_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `BEGIN` keyword. + # + # BEGIN { foo } + # ^^^^^^^^^^^^^ + class PreExecutionNode < Node + @closing_loc: Location + + @opening_loc: Location + + @keyword_loc: Location + + @statements: StatementsNode? + + # Initialize a new PreExecutionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, StatementsNode? statements, Location keyword_loc, Location opening_loc, Location closing_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> PreExecutionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?statements: StatementsNode?, ?keyword_loc: Location, ?opening_loc: Location, ?closing_loc: Location) -> PreExecutionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :pre_execution_node + def type: () -> :pre_execution_node + + # See `Node.type`. + # -- + # : () -> :pre_execution_node + def self.type: () -> :pre_execution_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # The top level node of any parse tree. + class ProgramNode < Node + @statements: StatementsNode + + @locals: Array[Symbol] + + # Initialize a new ProgramNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, StatementsNode statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, StatementsNode statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ProgramNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?statements: StatementsNode) -> ProgramNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :program_node + def type: () -> :program_node + + # See `Node.type`. + # -- + # : () -> :program_node + def self.type: () -> :program_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :call-seq: + # statements -> StatementsNode + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode + def statements: () -> StatementsNode + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `..` or `...` operators. + # + # 1..2 + # ^^^^ + # + # c if a =~ /left/ ... b =~ /right/ + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + class RangeNode < Node + @operator_loc: Location + + @right: Prism::node? + + @left: Prism::node? + + # Initialize a new RangeNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node? left, Prism::node? right, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RangeNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?left: Prism::node?, ?right: Prism::node?, ?operator_loc: Location) -> RangeNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :range_node + def type: () -> :range_node + + # See `Node.type`. + # -- + # : () -> :range_node + def self.type: () -> :range_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # ... operator + # -- + # : () -> bool + def exclude_end?: () -> bool + + # :call-seq: + # left -> Node | nil + # + # The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # 1... + # ^ + # + # hello...goodbye + # ^^^^^ + # -- + # : () -> Prism::node? + def left: () -> Prism::node? + + # :call-seq: + # right -> Node | nil + # + # The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # ..5 + # ^ + # + # 1...foo + # ^^^ + # If neither right-hand or left-hand side was included, this will be a MissingNode. + # -- + # : () -> Prism::node? + def right: () -> Prism::node? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # The Location of the `..` or `...` operator. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a rational number literal. + # + # 1.0r + # ^^^^ + class RationalNode < Node + @denominator: Integer + + @numerator: Integer + + # Initialize a new RationalNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Integer numerator, Integer denominator) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Integer numerator, Integer denominator) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RationalNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?numerator: Integer, ?denominator: Integer) -> RationalNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rational_node + def type: () -> :rational_node + + # See `Node.type`. + # -- + # : () -> :rational_node + def self.type: () -> :rational_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # 0b prefix + # -- + # : () -> bool + def binary?: () -> bool + + # :category: Flags + # 0d or no prefix + # -- + # : () -> bool + def decimal?: () -> bool + + # :category: Flags + # 0o or 0 prefix + # -- + # : () -> bool + def octal?: () -> bool + + # :category: Flags + # 0x prefix + # -- + # : () -> bool + def hexadecimal?: () -> bool + + # :call-seq: + # numerator -> Integer + # + # The numerator of the rational number. + # + # 1.5r # numerator 3 + # -- + # : () -> Integer + def numerator: () -> Integer + + # :call-seq: + # denominator -> Integer + # + # The denominator of the rational number. + # + # 1.5r # denominator 2 + # -- + # : () -> Integer + def denominator: () -> Integer + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `redo` keyword. + # + # redo + # ^^^^ + class RedoNode < Node + # Initialize a new RedoNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RedoNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> RedoNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> RedoNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :redo_node + def type: () -> :redo_node + + # See `Node.type`. + # -- + # : () -> :redo_node + def self.type: () -> :redo_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a regular expression literal with no interpolation. + # + # /foo/i + # ^^^^^^ + class RegularExpressionNode < Node + @unescaped: String + + @closing_loc: Location + + @content_loc: Location + + @opening_loc: Location + + # Initialize a new RegularExpressionNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RegularExpressionNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> RegularExpressionNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :regular_expression_node + def type: () -> :regular_expression_node + + # See `Node.type`. + # -- + # : () -> :regular_expression_node + def self.type: () -> :regular_expression_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # i - ignores the case of characters when matching + # -- + # : () -> bool + def ignore_case?: () -> bool + + # :category: Flags + # x - ignores whitespace and allows comments in regular expressions + # -- + # : () -> bool + def extended?: () -> bool + + # :category: Flags + # m - allows $ to match the end of lines within strings + # -- + # : () -> bool + def multi_line?: () -> bool + + # :category: Flags + # o - only interpolates values into the regular expression once + # -- + # : () -> bool + def once?: () -> bool + + # :category: Flags + # e - forces the EUC-JP encoding + # -- + # : () -> bool + def euc_jp?: () -> bool + + # :category: Flags + # n - forces the ASCII-8BIT encoding + # -- + # : () -> bool + def ascii_8bit?: () -> bool + + # :category: Flags + # s - forces the Windows-31J encoding + # -- + # : () -> bool + def windows_31j?: () -> bool + + # :category: Flags + # u - forces the UTF-8 encoding + # -- + # : () -> bool + def utf_8?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a required keyword parameter to a method, block, or lambda definition. + # + # def a(b: ) + # ^^ + # end + class RequiredKeywordParameterNode < Node + @name_loc: Location + + @name: Symbol + + # Initialize a new RequiredKeywordParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name, Location name_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RequiredKeywordParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol, ?name_loc: Location) -> RequiredKeywordParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :required_keyword_parameter_node + def type: () -> :required_keyword_parameter_node + + # See `Node.type`. + # -- + # : () -> :required_keyword_parameter_node + def self.type: () -> :required_keyword_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # :category: Locations + # :call-seq: + # name_loc -> Location + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location + def name_loc: () -> Location + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_name_loc: (_Repository repository) -> Relocation::Entry + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a required parameter to a method, block, or lambda definition. + # + # def a(b) + # ^ + # end + class RequiredParameterNode < Node + @name: Symbol + + # Initialize a new RequiredParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol name) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RequiredParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol) -> RequiredParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :required_parameter_node + def type: () -> :required_parameter_node + + # See `Node.type`. + # -- + # : () -> :required_parameter_node + def self.type: () -> :required_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol + # + # Returns the `name` attribute. + # -- + # : () -> Symbol + def name: () -> Symbol + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an expression modified with a rescue. + # + # foo rescue nil + # ^^^^^^^^^^^^^^ + class RescueModifierNode < Node + @rescue_expression: Prism::node + + @keyword_loc: Location + + @expression: Prism::node + + # Initialize a new RescueModifierNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location keyword_loc, Prism::node rescue_expression) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Prism::node expression, Location keyword_loc, Prism::node rescue_expression) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RescueModifierNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?expression: Prism::node, ?keyword_loc: Location, ?rescue_expression: Prism::node) -> RescueModifierNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rescue_modifier_node + def type: () -> :rescue_modifier_node + + # See `Node.type`. + # -- + # : () -> :rescue_modifier_node + def self.type: () -> :rescue_modifier_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # expression -> Node + # + # Returns the `expression` attribute. + # -- + # : () -> Prism::node + def expression: () -> Prism::node + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # rescue_expression -> Node + # + # Returns the `rescue_expression` attribute. + # -- + # : () -> Prism::node + def rescue_expression: () -> Prism::node + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a rescue statement. + # + # begin + # rescue Foo, *splat, Bar => ex + # foo + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + # end + # + # `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field. + class RescueNode < Node + @subsequent: RescueNode? + + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? + + @operator_loc: Location? + + @exceptions: Array[Prism::node] + + @keyword_loc: Location + + # Initialize a new RescueNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] exceptions, Location? operator_loc, (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? reference, Location? then_keyword_loc, StatementsNode? statements, RescueNode? subsequent) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] exceptions, Location? operator_loc, (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? reference, Location? then_keyword_loc, StatementsNode? statements, RescueNode? subsequent) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RescueNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?exceptions: Array[Prism::node], ?operator_loc: Location?, ?reference: (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)?, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?subsequent: RescueNode?) -> RescueNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rescue_node + def type: () -> :rescue_node + + # See `Node.type`. + # -- + # : () -> :rescue_node + def self.type: () -> :rescue_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # exceptions -> Array[Node] + # + # Returns the `exceptions` attribute. + # -- + # : () -> Array[Prism::node] + def exceptions: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # operator_loc -> Location | nil + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location? + def operator_loc: () -> Location? + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_operator_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # reference -> LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode | nil + # + # Returns the `reference` attribute. + # -- + # : () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? + def reference: () -> (LocalVariableTargetNode | InstanceVariableTargetNode | ClassVariableTargetNode | GlobalVariableTargetNode | ConstantTargetNode | ConstantPathTargetNode | CallTargetNode | IndexTargetNode | BackReferenceReadNode | NumberedReferenceReadNode | MissingNode)? + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # Returns the Location represented by `then_keyword_loc`. + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # subsequent -> RescueNode | nil + # + # Returns the `subsequent` attribute. + # -- + # : () -> RescueNode? + def subsequent: () -> RescueNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # operator -> String | nil + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String? + def operator: () -> String? + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a rest parameter to a method, block, or lambda definition. + # + # def a(*b) + # ^^ + # end + class RestParameterNode < Node + @operator_loc: Location + + @name_loc: Location? + + @name: Symbol? + + # Initialize a new RestParameterNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Symbol? name, Location? name_loc, Location operator_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RestParameterNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?name: Symbol?, ?name_loc: Location?, ?operator_loc: Location) -> RestParameterNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :rest_parameter_node + def type: () -> :rest_parameter_node + + # See `Node.type`. + # -- + # : () -> :rest_parameter_node + def self.type: () -> :rest_parameter_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a parameter name that has been repeated in the method signature + # -- + # : () -> bool + def repeated_parameter?: () -> bool + + # :call-seq: + # name -> Symbol | nil + # + # Returns the `name` attribute. + # -- + # : () -> Symbol? + def name: () -> Symbol? + + # :category: Locations + # :call-seq: + # name_loc -> Location | nil + # + # Returns the Location represented by `name_loc`. + # -- + # : () -> Location? + def name_loc: () -> Location? + + # :category: Repository + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_name_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `retry` keyword. + # + # retry + # ^^^^^ + class RetryNode < Node + # Initialize a new RetryNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> RetryNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> RetryNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> RetryNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :retry_node + def type: () -> :retry_node + + # See `Node.type`. + # -- + # : () -> :retry_node + def self.type: () -> :retry_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `return` keyword. + # + # return 1 + # ^^^^^^^^ + class ReturnNode < Node + @arguments: ArgumentsNode? + + @keyword_loc: Location + + # Initialize a new ReturnNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, ArgumentsNode? arguments) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, ArgumentsNode? arguments) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ReturnNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?arguments: ArgumentsNode?) -> ReturnNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :return_node + def type: () -> :return_node + + # See `Node.type`. + # -- + # : () -> :return_node + def self.type: () -> :return_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the `self` keyword. + # + # self + # ^^^^ + class SelfNode < Node + # Initialize a new SelfNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SelfNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> SelfNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> SelfNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :self_node + def type: () -> :self_node + + # See `Node.type`. + # -- + # : () -> :self_node + def self.type: () -> :self_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # This node wraps a constant write to indicate that when the value is written, it should have its shareability state modified. + # + # # shareable_constant_value: literal + # C = { a: 1 } + # ^^^^^^^^^^^^ + class ShareableConstantNode < Node + @write: ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode + + # Initialize a new ShareableConstantNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) write) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode write) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> ShareableConstantNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?write: (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode)) -> ShareableConstantNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?write: ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) -> ShareableConstantNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :shareable_constant_node + def type: () -> :shareable_constant_node + + # See `Node.type`. + # -- + # : () -> :shareable_constant_node + def self.type: () -> :shareable_constant_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # constant writes that should be modified with shareable constant value literal + # -- + # : () -> bool + def literal?: () -> bool + + # :category: Flags + # constant writes that should be modified with shareable constant value experimental everything + # -- + # : () -> bool + def experimental_everything?: () -> bool + + # :category: Flags + # constant writes that should be modified with shareable constant value experimental copy + # -- + # : () -> bool + def experimental_copy?: () -> bool + + # :call-seq: + # write -> ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode + # + # The constant write that should be modified with the shareability state. + # -- + # : () -> (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) + def write: () -> (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a singleton class declaration involving the `class` keyword. + # + # class << self end + # ^^^^^^^^^^^^^^^^^ + class SingletonClassNode < Node + @end_keyword_loc: Location + + @body: (StatementsNode | BeginNode)? + + @expression: Prism::node + + @operator_loc: Location + + @class_keyword_loc: Location + + @locals: Array[Symbol] + + # Initialize a new SingletonClassNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, Location operator_loc, Prism::node expression, (StatementsNode | BeginNode)? body, Location end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Symbol] locals, Location class_keyword_loc, Location operator_loc, Prism::node expression, (StatementsNode | BeginNode)? body, Location end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SingletonClassNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?locals: Array[Symbol], ?class_keyword_loc: Location, ?operator_loc: Location, ?expression: Prism::node, ?body: (StatementsNode | BeginNode)?, ?end_keyword_loc: Location) -> SingletonClassNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :singleton_class_node + def type: () -> :singleton_class_node + + # See `Node.type`. + # -- + # : () -> :singleton_class_node + def self.type: () -> :singleton_class_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # locals -> Array[Symbol] + # + # Returns the `locals` attribute. + # -- + # : () -> Array[Symbol] + def locals: () -> Array[Symbol] + + # :category: Locations + # :call-seq: + # class_keyword_loc -> Location + # + # Returns the Location represented by `class_keyword_loc`. + # -- + # : () -> Location + def class_keyword_loc: () -> Location + + # :category: Repository + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_class_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # expression -> Node + # + # Returns the `expression` attribute. + # -- + # : () -> Prism::node + def expression: () -> Prism::node + + # :call-seq: + # body -> StatementsNode | BeginNode | nil + # + # Returns the `body` attribute. + # -- + # : () -> (StatementsNode | BeginNode)? + def body: () -> (StatementsNode | BeginNode)? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location + # + # Returns the Location represented by `end_keyword_loc`. + # -- + # : () -> Location + def end_keyword_loc: () -> Location + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # class_keyword -> String + # + # Slice the location of class_keyword_loc from the source. + # -- + # : () -> String + def class_keyword: () -> String + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # :call-seq: + # end_keyword -> String + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String + def end_keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `__ENCODING__` keyword. + # + # __ENCODING__ + # ^^^^^^^^^^^^ + class SourceEncodingNode < Node + # Initialize a new SourceEncodingNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SourceEncodingNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> SourceEncodingNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceEncodingNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :source_encoding_node + def type: () -> :source_encoding_node + + # See `Node.type`. + # -- + # : () -> :source_encoding_node + def self.type: () -> :source_encoding_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `__FILE__` keyword. + # + # __FILE__ + # ^^^^^^^^ + class SourceFileNode < Node + @filepath: String + + # Initialize a new SourceFileNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, String filepath) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, String filepath) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SourceFileNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?filepath: String) -> SourceFileNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :source_file_node + def type: () -> :source_file_node + + # See `Node.type`. + # -- + # : () -> :source_file_node + def self.type: () -> :source_file_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + # -- + # : () -> bool + def frozen?: () -> bool + + # :category: Flags + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + # -- + # : () -> bool + def mutable?: () -> bool + + # :call-seq: + # filepath -> String + # + # Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism.parse*` APIs. + # -- + # : () -> String + def filepath: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `__LINE__` keyword. + # + # __LINE__ + # ^^^^^^^^ + class SourceLineNode < Node + # Initialize a new SourceLineNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SourceLineNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> SourceLineNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> SourceLineNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :source_line_node + def type: () -> :source_line_node + + # See `Node.type`. + # -- + # : () -> :source_line_node + def self.type: () -> :source_line_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the splat operator. + # + # [*a] + # ^^ + class SplatNode < Node + @expression: Prism::node? + + @operator_loc: Location + + # Initialize a new SplatNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Prism::node? expression) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location operator_loc, Prism::node? expression) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SplatNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?operator_loc: Location, ?expression: Prism::node?) -> SplatNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :splat_node + def type: () -> :splat_node + + # See `Node.type`. + # -- + # : () -> :splat_node + def self.type: () -> :splat_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # operator_loc -> Location + # + # Returns the Location represented by `operator_loc`. + # -- + # : () -> Location + def operator_loc: () -> Location + + # :category: Repository + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_operator_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # expression -> Node | nil + # + # Returns the `expression` attribute. + # -- + # : () -> Prism::node? + def expression: () -> Prism::node? + + # :call-seq: + # operator -> String + # + # Slice the location of operator_loc from the source. + # -- + # : () -> String + def operator: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a set of statements contained within some scope. + # + # foo; bar; baz + # ^^^^^^^^^^^^^ + class StatementsNode < Node + @body: Array[Prism::node] + + # Initialize a new StatementsNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] body) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[Prism::node] body) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> StatementsNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?body: Array[Prism::node]) -> StatementsNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :statements_node + def type: () -> :statements_node + + # See `Node.type`. + # -- + # : () -> :statements_node + def self.type: () -> :statements_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # body -> Array[Node] + # + # Returns the `body` attribute. + # -- + # : () -> Array[Prism::node] + def body: () -> Array[Prism::node] + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string. + # + # "foo" + # ^^^^^ + # + # %w[foo] + # ^^^ + # + # "foo #{bar} baz" + # ^^^^ ^^^^ + class StringNode < Node + @unescaped: String + + @closing_loc: Location? + + @content_loc: Location + + @opening_loc: Location? + + # Initialize a new StringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location content_loc, Location? closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location content_loc, Location? closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> StringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?content_loc: Location, ?closing_loc: Location?, ?unescaped: String) -> StringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :string_node + def type: () -> :string_node + + # See `Node.type`. + # -- + # : () -> :string_node + def self.type: () -> :string_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + # -- + # : () -> bool + def frozen?: () -> bool + + # :category: Flags + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + # -- + # : () -> bool + def mutable?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `super` keyword with parentheses or arguments. + # + # super() + # ^^^^^^^ + # + # super foo, bar + # ^^^^^^^^^^^^^^ + # + # If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead. + class SuperNode < Node + @block: (BlockNode | BlockArgumentNode)? + + @rparen_loc: Location? + + @arguments: ArgumentsNode? + + @lparen_loc: Location? + + @keyword_loc: Location + + # Initialize a new SuperNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc, (BlockNode | BlockArgumentNode)? block) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc, (BlockNode | BlockArgumentNode)? block) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SuperNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?, ?block: (BlockNode | BlockArgumentNode)?) -> SuperNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :super_node + def type: () -> :super_node + + # See `Node.type`. + # -- + # : () -> :super_node + def self.type: () -> :super_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Can be only `nil` when there are empty parentheses, like `super()`. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # block -> BlockNode | BlockArgumentNode | nil + # + # Returns the `block` attribute. + # -- + # : () -> (BlockNode | BlockArgumentNode)? + def block: () -> (BlockNode | BlockArgumentNode)? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents a symbol literal or a symbol contained within a `%i` list. + # + # :foo + # ^^^^ + # + # %i[foo] + # ^^^ + class SymbolNode < Node + @unescaped: String + + @closing_loc: Location? + + @value_loc: Location? + + @opening_loc: Location? + + # Initialize a new SymbolNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location? value_loc, Location? closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location? opening_loc, Location? value_loc, Location? closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> SymbolNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location?, ?value_loc: Location?, ?closing_loc: Location?, ?unescaped: String) -> SymbolNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :symbol_node + def type: () -> :symbol_node + + # See `Node.type`. + # -- + # : () -> :symbol_node + def self.type: () -> :symbol_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to US-ASCII + # -- + # : () -> bool + def forced_us_ascii_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location | nil + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location? + def opening_loc: () -> Location? + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_opening_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # value_loc -> Location | nil + # + # Returns the Location represented by `value_loc`. + # -- + # : () -> Location? + def value_loc: () -> Location? + + # :category: Repository + # Save the value_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_value_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String | nil + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String? + def opening: () -> String? + + # :call-seq: + # value -> String | nil + # + # Slice the location of value_loc from the source. + # -- + # : () -> String? + def value: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the literal `true` keyword. + # + # true + # ^^^^ + class TrueNode < Node + # Initialize a new TrueNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, ) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> TrueNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ) -> TrueNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer) -> TrueNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :true_node + def type: () -> :true_node + + # See `Node.type`. + # -- + # : () -> :true_node + def self.type: () -> :true_node + + # : () -> String + def inspect: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `undef` keyword. + # + # undef :foo, :bar, :baz + # ^^^^^^^^^^^^^^^^^^^^^^ + class UndefNode < Node + @keyword_loc: Location + + @names: Array[SymbolNode | InterpolatedSymbolNode] + + # Initialize a new UndefNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Array[SymbolNode | InterpolatedSymbolNode] names, Location keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Array[SymbolNode | InterpolatedSymbolNode] names, Location keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> UndefNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?names: Array[SymbolNode | InterpolatedSymbolNode], ?keyword_loc: Location) -> UndefNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :undef_node + def type: () -> :undef_node + + # See `Node.type`. + # -- + # : () -> :undef_node + def self.type: () -> :undef_node + + # : () -> String + def inspect: () -> String + + # :call-seq: + # names -> Array[SymbolNode | InterpolatedSymbolNode] + # + # Returns the `names` attribute. + # -- + # : () -> Array[SymbolNode | InterpolatedSymbolNode] + def names: () -> Array[SymbolNode | InterpolatedSymbolNode] + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `unless` keyword, either in the block form or the modifier form. + # + # bar unless foo + # ^^^^^^^^^^^^^^ + # + # unless foo then bar end + # ^^^^^^^^^^^^^^^^^^^^^^^ + class UnlessNode < Node + @end_keyword_loc: Location? + + @else_clause: ElseNode? + + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @predicate: Prism::node + + @keyword_loc: Location + + # Initialize a new UnlessNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, ElseNode? else_clause, Location? end_keyword_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Prism::node predicate, Location? then_keyword_loc, StatementsNode? statements, ElseNode? else_clause, Location? end_keyword_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> UnlessNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?predicate: Prism::node, ?then_keyword_loc: Location?, ?statements: StatementsNode?, ?else_clause: ElseNode?, ?end_keyword_loc: Location?) -> UnlessNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :unless_node + def type: () -> :unless_node + + # See `Node.type`. + # -- + # : () -> :unless_node + def self.type: () -> :unless_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # The Location of the `unless` keyword. + # + # unless cond then bar end + # ^^^^^^ + # + # bar unless cond + # ^^^^^^ + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # predicate -> Node + # + # The condition to be evaluated for the unless expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # unless cond then bar end + # ^^^^ + # + # bar unless cond + # ^^^^ + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # The Location of the `then` keyword, if present. + # + # unless cond then bar end + # ^^^^ + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # The body of statements that will executed if the unless condition is + # falsey. Will be `nil` if no body is provided. + # + # unless cond then bar end + # ^^^ + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # else_clause -> ElseNode | nil + # + # The else clause of the unless expression, if present. + # + # unless cond then bar else baz end + # ^^^^^^^^ + # -- + # : () -> ElseNode? + def else_clause: () -> ElseNode? + + # :category: Locations + # :call-seq: + # end_keyword_loc -> Location | nil + # + # The Location of the `end` keyword, if present. + # + # unless cond then bar end + # ^^^ + # -- + # : () -> Location? + def end_keyword_loc: () -> Location? + + # :category: Repository + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_end_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # :call-seq: + # end_keyword -> String | nil + # + # Slice the location of end_keyword_loc from the source. + # -- + # : () -> String? + def end_keyword: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `until` keyword, either in the block form or the modifier form. + # + # bar until foo + # ^^^^^^^^^^^^^ + # + # until foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class UntilNode < Node + @statements: StatementsNode? + + @predicate: Prism::node + + @closing_loc: Location? + + @do_keyword_loc: Location? + + @keyword_loc: Location + + # Initialize a new UntilNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> UntilNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> UntilNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :until_node + def type: () -> :until_node + + # See `Node.type`. + # -- + # : () -> :until_node + def self.type: () -> :until_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a loop after a begin statement, so the body is executed first before the condition + # -- + # : () -> bool + def begin_modifier?: () -> bool + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # do_keyword_loc -> Location | nil + # + # Returns the Location represented by `do_keyword_loc`. + # -- + # : () -> Location? + def do_keyword_loc: () -> Location? + + # :category: Repository + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_do_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # predicate -> Node + # + # Returns the `predicate` attribute. + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # do_keyword -> String | nil + # + # Slice the location of do_keyword_loc from the source. + # -- + # : () -> String? + def do_keyword: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `when` keyword within a case statement. + # + # case true + # when true + # ^^^^^^^^^ + # end + class WhenNode < Node + @statements: StatementsNode? + + @then_keyword_loc: Location? + + @conditions: Array[Prism::node] + + @keyword_loc: Location + + # Initialize a new WhenNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] conditions, Location? then_keyword_loc, StatementsNode? statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Array[Prism::node] conditions, Location? then_keyword_loc, StatementsNode? statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> WhenNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?conditions: Array[Prism::node], ?then_keyword_loc: Location?, ?statements: StatementsNode?) -> WhenNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :when_node + def type: () -> :when_node + + # See `Node.type`. + # -- + # : () -> :when_node + def self.type: () -> :when_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # conditions -> Array[Node] + # + # Returns the `conditions` attribute. + # -- + # : () -> Array[Prism::node] + def conditions: () -> Array[Prism::node] + + # :category: Locations + # :call-seq: + # then_keyword_loc -> Location | nil + # + # Returns the Location represented by `then_keyword_loc`. + # -- + # : () -> Location? + def then_keyword_loc: () -> Location? + + # :category: Repository + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_then_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # then_keyword -> String | nil + # + # Slice the location of then_keyword_loc from the source. + # -- + # : () -> String? + def then_keyword: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `while` keyword, either in the block form or the modifier form. + # + # bar while foo + # ^^^^^^^^^^^^^ + # + # while foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class WhileNode < Node + @statements: StatementsNode? + + @predicate: Prism::node + + @closing_loc: Location? + + @do_keyword_loc: Location? + + @keyword_loc: Location + + # Initialize a new WhileNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? do_keyword_loc, Location? closing_loc, Prism::node predicate, StatementsNode? statements) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> WhileNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?do_keyword_loc: Location?, ?closing_loc: Location?, ?predicate: Prism::node, ?statements: StatementsNode?) -> WhileNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :while_node + def type: () -> :while_node + + # See `Node.type`. + # -- + # : () -> :while_node + def self.type: () -> :while_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # a loop after a begin statement, so the body is executed first before the condition + # -- + # : () -> bool + def begin_modifier?: () -> bool + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # do_keyword_loc -> Location | nil + # + # Returns the Location represented by `do_keyword_loc`. + # -- + # : () -> Location? + def do_keyword_loc: () -> Location? + + # :category: Repository + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_do_keyword_loc: (_Repository repository) -> Relocation::Entry? + + # :category: Locations + # :call-seq: + # closing_loc -> Location | nil + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location? + def closing_loc: () -> Location? + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_closing_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # predicate -> Node + # + # Returns the `predicate` attribute. + # -- + # : () -> Prism::node + def predicate: () -> Prism::node + + # :call-seq: + # statements -> StatementsNode | nil + # + # Returns the `statements` attribute. + # -- + # : () -> StatementsNode? + def statements: () -> StatementsNode? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # do_keyword -> String | nil + # + # Slice the location of do_keyword_loc from the source. + # -- + # : () -> String? + def do_keyword: () -> String? + + # :call-seq: + # closing -> String | nil + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String? + def closing: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents an xstring literal with no interpolation. + # + # `foo` + # ^^^^^ + class XStringNode < Node + @unescaped: String + + @closing_loc: Location + + @content_loc: Location + + @opening_loc: Location + + # Initialize a new XStringNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location opening_loc, Location content_loc, Location closing_loc, String unescaped) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> XStringNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?opening_loc: Location, ?content_loc: Location, ?closing_loc: Location, ?unescaped: String) -> XStringNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :x_string_node + def type: () -> :x_string_node + + # See `Node.type`. + # -- + # : () -> :x_string_node + def self.type: () -> :x_string_node + + # : () -> String + def inspect: () -> String + + # :category: Flags + # internal bytes forced the encoding to UTF-8 + # -- + # : () -> bool + def forced_utf8_encoding?: () -> bool + + # :category: Flags + # internal bytes forced the encoding to binary + # -- + # : () -> bool + def forced_binary_encoding?: () -> bool + + # :category: Locations + # :call-seq: + # opening_loc -> Location + # + # Returns the Location represented by `opening_loc`. + # -- + # : () -> Location + def opening_loc: () -> Location + + # :category: Repository + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_opening_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # content_loc -> Location + # + # Returns the Location represented by `content_loc`. + # -- + # : () -> Location + def content_loc: () -> Location + + # :category: Repository + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_content_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # closing_loc -> Location + # + # Returns the Location represented by `closing_loc`. + # -- + # : () -> Location + def closing_loc: () -> Location + + # :category: Repository + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_closing_loc: (_Repository repository) -> Relocation::Entry + + # :call-seq: + # unescaped -> String + # + # Returns the `unescaped` attribute. + # -- + # : () -> String + def unescaped: () -> String + + # :call-seq: + # opening -> String + # + # Slice the location of opening_loc from the source. + # -- + # : () -> String + def opening: () -> String + + # :call-seq: + # content -> String + # + # Slice the location of content_loc from the source. + # -- + # : () -> String + def content: () -> String + + # :call-seq: + # closing -> String + # + # Slice the location of closing_loc from the source. + # -- + # : () -> String + def closing: () -> String + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Represents the use of the `yield` keyword. + # + # yield 1 + # ^^^^^^^ + class YieldNode < Node + @rparen_loc: Location? + + @arguments: ArgumentsNode? + + @lparen_loc: Location? + + @keyword_loc: Location + + # Initialize a new YieldNode node. + # -- + # : (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc) -> void + def initialize: (Source source, Integer node_id, Location location, Integer flags, Location keyword_loc, Location? lparen_loc, ArgumentsNode? arguments, Location? rparen_loc) -> void + + # See Node.accept. + # -- + # : (_Visitor visitor) -> untyped + def accept: (_Visitor visitor) -> untyped + + # See Node.child_nodes. + # -- + # : () -> Array[node?] + def child_nodes: () -> Array[node?] + + # See Node.each_child_node. + # -- + # : () { (node) -> void } -> void + # : () -> Enumerator[node, void] + def each_child_node: () { (node) -> void } -> void + | () -> Enumerator[node, void] + + # See Node.compact_child_nodes. + # -- + # : () -> Array[node] + def compact_child_nodes: () -> Array[node] + + # See Node.comment_targets. + # -- + # : () -> Array[node | Location] + def comment_targets: () -> Array[node | Location] + + # :call-seq: + # copy(**fields) -> YieldNode + # + # Creates a copy of self with the given fields, using self as the template. + # -- + # : (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + def copy: (?node_id: Integer, ?location: Location, ?flags: Integer, ?keyword_loc: Location, ?lparen_loc: Location?, ?arguments: ArgumentsNode?, ?rparen_loc: Location?) -> YieldNode + + alias deconstruct child_nodes + + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # See `Node#type`. + # -- + # : () -> :yield_node + def type: () -> :yield_node + + # See `Node.type`. + # -- + # : () -> :yield_node + def self.type: () -> :yield_node + + # : () -> String + def inspect: () -> String + + # :category: Locations + # :call-seq: + # keyword_loc -> Location + # + # Returns the Location represented by `keyword_loc`. + # -- + # : () -> Location + def keyword_loc: () -> Location + + # :category: Repository + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry + def save_keyword_loc: (_Repository repository) -> Relocation::Entry + + # :category: Locations + # :call-seq: + # lparen_loc -> Location | nil + # + # Returns the Location represented by `lparen_loc`. + # -- + # : () -> Location? + def lparen_loc: () -> Location? + + # :category: Repository + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_lparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # arguments -> ArgumentsNode | nil + # + # Returns the `arguments` attribute. + # -- + # : () -> ArgumentsNode? + def arguments: () -> ArgumentsNode? + + # :category: Locations + # :call-seq: + # rparen_loc -> Location | nil + # + # Returns the Location represented by `rparen_loc`. + # -- + # : () -> Location? + def rparen_loc: () -> Location? + + # :category: Repository + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + # -- + # : (_Repository repository) -> Relocation::Entry? + def save_rparen_loc: (_Repository repository) -> Relocation::Entry? + + # :call-seq: + # keyword -> String + # + # Slice the location of keyword_loc from the source. + # -- + # : () -> String + def keyword: () -> String + + # :call-seq: + # lparen -> String | nil + # + # Slice the location of lparen_loc from the source. + # -- + # : () -> String? + def lparen: () -> String? + + # :call-seq: + # rparen -> String | nil + # + # Slice the location of rparen_loc from the source. + # -- + # : () -> String? + def rparen: () -> String? + + # : (untyped other) -> bool + def ===: (untyped other) -> bool + end + + # Flags for arguments nodes. + module ArgumentsNodeFlags + # if the arguments contain forwarding + CONTAINS_FORWARDING: untyped + + # if the arguments contain keywords + CONTAINS_KEYWORDS: untyped + + # if the arguments contain a keyword splat + CONTAINS_KEYWORD_SPLAT: untyped + + # if the arguments contain a splat + CONTAINS_SPLAT: untyped + + # if the arguments contain multiple splats + CONTAINS_MULTIPLE_SPLATS: untyped + end + + # Flags for array nodes. + module ArrayNodeFlags + # if array contains splat nodes + CONTAINS_SPLAT: untyped + end + + # Flags for call nodes. + module CallNodeFlags + # &. operator + SAFE_NAVIGATION: untyped + + # a call that could have been a local variable + VARIABLE_CALL: untyped + + # a call that is an attribute write, so the value being written should be returned + ATTRIBUTE_WRITE: untyped + + # a call that ignores method visibility + IGNORE_VISIBILITY: untyped + end + + # Flags for nodes that have unescaped content. + module EncodingFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + end + + # Flags for integer nodes that correspond to the base of the integer. + module IntegerBaseFlags + # 0b prefix + BINARY: untyped + + # 0d or no prefix + DECIMAL: untyped + + # 0o or 0 prefix + OCTAL: untyped + + # 0x prefix + HEXADECIMAL: untyped + end + + # Flags for interpolated string nodes that indicated mutability if they are also marked as literals. + module InterpolatedStringNodeFlags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + FROZEN: untyped + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + MUTABLE: untyped + end + + # Flags for keyword hash nodes. + module KeywordHashNodeFlags + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + SYMBOL_KEYS: untyped + end + + # Flags for while and until loop nodes. + module LoopFlags + # a loop after a begin statement, so the body is executed first before the condition + BEGIN_MODIFIER: untyped + end + + # Flags for parameter nodes. + module ParameterFlags + # a parameter name that has been repeated in the method signature + REPEATED_PARAMETER: untyped + end + + # Flags for parentheses nodes. + module ParenthesesNodeFlags + # parentheses that contain multiple potentially void statements + MULTIPLE_STATEMENTS: untyped + end + + # Flags for range and flip-flop nodes. + module RangeFlags + # ... operator + EXCLUDE_END: untyped + end + + # Flags for regular expression and match last line nodes. + module RegularExpressionFlags + # i - ignores the case of characters when matching + IGNORE_CASE: untyped + + # x - ignores whitespace and allows comments in regular expressions + EXTENDED: untyped + + # m - allows $ to match the end of lines within strings + MULTI_LINE: untyped + + # o - only interpolates values into the regular expression once + ONCE: untyped + + # e - forces the EUC-JP encoding + EUC_JP: untyped + + # n - forces the ASCII-8BIT encoding + ASCII_8BIT: untyped + + # s - forces the Windows-31J encoding + WINDOWS_31J: untyped + + # u - forces the UTF-8 encoding + UTF_8: untyped + + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING: untyped + end + + # Flags for shareable constant nodes. + module ShareableConstantNodeFlags + # constant writes that should be modified with shareable constant value literal + LITERAL: untyped + + # constant writes that should be modified with shareable constant value experimental everything + EXPERIMENTAL_EVERYTHING: untyped + + # constant writes that should be modified with shareable constant value experimental copy + EXPERIMENTAL_COPY: untyped + end + + # Flags for string nodes. + module StringFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + FROZEN: untyped + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + MUTABLE: untyped + end + + # Flags for symbol nodes. + module SymbolFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING: untyped + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING: untyped + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING: untyped + end + + # The flags that are common to all nodes. + module NodeFlags + # A flag to indicate that the node is a candidate to emit a :line event + # through tracepoint when compiled. + NEWLINE: ::Integer + + # A flag to indicate that the value that the node represents is a value that + # can be determined at parse-time. + STATIC_LITERAL: ::Integer + end +end diff --git a/sig/generated/prism/node_ext.rbs b/sig/generated/prism/node_ext.rbs new file mode 100644 index 0000000000..273e591eb8 --- /dev/null +++ b/sig/generated/prism/node_ext.rbs @@ -0,0 +1,387 @@ +# Generated from lib/prism/node_ext.rb with RBS::Inline + +# -- +# Here we are reopening the prism module to provide methods on nodes that aren't +# templated and are meant as convenience methods. +# ++ +module Prism + class Node + # : (*String replacements) -> void + def deprecated: (*String replacements) -> void + end + + module RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : (Integer flags) -> Integer + def self.options: (Integer flags) -> Integer + end + + class InterpolatedMatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + class InterpolatedRegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + class MatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + class RegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + # -- + # : () -> Integer + def options: () -> Integer + end + + module HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : (String? opening) -> bool? + def self.heredoc?: (String? opening) -> bool? + end + + class InterpolatedStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + end + + class InterpolatedXStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + end + + class StringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + # -- + # : () -> InterpolatedStringNode + def to_interpolated: () -> InterpolatedStringNode + end + + class XStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + # -- + # : () -> bool? + def heredoc?: () -> bool? + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + # -- + # : () -> InterpolatedXStringNode + def to_interpolated: () -> InterpolatedXStringNode + end + + class ImaginaryNode < Node + # Returns the value of the node as a Ruby Complex. + # -- + # : () -> Complex + def value: () -> Complex + end + + class RationalNode < Node + # Returns the value of the node as a Ruby Rational. + # -- + # : () -> Rational + def value: () -> Rational + + # Returns the value of the node as an IntegerNode or a FloatNode. This + # method is deprecated in favor of #value or #numerator/#denominator. + # -- + # : () -> (IntegerNode | FloatNode) + def numeric: () -> (IntegerNode | FloatNode) + end + + class ConstantReadNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant. For example: "Foo" + # -- + # : () -> String + def full_name: () -> String + end + + class ConstantWriteNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant. For example: "Foo" + # -- + # : () -> String + def full_name: () -> String + end + + class ConstantPathNode < Node + # An error class raised when dynamic parts are found while computing a + # constant path's full name. For example: + # Foo::Bar::Baz -> does not raise because all parts of the constant path are + # simple constants + # var::Bar::Baz -> raises because the first part of the constant path is a + # local variable + class DynamicPartsInConstantPathError < StandardError + end + + # An error class raised when missing nodes are found while computing a + # constant path's full name. For example: + # Foo:: -> raises because the constant path is missing the last part + class MissingNodesInConstantPathError < StandardError + end + + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant path. For example: "Foo::Bar" + # -- + # : () -> String + def full_name: () -> String + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + # -- + # : () -> (ConstantReadNode | MissingNode) + def child: () -> (ConstantReadNode | MissingNode) + end + + class ConstantPathTargetNode < Node + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant path. For example: "Foo::Bar" + # -- + # : () -> String + def full_name: () -> String + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + # -- + # : () -> (ConstantReadNode | MissingNode) + def child: () -> (ConstantReadNode | MissingNode) + end + + class ConstantTargetNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + # -- + # : () -> Array[Symbol] + def full_name_parts: () -> Array[Symbol] + + # Returns the full name of this constant. For example: "Foo" + # -- + # : () -> String + def full_name: () -> String + end + + class ParametersNode < Node + # Mirrors the Method#parameters method. + # -- + # : () -> Array[[Symbol, Symbol] | [Symbol]] + def signature: () -> Array[[ Symbol, Symbol ] | [ Symbol ]] + end + + class CallNode < Node + # When a call node has the attribute_write flag set, it means that the call + # is using the attribute write syntax. This is either a method call to []= + # or a method call to a method that ends with =. Either way, the = sign is + # present in the source. + # + # Prism returns the message_loc _without_ the = sign attached, because there + # can be any amount of space between the message and the = sign. However, + # sometimes you want the location of the full message including the inner + # space and the = sign. This method provides that. + # -- + # : () -> Location? + def full_message_loc: () -> Location? + end + + class CallOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class ClassVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class ConstantOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class ConstantPathOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class GlobalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class IndexOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class InstanceVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class LocalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + # -- + # : () -> Symbol + def operator: () -> Symbol + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + # -- + # : () -> Location + def operator_loc: () -> Location + end + + class CaseMatchNode < Node + # Returns the else clause of the case match node. This method is deprecated + # in favor of #else_clause. + # -- + # : () -> ElseNode? + def consequent: () -> ElseNode? + end + + class CaseNode < Node + # Returns the else clause of the case node. This method is deprecated in + # favor of #else_clause. + # -- + # : () -> ElseNode? + def consequent: () -> ElseNode? + end + + class IfNode < Node + # Returns the subsequent if/elsif/else clause of the if node. This method is + # deprecated in favor of #subsequent. + # -- + # : () -> (IfNode | ElseNode)? + def consequent: () -> (IfNode | ElseNode)? + end + + class RescueNode < Node + # Returns the subsequent rescue clause of the rescue node. This method is + # deprecated in favor of #subsequent. + # -- + # : () -> RescueNode? + def consequent: () -> RescueNode? + end + + class UnlessNode < Node + # Returns the else clause of the unless node. This method is deprecated in + # favor of #else_clause. + # -- + # : () -> ElseNode? + def consequent: () -> ElseNode? + end +end diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs new file mode 100644 index 0000000000..96b1665d06 --- /dev/null +++ b/sig/generated/prism/parse_result.rbs @@ -0,0 +1,811 @@ +# Generated from lib/prism/parse_result.rb with RBS::Inline + +module Prism + # An internal interface for a cache that can be used to compute code + # units from byte offsets. + interface _CodeUnitsCache + def []: (Integer byte_offset) -> Integer + end + + # This represents a source of Ruby code that has been parsed. It is used in + # conjunction with locations to allow them to resolve line numbers and source + # ranges. + class Source + # Create a new source object with the given source code. This method should + # be used instead of `new` and it will return either a `Source` or a + # specialized and more performant `ASCIISource` if no multibyte characters + # are present in the source code. + # -- + # : (String source, ?Integer start_line, ?Array[Integer] offsets) -> Source + def self.for: (String source, ?Integer start_line, ?Array[Integer] offsets) -> Source + + # The source code that this source object represents. + attr_reader source: String + + # The line number where this source starts. + attr_reader start_line: Integer + + # The list of newline byte offsets in the source code. + attr_reader offsets: Array[Integer] + + # Create a new source object with the given source code. + # -- + # : (String source, ?Integer start_line, ?Array[Integer] offsets) -> void + def initialize: (String source, ?Integer start_line, ?Array[Integer] offsets) -> void + + # Replace the value of start_line with the given value. + # -- + # : (Integer start_line) -> void + def replace_start_line: (Integer start_line) -> void + + # Replace the value of offsets with the given value. + # -- + # : (Array[Integer] offsets) -> void + def replace_offsets: (Array[Integer] offsets) -> void + + # Returns the encoding of the source code, which is set by parameters to the + # parser or by the encoding magic comment. + # -- + # : () -> Encoding + def encoding: () -> Encoding + + # Returns the lines of the source code as an array of strings. + # -- + # : () -> Array[String] + def lines: () -> Array[String] + + # Perform a byteslice on the source code using the given byte offset and + # byte length. + # -- + # : (Integer byte_offset, Integer length) -> String + def slice: (Integer byte_offset, Integer length) -> String + + # Converts the line number and column in bytes to a byte offset. + # -- + # : (Integer line, Integer column) -> Integer + def byte_offset: (Integer line, Integer column) -> Integer + + # Binary search through the offsets to find the line number for the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def line: (Integer byte_offset) -> Integer + + # Return the byte offset of the start of the line corresponding to the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def line_start: (Integer byte_offset) -> Integer + + # Returns the byte offset of the end of the line corresponding to the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def line_end: (Integer byte_offset) -> Integer + + # Return the column in bytes for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def column: (Integer byte_offset) -> Integer + + # Return the character offset for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def character_offset: (Integer byte_offset) -> Integer + + # Return the column in characters for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def character_column: (Integer byte_offset) -> Integer + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the + # concept of code units that differs from the number of characters in other + # encodings, it is not captured here. + # + # We purposefully replace invalid and undefined characters with replacement + # characters in this conversion. This happens for two reasons. First, it's + # possible that the given byte offset will not occur on a character + # boundary. Second, it's possible that the source code will contain a + # character that has no equivalent in the given encoding. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer + + # Generate a cache that targets a specific encoding for calculating code + # unit offsets. + # -- + # : (Encoding encoding) -> CodeUnitsCache + def code_units_cache: (Encoding encoding) -> CodeUnitsCache + + # Returns the column in code units for the given encoding for the + # given byte offset. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer + + # Freeze this object and the objects it contains. + # -- + # : () -> void + def deep_freeze: () -> void + + private + + # Binary search through the offsets to find the line number for the given + # byte offset. + # -- + # : (Integer byte_offset) -> Integer + def find_line: (Integer byte_offset) -> Integer + end + + # A cache that can be used to quickly compute code unit offsets from byte + # offsets. It purposefully provides only a single #[] method to access the + # cache in order to minimize surface area. + # + # Note that there are some known issues here that may or may not be addressed + # in the future: + # + # * The first is that there are issues when the cache computes values that are + # not on character boundaries. This can result in subsequent computations + # being off by one or more code units. + # * The second is that this cache is currently unbounded. In theory we could + # introduce some kind of LRU cache to limit the number of entries, but this + # has not yet been implemented. + class CodeUnitsCache + class UTF16Counter + @source: String + + @encoding: Encoding + + # : (String source, Encoding encoding) -> void + def initialize: (String source, Encoding encoding) -> void + + # : (Integer byte_offset, Integer byte_length) -> Integer + def count: (Integer byte_offset, Integer byte_length) -> Integer + end + + class LengthCounter + @source: String + + @encoding: Encoding + + # : (String source, Encoding encoding) -> void + def initialize: (String source, Encoding encoding) -> void + + # : (Integer byte_offset, Integer byte_length) -> Integer + def count: (Integer byte_offset, Integer byte_length) -> Integer + end + + @source: String + + @counter: UTF16Counter | LengthCounter + + @cache: Hash[Integer, Integer] + + @offsets: Array[Integer] + + # Initialize a new cache with the given source and encoding. + # -- + # : (String source, Encoding encoding) -> void + def initialize: (String source, Encoding encoding) -> void + + # Retrieve the code units offset from the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def []: (Integer byte_offset) -> Integer + end + + # Specialized version of Prism::Source for source code that includes ASCII + # characters only. This class is used to apply performance optimizations that + # cannot be applied to sources that include multibyte characters. + # + # In the extremely rare case that a source includes multi-byte characters but + # is marked as binary because of a magic encoding comment and it cannot be + # eagerly converted to UTF-8, this class will be used as well. This is because + # at that point we will treat everything as single-byte characters. + class ASCIISource < Source + # Return the character offset for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def character_offset: (Integer byte_offset) -> Integer + + # Return the column in characters for the given byte offset. + # -- + # : (Integer byte_offset) -> Integer + def character_column: (Integer byte_offset) -> Integer + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the + # concept of code units that differs from the number of characters in other + # encodings, it is not captured here. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer + + # Returns a cache that is the identity function in order to maintain the + # same interface. We can do this because code units are always equivalent to + # byte offsets for ASCII-only sources. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + + # Specialized version of `code_units_column` that does not depend on + # `code_units_offset`, which is a more expensive operation. This is + # essentially the same as `Prism::Source#column`. + # -- + # : (Integer byte_offset, Encoding encoding) -> Integer + def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer + end + + # This represents a location in the source. + class Location + # A Source object that is used to determine more information from the given + # offset and length. + attr_reader source: Source + + # The byte offset from the beginning of the source where this location + # starts. + attr_reader start_offset: Integer + + # The length of this location in bytes. + attr_reader length: Integer + + @trailing_comments: Array[Comment]? + + @leading_comments: Array[Comment]? + + # Create a new location object with the given source, start byte offset, and + # byte length. + # -- + # : (Source source, Integer start_offset, Integer length) -> void + def initialize: (Source source, Integer start_offset, Integer length) -> void + + # These are the comments that are associated with this location that exist + # before the start of this location. + # -- + # : () -> Array[Comment] + def leading_comments: () -> Array[Comment] + + # Attach a comment to the leading comments of this location. + # -- + # : (Comment comment) -> void + def leading_comment: (Comment comment) -> void + + # These are the comments that are associated with this location that exist + # after the end of this location. + # -- + # : () -> Array[Comment] + def trailing_comments: () -> Array[Comment] + + # Attach a comment to the trailing comments of this location. + # -- + # : (Comment comment) -> void + def trailing_comment: (Comment comment) -> void + + # Returns all comments that are associated with this location (both leading + # and trailing comments). + # -- + # : () -> Array[Comment] + def comments: () -> Array[Comment] + + # Create a new location object with the given options. + # -- + # : (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + def copy: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location + + # Returns a new location that is the result of chopping off the last byte. + # -- + # : () -> Location + def chop: () -> Location + + # Returns a string representation of this location. + # -- + # : () -> String + def inspect: () -> String + + # Returns all of the lines of the source code associated with this location. + # -- + # : () -> Array[String] + def source_lines: () -> Array[String] + + # The source code that this location represents. + # -- + # : () -> String + def slice: () -> String + + # The source code that this location represents starting from the beginning + # of the line that this location starts on to the end of the line that this + # location ends on. + # -- + # : () -> String + def slice_lines: () -> String + + # The character offset from the beginning of the source where this location + # starts. + # -- + # : () -> Integer + def start_character_offset: () -> Integer + + # The offset from the start of the file in code units of the given encoding. + # -- + # : (Encoding encoding) -> Integer + def start_code_units_offset: (Encoding encoding) -> Integer + + # The start offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # The byte offset from the beginning of the source where this location ends. + # -- + # : () -> Integer + def end_offset: () -> Integer + + # The character offset from the beginning of the source where this location + # ends. + # -- + # : () -> Integer + def end_character_offset: () -> Integer + + # The offset from the start of the file in code units of the given encoding. + # -- + # : (Encoding encoding) -> Integer + def end_code_units_offset: (Encoding encoding) -> Integer + + # The end offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + + # The line number where this location starts. + # -- + # : () -> Integer + def start_line: () -> Integer + + # The content of the line where this location starts before this location. + # -- + # : () -> String + def start_line_slice: () -> String + + # The line number where this location ends. + # -- + # : () -> Integer + def end_line: () -> Integer + + # The column in bytes where this location starts from the start of + # the line. + # -- + # : () -> Integer + def start_column: () -> Integer + + # The column in characters where this location ends from the start of + # the line. + # -- + # : () -> Integer + def start_character_column: () -> Integer + + # The column in code units of the given encoding where this location + # starts from the start of the line. + # -- + # : (?Encoding encoding) -> Integer + def start_code_units_column: (?Encoding encoding) -> Integer + + # The start column in code units using the given cache to fetch or calculate + # the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + + # The column in bytes where this location ends from the start of the + # line. + # -- + # : () -> Integer + def end_column: () -> Integer + + # The column in characters where this location ends from the start of + # the line. + # -- + # : () -> Integer + def end_character_column: () -> Integer + + # The column in code units of the given encoding where this location + # ends from the start of the line. + # -- + # : (?Encoding encoding) -> Integer + def end_code_units_column: (?Encoding encoding) -> Integer + + # The end column in code units using the given cache to fetch or calculate + # the value. + # -- + # : (_CodeUnitsCache cache) -> Integer + def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + + # Implement the hash pattern matching interface for Location. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Implement the pretty print interface for Location. + # -- + # : (PP q) -> void + def pretty_print: (PP q) -> void + + # Returns true if the given other location is equal to this location. + # -- + # : (untyped other) -> bool + def ==: (untyped other) -> bool + + # Returns a new location that stretches from this location to the given + # other location. Raises an error if this location is not before the other + # location or if they don't share the same source. + # -- + # : (Location other) -> Location + def join: (Location other) -> Location + + # Join this location with the first occurrence of the string in the source + # that occurs after this location on the same line, and return the new + # location. This will raise an error if the string does not exist. + # -- + # : (String string) -> Location + def adjoin: (String string) -> Location + end + + # This represents a comment that was encountered during parsing. It is the + # base class for all comment types. + class Comment + # The Location of this comment in the source. + attr_reader location: Location + + # Create a new comment object with the given location. + # -- + # : (Location location) -> void + def initialize: (Location location) -> void + + # Implement the hash pattern matching interface for Comment. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns the content of the comment by slicing it from the source code. + # -- + # : () -> String + def slice: () -> String + + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. This can only be true for inline + # comments and should be false for block comments. + # -- + # : () -> bool + def trailing?: () -> bool + end + + # InlineComment objects are the most common. They correspond to comments in + # the source file like this one that start with #. + class InlineComment < Comment + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. + # -- + # : () -> bool + def trailing?: () -> bool + + # Returns a string representation of this comment. + # -- + # : () -> String + def inspect: () -> String + end + + # EmbDocComment objects correspond to comments that are surrounded by =begin + # and =end. + class EmbDocComment < Comment + # Returns false. This can only be true for inline comments. + # -- + # : () -> bool + def trailing?: () -> bool + + # Returns a string representation of this comment. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents a magic comment that was encountered during parsing. + class MagicComment + # A Location object representing the location of the key in the source. + attr_reader key_loc: Location + + # A Location object representing the location of the value in the source. + attr_reader value_loc: Location + + # Create a new magic comment object with the given key and value locations. + # -- + # : (Location key_loc, Location value_loc) -> void + def initialize: (Location key_loc, Location value_loc) -> void + + # Returns the key of the magic comment by slicing it from the source code. + # -- + # : () -> String + def key: () -> String + + # Returns the value of the magic comment by slicing it from the source code. + # -- + # : () -> String + def value: () -> String + + # Implement the hash pattern matching interface for MagicComment. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns a string representation of this magic comment. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents an error that was encountered during parsing. + class ParseError + # The type of error. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + attr_reader type: Symbol + + # The message associated with this error. + attr_reader message: String + + # A Location object representing the location of this error in the source. + attr_reader location: Location + + # The level of this error. + attr_reader level: Symbol + + # Create a new error object with the given message and location. + # -- + # : (Symbol type, String message, Location location, Symbol level) -> void + def initialize: (Symbol type, String message, Location location, Symbol level) -> void + + # Implement the hash pattern matching interface for ParseError. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns a string representation of this error. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents a warning that was encountered during parsing. + class ParseWarning + # The type of warning. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + attr_reader type: Symbol + + # The message associated with this warning. + attr_reader message: String + + # A Location object representing the location of this warning in the source. + attr_reader location: Location + + # The level of this warning. + attr_reader level: Symbol + + # Create a new warning object with the given message and location. + # -- + # : (Symbol type, String message, Location location, Symbol level) -> void + def initialize: (Symbol type, String message, Location location, Symbol level) -> void + + # Implement the hash pattern matching interface for ParseWarning. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns a string representation of this warning. + # -- + # : () -> String + def inspect: () -> String + end + + # This represents the result of a call to Prism.parse or Prism.parse_file. + # It contains the requested structure, any comments that were encounters, + # and any errors that were encountered. + class Result + # The list of comments that were encountered during parsing. + attr_reader comments: Array[Comment] + + # The list of magic comments that were encountered during parsing. + attr_reader magic_comments: Array[MagicComment] + + # An optional location that represents the location of the __END__ marker + # and the rest of the content of the file. This content is loaded into the + # DATA constant when the file being parsed is the main file being executed. + attr_reader data_loc: Location? + + # The list of errors that were generated during parsing. + attr_reader errors: Array[ParseError] + + # The list of warnings that were generated during parsing. + attr_reader warnings: Array[ParseWarning] + + # A Source instance that represents the source code that was parsed. + attr_reader source: Source + + # Create a new result object with the given values. + # -- + # : (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + def initialize: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + + # Implement the hash pattern matching interface for Result. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Returns the encoding of the source code that was parsed. + # -- + # : () -> Encoding + def encoding: () -> Encoding + + # Returns true if there were no errors during parsing and false if there + # were. + # -- + # : () -> bool + def success?: () -> bool + + # Returns true if there were errors during parsing and false if there were + # not. + # -- + # : () -> bool + def failure?: () -> bool + + # Create a code units cache for the given encoding. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + end + + # This is a result specific to the `parse` and `parse_file` methods. + class ParseResult < Result + # The syntax tree that was parsed from the source code. + attr_reader value: ProgramNode + + # Create a new parse result object with the given values. + # -- + # : (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + def initialize: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + + # Implement the hash pattern matching interface for ParseResult. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # Attach the list of comments to their respective locations in the tree. + # -- + # : () -> void + def attach_comments!: () -> void + + # Walk the tree and mark nodes that are on a new line, loosely emulating + # the behavior of CRuby's `:line` tracepoint event. + # -- + # : () -> void + def mark_newlines!: () -> void + + # Returns a string representation of the syntax tree with the errors + # displayed inline. + # -- + # : () -> String + def errors_format: () -> String + end + + # This is a result specific to the `lex` and `lex_file` methods. + class LexResult < Result + # The list of tokens that were parsed from the source code. + attr_reader value: Array[[ Token, Integer ]] + + # Create a new lex result object with the given values. + # -- + # : (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + def initialize: (Array[[ Token, Integer ]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + + # Implement the hash pattern matching interface for LexResult. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + end + + # This is a result specific to the `parse_lex` and `parse_lex_file` methods. + class ParseLexResult < Result + # A tuple of the syntax tree and the list of tokens that were parsed from + # the source code. + attr_reader value: [ ProgramNode, Array[[ Token, Integer ]] ] + + # Create a new parse lex result object with the given values. + # -- + # : ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + def initialize: ([ ProgramNode, Array[[ Token, Integer ]] ] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + + # Implement the hash pattern matching interface for ParseLexResult. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + end + + # This represents a token from the Ruby source. + class Token + # The Source object that represents the source this token came from. + attr_reader source: Source + + # The type of token that this token is. + attr_reader type: Symbol + + # A byteslice of the source that this token represents. + attr_reader value: String + + @location: Location | Integer + + # Create a new token object with the given type, value, and location. + # -- + # : (Source source, Symbol type, String value, Location | Integer location) -> void + def initialize: (Source source, Symbol type, String value, Location | Integer location) -> void + + # Implement the hash pattern matching interface for Token. + # -- + # : (Array[Symbol]? keys) -> Hash[Symbol, untyped] + def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] + + # A Location object representing the location of this token in the source. + # -- + # : () -> Location + def location: () -> Location + + # Implement the pretty print interface for Token. + # -- + # : (PP q) -> void + def pretty_print: (PP q) -> void + + # Returns true if the given other token is equal to this token. + # -- + # : (untyped other) -> bool + def ==: (untyped other) -> bool + + # Returns a string representation of this token. + # -- + # : () -> String + def inspect: () -> String + + # Freeze this object and the objects it contains. + # -- + # : () -> void + def deep_freeze: () -> void + end + + # This object is passed to the various Prism.* methods that accept the + # `scopes` option as an element of the list. It defines both the local + # variables visible at that scope as well as the forwarding parameters + # available at that scope. + class Scope + # The list of local variables that are defined in this scope. This should be + # defined as an array of symbols. + attr_reader locals: Array[Symbol] + + # The list of local variables that are forwarded to the next scope. This + # should by defined as an array of symbols containing the specific values of + # :*, :**, :&, or :"...". + attr_reader forwarding: Array[Symbol] + + # Create a new scope object with the given locals and forwarding. + # -- + # : (Array[Symbol] locals, Array[Symbol] forwarding) -> void + def initialize: (Array[Symbol] locals, Array[Symbol] forwarding) -> void + end + + # Create a new scope with the given locals and forwarding options that is + # suitable for passing into one of the Prism.* methods that accepts the + # `scopes` option. + # -- + # : (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope + def self.scope: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope +end diff --git a/sig/generated/prism/parse_result/comments.rbs b/sig/generated/prism/parse_result/comments.rbs new file mode 100644 index 0000000000..1dc7ae974b --- /dev/null +++ b/sig/generated/prism/parse_result/comments.rbs @@ -0,0 +1,108 @@ +# Generated from lib/prism/parse_result/comments.rb with RBS::Inline + +module Prism + class ParseResult < Result + # When we've parsed the source, we have both the syntax tree and the list of + # comments that we found in the source. This class is responsible for + # walking the tree and finding the nearest location to attach each comment. + # + # It does this by first finding the nearest locations to each comment. + # Locations can either come from nodes directly or from location fields on + # nodes. For example, a `ClassNode` has an overall location encompassing the + # entire class, but it also has a location for the `class` keyword. + # + # Once the nearest locations are found, it determines which one to attach + # to. If it's a trailing comment (a comment on the same line as other source + # code), it will favor attaching to the nearest location that occurs before + # the comment. Otherwise it will favor attaching to the nearest location + # that is after the comment. + class Comments + # An internal interface for a target that comments can be attached + # to. This is either going to be a NodeTarget or a CommentTarget. + interface _CommentTarget + def start_offset: () -> Integer + + def end_offset: () -> Integer + + def encloses?: (Comment) -> bool + + def leading_comment: (Comment) -> void + + def trailing_comment: (Comment) -> void + end + + # A target for attaching comments that is based on a specific node's + # location. + class NodeTarget + # :nodoc: + attr_reader node: node + + # : (node node) -> void + def initialize: (node node) -> void + + # : () -> Integer + def start_offset: () -> Integer + + # : () -> Integer + def end_offset: () -> Integer + + # : (Comment comment) -> bool + def encloses?: (Comment comment) -> bool + + # : (Comment comment) -> void + def leading_comment: (Comment comment) -> void + + # : (Comment comment) -> void + def trailing_comment: (Comment comment) -> void + end + + # A target for attaching comments that is based on a location field on a + # node. For example, the `end` token of a ClassNode. + class LocationTarget + # :nodoc: + attr_reader location: Location + + # : (Location location) -> void + def initialize: (Location location) -> void + + # : () -> Integer + def start_offset: () -> Integer + + # : () -> Integer + def end_offset: () -> Integer + + # : (Comment comment) -> bool + def encloses?: (Comment comment) -> bool + + # : (Comment comment) -> void + def leading_comment: (Comment comment) -> void + + # : (Comment comment) -> void + def trailing_comment: (Comment comment) -> void + end + + # The parse result that we are attaching comments to. + attr_reader parse_result: ParseResult + + # Create a new Comments object that will attach comments to the given + # parse result. + # -- + # : (ParseResult parse_result) -> void + def initialize: (ParseResult parse_result) -> void + + # Attach the comments to their respective locations in the tree by + # mutating the parse result. + # -- + # : () -> void + def attach!: () -> void + + private + + # Responsible for finding the nearest targets to the given comment within + # the context of the given encapsulating node. + # -- + # : (node node, Comment comment) -> [_CommentTarget?, _CommentTarget?, _CommentTarget?] + def nearest_targets: (node node, Comment comment) -> [ _CommentTarget?, _CommentTarget?, _CommentTarget? ] + end + end +end diff --git a/sig/generated/prism/parse_result/errors.rbs b/sig/generated/prism/parse_result/errors.rbs new file mode 100644 index 0000000000..1b97d8a763 --- /dev/null +++ b/sig/generated/prism/parse_result/errors.rbs @@ -0,0 +1,22 @@ +# Generated from lib/prism/parse_result/errors.rb with RBS::Inline + +module Prism + class ParseResult < Result + # An object to represent the set of errors on a parse result. This object + # can be used to format the errors in a human-readable way. + class Errors + # The parse result that contains the errors. + attr_reader parse_result: ParseResult + + # Initialize a new set of errors from the given parse result. + # -- + # : (ParseResult parse_result) -> void + def initialize: (ParseResult parse_result) -> void + + # Formats the errors in a human-readable way and return them as a string. + # -- + # : () -> String + def format: () -> String + end + end +end diff --git a/sig/generated/prism/parse_result/newlines.rbs b/sig/generated/prism/parse_result/newlines.rbs new file mode 100644 index 0000000000..7037631712 --- /dev/null +++ b/sig/generated/prism/parse_result/newlines.rbs @@ -0,0 +1,129 @@ +# Generated from lib/prism/parse_result/newlines.rb with RBS::Inline + +module Prism + class ParseResult < Result + # The :line tracepoint event gets fired whenever the Ruby VM encounters an + # expression on a new line. The types of expressions that can trigger this + # event are: + # + # * if statements + # * unless statements + # * nodes that are children of statements lists + # + # In order to keep track of the newlines, we have a list of offsets that + # come back from the parser. We assign these offsets to the first nodes that + # we find in the tree that are on those lines. + # + # Note that the logic in this file should be kept in sync with the Java + # MarkNewlinesVisitor, since that visitor is responsible for marking the + # newlines for JRuby/TruffleRuby. + # + # This file is autoloaded only when `mark_newlines!` is called, so the + # re-opening of the various nodes in this file will only be performed in + # that case. We do that to avoid storing the extra `@newline` instance + # variable on every node if we don't need it. + class Newlines < Visitor + @lines: Array[bool] + + # Create a new Newlines visitor with the given newline offsets. + # -- + # : (Integer lines) -> void + def initialize: (Integer lines) -> void + + # Permit block nodes to mark newlines within themselves. + # -- + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # Permit lambda nodes to mark newlines within themselves. + # -- + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # Mark if nodes as newlines. + # -- + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # Mark unless nodes as newlines. + # -- + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # Permit statements lists to mark newlines within themselves. + # -- + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + end + end + + class Node + @newline_flag: bool + + # : () -> bool + def newline_flag?: () -> bool + + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void + end + + class BeginNode < Node + # @rbs override + def newline_flag!: ... + end + + class ParenthesesNode < Node + # @rbs override + def newline_flag!: ... + end + + class IfNode < Node + # @rbs override + def newline_flag!: ... + end + + class UnlessNode < Node + # @rbs override + def newline_flag!: ... + end + + class UntilNode < Node + # @rbs override + def newline_flag!: ... + end + + class WhileNode < Node + # @rbs override + def newline_flag!: ... + end + + class RescueModifierNode < Node + # @rbs override + def newline_flag!: ... + end + + class InterpolatedMatchLastLineNode < Node + # @rbs override + def newline_flag!: ... + end + + class InterpolatedRegularExpressionNode < Node + # @rbs override + def newline_flag!: ... + end + + class InterpolatedStringNode < Node + # @rbs override + def newline_flag!: ... + end + + class InterpolatedSymbolNode < Node + # @rbs override + def newline_flag!: ... + end + + class InterpolatedXStringNode < Node + # @rbs override + def newline_flag!: ... + end +end diff --git a/sig/generated/prism/pattern.rbs b/sig/generated/prism/pattern.rbs new file mode 100644 index 0000000000..d427b0098b --- /dev/null +++ b/sig/generated/prism/pattern.rbs @@ -0,0 +1,156 @@ +# Generated from lib/prism/pattern.rb with RBS::Inline + +module Prism + # A pattern is an object that wraps a Ruby pattern matching expression. The + # expression would normally be passed to an `in` clause within a `case` + # expression or a rightward assignment expression. For example, in the + # following snippet: + # + # case node + # in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]] + # end + # + # the pattern is the ConstantPathNode[...] expression. + # + # The pattern gets compiled into an object that responds to #call by running + # the #compile method. This method itself will run back through Prism to + # parse the expression into a tree, then walk the tree to generate the + # necessary callable objects. For example, if you wanted to compile the + # expression above into a callable, you would: + # + # callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile + # callable.call(node) + # + # The callable object returned by #compile is guaranteed to respond to #call + # with a single argument, which is the node to match against. It also is + # guaranteed to respond to #===, which means it itself can be used in a `case` + # expression, as in: + # + # case node + # when callable + # end + # + # If the query given to the initializer cannot be compiled into a valid + # matcher (either because of a syntax error or because it is using syntax we + # do not yet support) then a Prism::Pattern::CompilationError will be + # raised. + class Pattern + # Raised when the query given to a pattern is either invalid Ruby syntax or + # is using syntax that we don't yet support. + class CompilationError < StandardError + # Create a new CompilationError with the given representation of the node + # that caused the error. + # -- + # : (String repr) -> void + def initialize: (String repr) -> void + end + + # The query that this pattern was initialized with. + attr_reader query: String + + @compiled: Proc? + + # Create a new pattern with the given query. The query should be a string + # containing a Ruby pattern matching expression. + # -- + # : (String query) -> void + def initialize: (String query) -> void + + # Compile the query into a callable object that can be used to match against + # nodes. + # -- + # : () -> Proc + def compile: () -> Proc + + # Scan the given node and all of its children for nodes that match the + # pattern. If a block is given, it will be called with each node that + # matches the pattern. If no block is given, an enumerator will be returned + # that will yield each node that matches the pattern. + # -- + # : (node root) { (node) -> void } -> void + # : (node root) -> Enumerator[node, void] + def scan: (node root) { (node) -> void } -> void + | (node root) -> Enumerator[node, void] + + private + + # Shortcut for combining two procs into one that returns true if both return + # true. + # -- + # : (Proc left, Proc right) -> Proc + def combine_and: (Proc left, Proc right) -> Proc + + # Shortcut for combining two procs into one that returns true if either + # returns true. + # -- + # : (Proc left, Proc right) -> Proc + def combine_or: (Proc left, Proc right) -> Proc + + # Raise an error because the given node is not supported. Note purposefully + # not typing this method since it is a no return method that Steep does not + # understand. + # -- + # : (node node) -> bot + def compile_error: (node node) -> bot + + # in [foo, bar, baz] + # -- + # : (ArrayPatternNode node) -> Proc + def compile_array_pattern_node: (ArrayPatternNode node) -> Proc + + # in foo | bar + # -- + # : (AlternationPatternNode node) -> Proc + def compile_alternation_pattern_node: (AlternationPatternNode node) -> Proc + + # in Prism::ConstantReadNode + # -- + # : (ConstantPathNode node) -> Proc + def compile_constant_path_node: (ConstantPathNode node) -> Proc + + # in ConstantReadNode + # in String + # -- + # : (ConstantReadNode node) -> Proc + def compile_constant_read_node: (ConstantReadNode node) -> Proc + + # Compile a name associated with a constant. + # -- + # : ((ConstantPathNode | ConstantReadNode) node, Symbol name) -> Proc + def compile_constant_name: (ConstantPathNode | ConstantReadNode node, Symbol name) -> Proc + + # in InstanceVariableReadNode[name: Symbol] + # in { name: Symbol } + # -- + # : (HashPatternNode node) -> Proc + def compile_hash_pattern_node: (HashPatternNode node) -> Proc + + # in nil + # -- + # : (NilNode node) -> Proc + def compile_nil_node: (NilNode node) -> Proc + + # in /foo/ + # -- + # : (RegularExpressionNode node) -> Proc + def compile_regular_expression_node: (RegularExpressionNode node) -> Proc + + # in "" + # in "foo" + # -- + # : (StringNode node) -> Proc + def compile_string_node: (StringNode node) -> Proc + + # in :+ + # in :foo + # -- + # : (SymbolNode node) -> Proc + def compile_symbol_node: (SymbolNode node) -> Proc + + # Compile any kind of node. Dispatch out to the individual compilation + # methods based on the type of node. + # -- + # : (node node) -> Proc + def compile_node: (node node) -> Proc + end +end diff --git a/sig/generated/prism/reflection.rbs b/sig/generated/prism/reflection.rbs new file mode 100644 index 0000000000..8237da3a2e --- /dev/null +++ b/sig/generated/prism/reflection.rbs @@ -0,0 +1,101 @@ +# Generated from lib/prism/reflection.rb with RBS::Inline + +module Prism + # The Reflection module provides the ability to reflect on the structure of + # the syntax tree itself, as opposed to looking at a single syntax tree. This + # is useful in metaprogramming contexts. + module Reflection + # A field represents a single piece of data on a node. It is the base class + # for all other field types. + class Field + # The name of the field. + attr_reader name: Symbol + + # Initializes the field with the given name. + # -- + # : (Symbol name) -> void + def initialize: (Symbol name) -> void + end + + # A node field represents a single child node in the syntax tree. It + # resolves to a Prism::Node in Ruby. + class NodeField < Field + end + + # An optional node field represents a single child node in the syntax tree + # that may or may not be present. It resolves to either a Prism::Node or nil + # in Ruby. + class OptionalNodeField < Field + end + + # A node list field represents a list of child nodes in the syntax tree. It + # resolves to an array of Prism::Node instances in Ruby. + class NodeListField < Field + end + + # A constant field represents a constant value on a node. Effectively, it + # represents an identifier found within the source. It resolves to a symbol + # in Ruby. + class ConstantField < Field + end + + # An optional constant field represents a constant value on a node that may + # or may not be present. It resolves to either a symbol or nil in Ruby. + class OptionalConstantField < Field + end + + # A constant list field represents a list of constant values on a node. It + # resolves to an array of symbols in Ruby. + class ConstantListField < Field + end + + # A string field represents a string value on a node. It almost always + # represents the unescaped value of a string-like literal. It resolves to a + # string in Ruby. + class StringField < Field + end + + # A location field represents the location of some part of the node in the + # source code. For example, the location of a keyword or an operator. It + # resolves to a Prism::Location in Ruby. + class LocationField < Field + end + + # An optional location field represents the location of some part of the + # node in the source code that may or may not be present. It resolves to + # either a Prism::Location or nil in Ruby. + class OptionalLocationField < Field + end + + # An integer field represents an integer value. It is used to represent the + # value of an integer literal, the depth of local variables, and the number + # of a numbered reference. It resolves to an Integer in Ruby. + class IntegerField < Field + end + + # A float field represents a double-precision floating point value. It is + # used exclusively to represent the value of a floating point literal. It + # resolves to a Float in Ruby. + class FloatField < Field + end + + # A flags field represents a bitset of flags on a node. It resolves to an + # integer in Ruby. Note that the flags cannot be accessed directly on the + # node because the integer is kept private. Instead, the various flags in + # the bitset should be accessed through their query methods. + class FlagsField < Field + # The names of the flags in the bitset. + attr_reader flags: Array[Symbol] + + # Initializes the flags field with the given name and flags. + # -- + # : (Symbol name, Array[Symbol] flags) -> void + def initialize: (Symbol name, Array[Symbol] flags) -> void + end + + # Returns the fields for the given node. + # -- + # : (singleton(Node) node) -> Array[Field] + def self.fields_for: (singleton(Node) node) -> Array[Field] + end +end diff --git a/sig/generated/prism/relocation.rbs b/sig/generated/prism/relocation.rbs new file mode 100644 index 0000000000..35238609ca --- /dev/null +++ b/sig/generated/prism/relocation.rbs @@ -0,0 +1,502 @@ +# Generated from lib/prism/relocation.rb with RBS::Inline + +module Prism + # Prism parses deterministically for the same input. This provides a nice + # property that is exposed through the #node_id API on nodes. Effectively this + # means that for the same input, these values will remain consistent every + # time the source is parsed. This means we can reparse the source same with a + # #node_id value and find the exact same node again. + # + # The Relocation module provides an API around this property. It allows you to + # "save" nodes and locations using a minimal amount of memory (just the + # node_id and a field identifier) and then reify them later. + module Relocation + type entry_value = untyped + + type entry_values = Hash[Symbol, entry_value] + + interface _Value + def start_line: () -> Integer + + def end_line: () -> Integer + + def start_offset: () -> Integer + + def end_offset: () -> Integer + + def start_character_offset: () -> Integer + + def end_character_offset: () -> Integer + + def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer + + def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer + + def start_column: () -> Integer + + def end_column: () -> Integer + + def start_character_column: () -> Integer + + def end_character_column: () -> Integer + + def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer + + def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer + + def leading_comments: () -> Array[Comment] + + def trailing_comments: () -> Array[Comment] + end + + interface _Field + def fields: (_Value value) -> entry_values + end + + # An entry in a repository that will lazily reify its values when they are + # first accessed. + class Entry + # Raised if a value that could potentially be on an entry is missing + # because it was either not configured on the repository or it has not yet + # been fetched. + class MissingValueError < StandardError + end + + @values: Hash[Symbol, untyped]? + + @repository: Repository? + + # Initialize a new entry with the given repository. + # -- + # : (Repository repository) -> void + def initialize: (Repository repository) -> void + + # Fetch the filepath of the value. + # -- + # : () -> String + def filepath: () -> String + + # Fetch the start line of the value. + # -- + # : () -> Integer + def start_line: () -> Integer + + # Fetch the end line of the value. + # -- + # : () -> Integer + def end_line: () -> Integer + + # Fetch the start byte offset of the value. + # -- + # : () -> Integer + def start_offset: () -> Integer + + # Fetch the end byte offset of the value. + # -- + # : () -> Integer + def end_offset: () -> Integer + + # Fetch the start character offset of the value. + # -- + # : () -> Integer + def start_character_offset: () -> Integer + + # Fetch the end character offset of the value. + # -- + # : () -> Integer + def end_character_offset: () -> Integer + + # Fetch the start code units offset of the value, for the encoding that + # was configured on the repository. + # -- + # : () -> Integer + def start_code_units_offset: () -> Integer + + # Fetch the end code units offset of the value, for the encoding that was + # configured on the repository. + # -- + # : () -> Integer + def end_code_units_offset: () -> Integer + + # Fetch the start byte column of the value. + # -- + # : () -> Integer + def start_column: () -> Integer + + # Fetch the end byte column of the value. + # -- + # : () -> Integer + def end_column: () -> Integer + + # Fetch the start character column of the value. + # -- + # : () -> Integer + def start_character_column: () -> Integer + + # Fetch the end character column of the value. + # -- + # : () -> Integer + def end_character_column: () -> Integer + + # Fetch the start code units column of the value, for the encoding that + # was configured on the repository. + # -- + # : () -> Integer + def start_code_units_column: () -> Integer + + # Fetch the end code units column of the value, for the encoding that was + # configured on the repository. + # -- + # : () -> Integer + def end_code_units_column: () -> Integer + + # Fetch the leading comments of the value. + # -- + # : () -> Array[CommentsField::Comment] + def leading_comments: () -> Array[CommentsField::Comment] + + # Fetch the trailing comments of the value. + # -- + # : () -> Array[CommentsField::Comment] + def trailing_comments: () -> Array[CommentsField::Comment] + + # Fetch the leading and trailing comments of the value. + # -- + # : () -> Array[CommentsField::Comment] + def comments: () -> Array[CommentsField::Comment] + + # Reify the values on this entry with the given values. This is an + # internal-only API that is called from the repository when it is time to + # reify the values. + # -- + # : (entry_values values) -> void + def reify!: (entry_values values) -> void + + private + + # Fetch a value from the entry, raising an error if it is missing. + # -- + # : (Symbol name) -> entry_value + def fetch_value: (Symbol name) -> entry_value + + # Return the values from the repository, reifying them if necessary. + # -- + # : () -> entry_values + def values: () -> entry_values + end + + # Represents the source of a repository that will be reparsed. + class Source + # The value that will need to be reparsed. + attr_reader value: untyped + + # Initialize the source with the given value. + # -- + # : (untyped value) -> void + def initialize: (untyped value) -> void + + # Reparse the value and return the parse result. + # -- + # : () -> ParseResult + def result: () -> ParseResult + + # Create a code units cache for the given encoding. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + end + + # A source that is represented by a file path. + class SourceFilepath < Source + # Reparse the file and return the parse result. + # -- + # : () -> ParseResult + def result: () -> ParseResult + end + + # A source that is represented by a string. + class SourceString < Source + # Reparse the string and return the parse result. + # -- + # : () -> ParseResult + def result: () -> ParseResult + end + + # A field that represents the file path. + class FilepathField + # The file path that this field represents. + attr_reader value: String + + # Initialize a new field with the given file path. + # -- + # : (String value) -> void + def initialize: (String value) -> void + + # Fetch the file path. + # -- + # : (_Value _value) -> entry_values + def fields: (_Value _value) -> entry_values + end + + # A field representing the start and end lines. + class LinesField + # Fetches the start and end line of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end byte offsets. + class OffsetsField + # Fetches the start and end byte offset of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end character offsets. + class CharacterOffsetsField + # Fetches the start and end character offset of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end code unit offsets. + class CodeUnitOffsetsField + # A pointer to the repository object that is used for lazily creating a + # code units cache. + attr_reader repository: Repository + + # The associated encoding for the code units. + attr_reader encoding: Encoding + + @cache: _CodeUnitsCache? + + # Initialize a new field with the associated repository and encoding. + # -- + # : (Repository repository, Encoding encoding) -> void + def initialize: (Repository repository, Encoding encoding) -> void + + # Fetches the start and end code units offset of a value for a particular + # encoding. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + + private + + # Lazily create a code units cache for the associated encoding. + # -- + # : () -> _CodeUnitsCache + def cache: () -> _CodeUnitsCache + end + + # A field representing the start and end byte columns. + class ColumnsField + # Fetches the start and end byte column of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end character columns. + class CharacterColumnsField + # Fetches the start and end character column of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the start and end code unit columns for a specific + # encoding. + class CodeUnitColumnsField + # The repository object that is used for lazily creating a code units + # cache. + attr_reader repository: Repository + + # The associated encoding for the code units. + attr_reader encoding: Encoding + + @cache: _CodeUnitsCache? + + # Initialize a new field with the associated repository and encoding. + # -- + # : (Repository repository, Encoding encoding) -> void + def initialize: (Repository repository, Encoding encoding) -> void + + # Fetches the start and end code units column of a value for a particular + # encoding. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + + private + + # Lazily create a code units cache for the associated encoding. + # -- + # : () -> _CodeUnitsCache + def cache: () -> _CodeUnitsCache + end + + # An abstract field used as the parent class of the two comments fields. + class CommentsField + # An object that represents a slice of a comment. + class Comment + # The slice of the comment. + attr_reader slice: String + + # Initialize a new comment with the given slice. + # + # : (String slice) -> void + def initialize: (String slice) -> void + end + + private + + # Create comment objects from the given values. + # -- + # : (entry_value values) -> Array[Comment] + def comments: (entry_value values) -> Array[Comment] + end + + # A field representing the leading comments. + class LeadingCommentsField < CommentsField + # Fetches the leading comments of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A field representing the trailing comments. + class TrailingCommentsField < CommentsField + # Fetches the trailing comments of a value. + # -- + # : (_Value value) -> entry_values + def fields: (_Value value) -> entry_values + end + + # A repository is a configured collection of fields and a set of entries + # that knows how to reparse a source and reify the values. + class Repository + # Raised when multiple fields of the same type are configured on the same + # repository. + class ConfigurationError < StandardError + end + + # The source associated with this repository. This will be either a + # SourceFilepath (the most common use case) or a SourceString. + attr_reader source: Source + + # The fields that have been configured on this repository. + attr_reader fields: Hash[Symbol, _Field] + + # The entries that have been saved on this repository. + attr_reader entries: Hash[Integer, Hash[Symbol, Entry]] + + # Initialize a new repository with the given source. + # -- + # : (Source source) -> void + def initialize: (Source source) -> void + + # Create a code units cache for the given encoding from the source. + # -- + # : (Encoding encoding) -> _CodeUnitsCache + def code_units_cache: (Encoding encoding) -> _CodeUnitsCache + + # Configure the filepath field for this repository and return self. + # -- + # : () -> self + def filepath: () -> self + + # Configure the lines field for this repository and return self. + # -- + # : () -> self + def lines: () -> self + + # Configure the offsets field for this repository and return self. + # -- + # : () -> self + def offsets: () -> self + + # Configure the character offsets field for this repository and return + # self. + # -- + # : () -> self + def character_offsets: () -> self + + # Configure the code unit offsets field for this repository for a specific + # encoding and return self. + # -- + # : (Encoding encoding) -> self + def code_unit_offsets: (Encoding encoding) -> self + + # Configure the columns field for this repository and return self. + # -- + # : () -> self + def columns: () -> self + + # Configure the character columns field for this repository and return + # self. + # -- + # : () -> self + def character_columns: () -> self + + # Configure the code unit columns field for this repository for a specific + # encoding and return self. + # -- + # : (Encoding encoding) -> self + def code_unit_columns: (Encoding encoding) -> self + + # Configure the leading comments field for this repository and return + # self. + # -- + # : () -> self + def leading_comments: () -> self + + # Configure the trailing comments field for this repository and return + # self. + # -- + # : () -> self + def trailing_comments: () -> self + + # Configure both the leading and trailing comment fields for this + # repository and return self. + # -- + # : () -> self + def comments: () -> self + + # This method is called from nodes and locations when they want to enter + # themselves into the repository. It it internal-only and meant to be + # called from the #save* APIs. + # -- + # : (Integer node_id, Symbol field_name) -> Entry + def enter: (Integer node_id, Symbol field_name) -> Entry + + # This method is called from the entries in the repository when they need + # to reify their values. It is internal-only and meant to be called from + # the various value APIs. + # -- + # : () -> void + def reify!: () -> void + + private + + # Append the given field to the repository and return the repository so + # that these calls can be chained. + # -- + # : (Symbol name, _Field) -> self + def field: (Symbol name, _Field) -> self + end + + # Create a new repository for the given filepath. + # -- + # : (String value) -> Repository + def self.filepath: (String value) -> Repository + + # Create a new repository for the given string. + # -- + # : (String value) -> Repository + def self.string: (String value) -> Repository + end +end diff --git a/sig/generated/prism/serialize.rbs b/sig/generated/prism/serialize.rbs new file mode 100644 index 0000000000..468f18dd56 --- /dev/null +++ b/sig/generated/prism/serialize.rbs @@ -0,0 +1,186 @@ +# Generated from lib/prism/serialize.rb with RBS::Inline + +module Prism + # A module responsible for deserializing parse results. + module Serialize + # The major version of prism that we are expecting to find in the serialized + # strings. + MAJOR_VERSION: ::Integer + + # The minor version of prism that we are expecting to find in the serialized + # strings. + MINOR_VERSION: ::Integer + + # The patch version of prism that we are expecting to find in the serialized + # strings. + PATCH_VERSION: ::Integer + + # Deserialize the dumped output from a request to parse or parse_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> ParseResult + def self.load_parse: (String input, String serialized, bool freeze) -> ParseResult + + # Deserialize the dumped output from a request to lex or lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> LexResult + def self.load_lex: (String input, String serialized, bool freeze) -> LexResult + + # Deserialize the dumped output from a request to parse_comments or + # parse_file_comments. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> Array[Comment] + def self.load_parse_comments: (String input, String serialized, bool freeze) -> Array[Comment] + + # Deserialize the dumped output from a request to parse_lex or + # parse_lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + # -- + # : (String input, String serialized, bool freeze) -> ParseLexResult + def self.load_parse_lex: (String input, String serialized, bool freeze) -> ParseLexResult + + class ConstantPool + # :nodoc: + attr_reader size: Integer + + @input: String + + @serialized: String + + @base: Integer + + @pool: Array[Symbol?] + + # : (String input, String serialized, Integer base, Integer size) -> void + def initialize: (String input, String serialized, Integer base, Integer size) -> void + + # : (Integer index, Encoding encoding) -> Symbol + def get: (Integer index, Encoding encoding) -> Symbol + end + + FastStringIO: untyped + + class Loader + # :nodoc: + attr_reader input: String + + attr_reader io: StringIO + + attr_reader source: Source + + # : (Source source, String serialized) -> void + def initialize: (Source source, String serialized) -> void + + # : () -> bool + def eof?: () -> bool + + # : (ConstantPool constant_pool) -> void + def load_constant_pool: (ConstantPool constant_pool) -> void + + # : () -> void + def load_header: () -> void + + # : () -> Encoding + def load_encoding: () -> Encoding + + # : (bool freeze) -> Array[Integer] + def load_line_offsets: (bool freeze) -> Array[Integer] + + # : (bool freeze) -> Array[Comment] + def load_comments: (bool freeze) -> Array[Comment] + + # : (bool freeze) -> Array[MagicComment] + def load_magic_comments: (bool freeze) -> Array[MagicComment] + + DIAGNOSTIC_TYPES: Array[Symbol] + + # : () -> Symbol + def load_error_level: () -> Symbol + + # : (Encoding encoding, bool freeze) -> Array[ParseError] + def load_errors: (Encoding encoding, bool freeze) -> Array[ParseError] + + # : () -> Symbol + def load_warning_level: () -> Symbol + + # : (Encoding encoding, bool freeze) -> Array[ParseWarning] + def load_warnings: (Encoding encoding, bool freeze) -> Array[ParseWarning] + + # : () -> Array[[Token, Integer]] + def load_tokens: () -> Array[[ Token, Integer ]] + + # variable-length integer using https://en.wikipedia.org/wiki/LEB128 + # This is also what protobuf uses: https://protobuf.dev/programming-guides/encoding/#varints + # -- + # : () -> Integer + def load_varuint: () -> Integer + + # : () -> Integer + def load_varsint: () -> Integer + + # : () -> Integer + def load_integer: () -> Integer + + # : () -> Float + def load_double: () -> Float + + # : () -> Integer + def load_uint32: () -> Integer + + # : (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? + def load_optional_node: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? + + # : (Encoding encoding) -> String + def load_embedded_string: (Encoding encoding) -> String + + # : (Encoding encoding) -> String + def load_string: (Encoding encoding) -> String + + # : (bool freeze) -> Location + def load_location_object: (bool freeze) -> Location + + # Load a location object from the serialized data. Note that we are lying + # about the signature a bit here, because we sometimes load it as a packed + # integer instead of an object. + # -- + # : (bool freeze) -> Location + def load_location: (bool freeze) -> Location + + # Load an optional location object from the serialized data if it is + # present. Note that we are lying about the signature a bit here, because + # we sometimes load it as a packed integer instead of an object. + # -- + # : (bool freeze) -> Location? + def load_optional_location: (bool freeze) -> Location? + + # : (bool freeze) -> Location? + def load_optional_location_object: (bool freeze) -> Location? + + # : (ConstantPool constant_pool, Encoding encoding) -> Symbol + def load_constant: (ConstantPool constant_pool, Encoding encoding) -> Symbol + + # : (ConstantPool constant_pool, Encoding encoding) -> Symbol? + def load_optional_constant: (ConstantPool constant_pool, Encoding encoding) -> Symbol? + + # : (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node + def load_node: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node + + @load_node_lambdas: Array[Proc] + + def define_load_node_lambdas: () -> void + end + + # The token types that can be indexed by their enum values. + TOKEN_TYPES: Array[Symbol?] + end +end diff --git a/sig/generated/prism/string_query.rbs b/sig/generated/prism/string_query.rbs new file mode 100644 index 0000000000..de2183a731 --- /dev/null +++ b/sig/generated/prism/string_query.rbs @@ -0,0 +1,36 @@ +# Generated from lib/prism/string_query.rb with RBS::Inline + +module Prism + # Query methods that allow categorizing strings based on their context for + # where they could be valid in a Ruby syntax tree. + class StringQuery + def self.local?: (String string) -> bool + + def self.constant?: (String string) -> bool + + def self.method_name?: (String string) -> bool + + # The string that this query is wrapping. + attr_reader string: String + + # Initialize a new query with the given string. + # -- + # : (String string) -> void + def initialize: (String string) -> void + + # Whether or not this string is a valid local variable name. + # -- + # : () -> bool + def local?: () -> bool + + # Whether or not this string is a valid constant name. + # -- + # : () -> bool + def constant?: () -> bool + + # Whether or not this string is a valid method name. + # -- + # : () -> bool + def method_name?: () -> bool + end +end diff --git a/sig/generated/prism/translation.rbs b/sig/generated/prism/translation.rbs new file mode 100644 index 0000000000..09971a2971 --- /dev/null +++ b/sig/generated/prism/translation.rbs @@ -0,0 +1,8 @@ +# Generated from lib/prism/translation.rb with RBS::Inline + +module Prism + # This module is responsible for converting the prism syntax tree into other + # syntax trees. + module Translation + end +end diff --git a/sig/generated/prism/visitor.rbs b/sig/generated/prism/visitor.rbs new file mode 100644 index 0000000000..ec65adbb29 --- /dev/null +++ b/sig/generated/prism/visitor.rbs @@ -0,0 +1,1111 @@ +# Generated from lib/prism/visitor.rb with RBS::Inline + +module Prism + interface _Visitor + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> void + + def visit_alias_method_node: (AliasMethodNode) -> void + + def visit_alternation_pattern_node: (AlternationPatternNode) -> void + + def visit_and_node: (AndNode) -> void + + def visit_arguments_node: (ArgumentsNode) -> void + + def visit_array_node: (ArrayNode) -> void + + def visit_array_pattern_node: (ArrayPatternNode) -> void + + def visit_assoc_node: (AssocNode) -> void + + def visit_assoc_splat_node: (AssocSplatNode) -> void + + def visit_back_reference_read_node: (BackReferenceReadNode) -> void + + def visit_begin_node: (BeginNode) -> void + + def visit_block_argument_node: (BlockArgumentNode) -> void + + def visit_block_local_variable_node: (BlockLocalVariableNode) -> void + + def visit_block_node: (BlockNode) -> void + + def visit_block_parameter_node: (BlockParameterNode) -> void + + def visit_block_parameters_node: (BlockParametersNode) -> void + + def visit_break_node: (BreakNode) -> void + + def visit_call_and_write_node: (CallAndWriteNode) -> void + + def visit_call_node: (CallNode) -> void + + def visit_call_operator_write_node: (CallOperatorWriteNode) -> void + + def visit_call_or_write_node: (CallOrWriteNode) -> void + + def visit_call_target_node: (CallTargetNode) -> void + + def visit_capture_pattern_node: (CapturePatternNode) -> void + + def visit_case_match_node: (CaseMatchNode) -> void + + def visit_case_node: (CaseNode) -> void + + def visit_class_node: (ClassNode) -> void + + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> void + + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> void + + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> void + + def visit_class_variable_read_node: (ClassVariableReadNode) -> void + + def visit_class_variable_target_node: (ClassVariableTargetNode) -> void + + def visit_class_variable_write_node: (ClassVariableWriteNode) -> void + + def visit_constant_and_write_node: (ConstantAndWriteNode) -> void + + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> void + + def visit_constant_or_write_node: (ConstantOrWriteNode) -> void + + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> void + + def visit_constant_path_node: (ConstantPathNode) -> void + + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> void + + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> void + + def visit_constant_path_target_node: (ConstantPathTargetNode) -> void + + def visit_constant_path_write_node: (ConstantPathWriteNode) -> void + + def visit_constant_read_node: (ConstantReadNode) -> void + + def visit_constant_target_node: (ConstantTargetNode) -> void + + def visit_constant_write_node: (ConstantWriteNode) -> void + + def visit_def_node: (DefNode) -> void + + def visit_defined_node: (DefinedNode) -> void + + def visit_else_node: (ElseNode) -> void + + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> void + + def visit_embedded_variable_node: (EmbeddedVariableNode) -> void + + def visit_ensure_node: (EnsureNode) -> void + + def visit_false_node: (FalseNode) -> void + + def visit_find_pattern_node: (FindPatternNode) -> void + + def visit_flip_flop_node: (FlipFlopNode) -> void + + def visit_float_node: (FloatNode) -> void + + def visit_for_node: (ForNode) -> void + + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> void + + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> void + + def visit_forwarding_super_node: (ForwardingSuperNode) -> void + + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> void + + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> void + + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> void + + def visit_global_variable_read_node: (GlobalVariableReadNode) -> void + + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> void + + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> void + + def visit_hash_node: (HashNode) -> void + + def visit_hash_pattern_node: (HashPatternNode) -> void + + def visit_if_node: (IfNode) -> void + + def visit_imaginary_node: (ImaginaryNode) -> void + + def visit_implicit_node: (ImplicitNode) -> void + + def visit_implicit_rest_node: (ImplicitRestNode) -> void + + def visit_in_node: (InNode) -> void + + def visit_index_and_write_node: (IndexAndWriteNode) -> void + + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> void + + def visit_index_or_write_node: (IndexOrWriteNode) -> void + + def visit_index_target_node: (IndexTargetNode) -> void + + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> void + + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> void + + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> void + + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> void + + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> void + + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> void + + def visit_integer_node: (IntegerNode) -> void + + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> void + + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> void + + def visit_interpolated_string_node: (InterpolatedStringNode) -> void + + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> void + + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> void + + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> void + + def visit_it_parameters_node: (ItParametersNode) -> void + + def visit_keyword_hash_node: (KeywordHashNode) -> void + + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> void + + def visit_lambda_node: (LambdaNode) -> void + + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> void + + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> void + + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> void + + def visit_local_variable_read_node: (LocalVariableReadNode) -> void + + def visit_local_variable_target_node: (LocalVariableTargetNode) -> void + + def visit_local_variable_write_node: (LocalVariableWriteNode) -> void + + def visit_match_last_line_node: (MatchLastLineNode) -> void + + def visit_match_predicate_node: (MatchPredicateNode) -> void + + def visit_match_required_node: (MatchRequiredNode) -> void + + def visit_match_write_node: (MatchWriteNode) -> void + + def visit_missing_node: (MissingNode) -> void + + def visit_module_node: (ModuleNode) -> void + + def visit_multi_target_node: (MultiTargetNode) -> void + + def visit_multi_write_node: (MultiWriteNode) -> void + + def visit_next_node: (NextNode) -> void + + def visit_nil_node: (NilNode) -> void + + def visit_no_block_parameter_node: (NoBlockParameterNode) -> void + + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> void + + def visit_numbered_parameters_node: (NumberedParametersNode) -> void + + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> void + + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> void + + def visit_optional_parameter_node: (OptionalParameterNode) -> void + + def visit_or_node: (OrNode) -> void + + def visit_parameters_node: (ParametersNode) -> void + + def visit_parentheses_node: (ParenthesesNode) -> void + + def visit_pinned_expression_node: (PinnedExpressionNode) -> void + + def visit_pinned_variable_node: (PinnedVariableNode) -> void + + def visit_post_execution_node: (PostExecutionNode) -> void + + def visit_pre_execution_node: (PreExecutionNode) -> void + + def visit_program_node: (ProgramNode) -> void + + def visit_range_node: (RangeNode) -> void + + def visit_rational_node: (RationalNode) -> void + + def visit_redo_node: (RedoNode) -> void + + def visit_regular_expression_node: (RegularExpressionNode) -> void + + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> void + + def visit_required_parameter_node: (RequiredParameterNode) -> void + + def visit_rescue_modifier_node: (RescueModifierNode) -> void + + def visit_rescue_node: (RescueNode) -> void + + def visit_rest_parameter_node: (RestParameterNode) -> void + + def visit_retry_node: (RetryNode) -> void + + def visit_return_node: (ReturnNode) -> void + + def visit_self_node: (SelfNode) -> void + + def visit_shareable_constant_node: (ShareableConstantNode) -> void + + def visit_singleton_class_node: (SingletonClassNode) -> void + + def visit_source_encoding_node: (SourceEncodingNode) -> void + + def visit_source_file_node: (SourceFileNode) -> void + + def visit_source_line_node: (SourceLineNode) -> void + + def visit_splat_node: (SplatNode) -> void + + def visit_statements_node: (StatementsNode) -> void + + def visit_string_node: (StringNode) -> void + + def visit_super_node: (SuperNode) -> void + + def visit_symbol_node: (SymbolNode) -> void + + def visit_true_node: (TrueNode) -> void + + def visit_undef_node: (UndefNode) -> void + + def visit_unless_node: (UnlessNode) -> void + + def visit_until_node: (UntilNode) -> void + + def visit_when_node: (WhenNode) -> void + + def visit_while_node: (WhileNode) -> void + + def visit_x_string_node: (XStringNode) -> void + + def visit_yield_node: (YieldNode) -> void + end + + # A class that knows how to walk down the tree. None of the individual visit + # methods are implemented on this visitor, so it forces the consumer to + # implement each one that they need. For a default implementation that + # continues walking the tree, see the Visitor class. + class BasicVisitor + # Calls `accept` on the given node if it is not `nil`, which in turn should + # call back into this visitor by calling the appropriate `visit_*` method. + # -- + # : (node? node) -> void + def visit: (node? node) -> void + + # Visits each node in `nodes` by calling `accept` on each one. + # -- + # : (Array[node?] nodes) -> void + def visit_all: (Array[node?] nodes) -> void + + # Visits the child nodes of `node` by calling `accept` on each one. + # -- + # : (node node) -> void + def visit_child_nodes: (node node) -> void + end + + # A visitor is a class that provides a default implementation for every accept + # method defined on the nodes. This means it can walk a tree without the + # caller needing to define any special handling. This allows you to handle a + # subset of the tree, while still walking the whole tree. + # + # For example, to find all of the method calls that call the `foo` method, you + # could write: + # + # class FooCalls < Prism::Visitor + # def visit_call_node(node) + # if node.name == :foo + # # Do something with the node + # end + # + # # Call super so that the visitor continues walking the tree + # super + # end + # end + class Visitor < BasicVisitor + # Visit a AliasGlobalVariableNode node + # -- + # : (AliasGlobalVariableNode node) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode node) -> void + + # Visit a AliasMethodNode node + # -- + # : (AliasMethodNode node) -> void + def visit_alias_method_node: (AliasMethodNode node) -> void + + # Visit a AlternationPatternNode node + # -- + # : (AlternationPatternNode node) -> void + def visit_alternation_pattern_node: (AlternationPatternNode node) -> void + + # Visit a AndNode node + # -- + # : (AndNode node) -> void + def visit_and_node: (AndNode node) -> void + + # Visit a ArgumentsNode node + # -- + # : (ArgumentsNode node) -> void + def visit_arguments_node: (ArgumentsNode node) -> void + + # Visit a ArrayNode node + # -- + # : (ArrayNode node) -> void + def visit_array_node: (ArrayNode node) -> void + + # Visit a ArrayPatternNode node + # -- + # : (ArrayPatternNode node) -> void + def visit_array_pattern_node: (ArrayPatternNode node) -> void + + # Visit a AssocNode node + # -- + # : (AssocNode node) -> void + def visit_assoc_node: (AssocNode node) -> void + + # Visit a AssocSplatNode node + # -- + # : (AssocSplatNode node) -> void + def visit_assoc_splat_node: (AssocSplatNode node) -> void + + # Visit a BackReferenceReadNode node + # -- + # : (BackReferenceReadNode node) -> void + def visit_back_reference_read_node: (BackReferenceReadNode node) -> void + + # Visit a BeginNode node + # -- + # : (BeginNode node) -> void + def visit_begin_node: (BeginNode node) -> void + + # Visit a BlockArgumentNode node + # -- + # : (BlockArgumentNode node) -> void + def visit_block_argument_node: (BlockArgumentNode node) -> void + + # Visit a BlockLocalVariableNode node + # -- + # : (BlockLocalVariableNode node) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode node) -> void + + # Visit a BlockNode node + # -- + # : (BlockNode node) -> void + def visit_block_node: (BlockNode node) -> void + + # Visit a BlockParameterNode node + # -- + # : (BlockParameterNode node) -> void + def visit_block_parameter_node: (BlockParameterNode node) -> void + + # Visit a BlockParametersNode node + # -- + # : (BlockParametersNode node) -> void + def visit_block_parameters_node: (BlockParametersNode node) -> void + + # Visit a BreakNode node + # -- + # : (BreakNode node) -> void + def visit_break_node: (BreakNode node) -> void + + # Visit a CallAndWriteNode node + # -- + # : (CallAndWriteNode node) -> void + def visit_call_and_write_node: (CallAndWriteNode node) -> void + + # Visit a CallNode node + # -- + # : (CallNode node) -> void + def visit_call_node: (CallNode node) -> void + + # Visit a CallOperatorWriteNode node + # -- + # : (CallOperatorWriteNode node) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode node) -> void + + # Visit a CallOrWriteNode node + # -- + # : (CallOrWriteNode node) -> void + def visit_call_or_write_node: (CallOrWriteNode node) -> void + + # Visit a CallTargetNode node + # -- + # : (CallTargetNode node) -> void + def visit_call_target_node: (CallTargetNode node) -> void + + # Visit a CapturePatternNode node + # -- + # : (CapturePatternNode node) -> void + def visit_capture_pattern_node: (CapturePatternNode node) -> void + + # Visit a CaseMatchNode node + # -- + # : (CaseMatchNode node) -> void + def visit_case_match_node: (CaseMatchNode node) -> void + + # Visit a CaseNode node + # -- + # : (CaseNode node) -> void + def visit_case_node: (CaseNode node) -> void + + # Visit a ClassNode node + # -- + # : (ClassNode node) -> void + def visit_class_node: (ClassNode node) -> void + + # Visit a ClassVariableAndWriteNode node + # -- + # : (ClassVariableAndWriteNode node) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode node) -> void + + # Visit a ClassVariableOperatorWriteNode node + # -- + # : (ClassVariableOperatorWriteNode node) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode node) -> void + + # Visit a ClassVariableOrWriteNode node + # -- + # : (ClassVariableOrWriteNode node) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode node) -> void + + # Visit a ClassVariableReadNode node + # -- + # : (ClassVariableReadNode node) -> void + def visit_class_variable_read_node: (ClassVariableReadNode node) -> void + + # Visit a ClassVariableTargetNode node + # -- + # : (ClassVariableTargetNode node) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode node) -> void + + # Visit a ClassVariableWriteNode node + # -- + # : (ClassVariableWriteNode node) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode node) -> void + + # Visit a ConstantAndWriteNode node + # -- + # : (ConstantAndWriteNode node) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode node) -> void + + # Visit a ConstantOperatorWriteNode node + # -- + # : (ConstantOperatorWriteNode node) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode node) -> void + + # Visit a ConstantOrWriteNode node + # -- + # : (ConstantOrWriteNode node) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode node) -> void + + # Visit a ConstantPathAndWriteNode node + # -- + # : (ConstantPathAndWriteNode node) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode node) -> void + + # Visit a ConstantPathNode node + # -- + # : (ConstantPathNode node) -> void + def visit_constant_path_node: (ConstantPathNode node) -> void + + # Visit a ConstantPathOperatorWriteNode node + # -- + # : (ConstantPathOperatorWriteNode node) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode node) -> void + + # Visit a ConstantPathOrWriteNode node + # -- + # : (ConstantPathOrWriteNode node) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode node) -> void + + # Visit a ConstantPathTargetNode node + # -- + # : (ConstantPathTargetNode node) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode node) -> void + + # Visit a ConstantPathWriteNode node + # -- + # : (ConstantPathWriteNode node) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode node) -> void + + # Visit a ConstantReadNode node + # -- + # : (ConstantReadNode node) -> void + def visit_constant_read_node: (ConstantReadNode node) -> void + + # Visit a ConstantTargetNode node + # -- + # : (ConstantTargetNode node) -> void + def visit_constant_target_node: (ConstantTargetNode node) -> void + + # Visit a ConstantWriteNode node + # -- + # : (ConstantWriteNode node) -> void + def visit_constant_write_node: (ConstantWriteNode node) -> void + + # Visit a DefNode node + # -- + # : (DefNode node) -> void + def visit_def_node: (DefNode node) -> void + + # Visit a DefinedNode node + # -- + # : (DefinedNode node) -> void + def visit_defined_node: (DefinedNode node) -> void + + # Visit a ElseNode node + # -- + # : (ElseNode node) -> void + def visit_else_node: (ElseNode node) -> void + + # Visit a EmbeddedStatementsNode node + # -- + # : (EmbeddedStatementsNode node) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode node) -> void + + # Visit a EmbeddedVariableNode node + # -- + # : (EmbeddedVariableNode node) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode node) -> void + + # Visit a EnsureNode node + # -- + # : (EnsureNode node) -> void + def visit_ensure_node: (EnsureNode node) -> void + + # Visit a FalseNode node + # -- + # : (FalseNode node) -> void + def visit_false_node: (FalseNode node) -> void + + # Visit a FindPatternNode node + # -- + # : (FindPatternNode node) -> void + def visit_find_pattern_node: (FindPatternNode node) -> void + + # Visit a FlipFlopNode node + # -- + # : (FlipFlopNode node) -> void + def visit_flip_flop_node: (FlipFlopNode node) -> void + + # Visit a FloatNode node + # -- + # : (FloatNode node) -> void + def visit_float_node: (FloatNode node) -> void + + # Visit a ForNode node + # -- + # : (ForNode node) -> void + def visit_for_node: (ForNode node) -> void + + # Visit a ForwardingArgumentsNode node + # -- + # : (ForwardingArgumentsNode node) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode node) -> void + + # Visit a ForwardingParameterNode node + # -- + # : (ForwardingParameterNode node) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode node) -> void + + # Visit a ForwardingSuperNode node + # -- + # : (ForwardingSuperNode node) -> void + def visit_forwarding_super_node: (ForwardingSuperNode node) -> void + + # Visit a GlobalVariableAndWriteNode node + # -- + # : (GlobalVariableAndWriteNode node) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode node) -> void + + # Visit a GlobalVariableOperatorWriteNode node + # -- + # : (GlobalVariableOperatorWriteNode node) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode node) -> void + + # Visit a GlobalVariableOrWriteNode node + # -- + # : (GlobalVariableOrWriteNode node) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode node) -> void + + # Visit a GlobalVariableReadNode node + # -- + # : (GlobalVariableReadNode node) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode node) -> void + + # Visit a GlobalVariableTargetNode node + # -- + # : (GlobalVariableTargetNode node) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode node) -> void + + # Visit a GlobalVariableWriteNode node + # -- + # : (GlobalVariableWriteNode node) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode node) -> void + + # Visit a HashNode node + # -- + # : (HashNode node) -> void + def visit_hash_node: (HashNode node) -> void + + # Visit a HashPatternNode node + # -- + # : (HashPatternNode node) -> void + def visit_hash_pattern_node: (HashPatternNode node) -> void + + # Visit a IfNode node + # -- + # : (IfNode node) -> void + def visit_if_node: (IfNode node) -> void + + # Visit a ImaginaryNode node + # -- + # : (ImaginaryNode node) -> void + def visit_imaginary_node: (ImaginaryNode node) -> void + + # Visit a ImplicitNode node + # -- + # : (ImplicitNode node) -> void + def visit_implicit_node: (ImplicitNode node) -> void + + # Visit a ImplicitRestNode node + # -- + # : (ImplicitRestNode node) -> void + def visit_implicit_rest_node: (ImplicitRestNode node) -> void + + # Visit a InNode node + # -- + # : (InNode node) -> void + def visit_in_node: (InNode node) -> void + + # Visit a IndexAndWriteNode node + # -- + # : (IndexAndWriteNode node) -> void + def visit_index_and_write_node: (IndexAndWriteNode node) -> void + + # Visit a IndexOperatorWriteNode node + # -- + # : (IndexOperatorWriteNode node) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode node) -> void + + # Visit a IndexOrWriteNode node + # -- + # : (IndexOrWriteNode node) -> void + def visit_index_or_write_node: (IndexOrWriteNode node) -> void + + # Visit a IndexTargetNode node + # -- + # : (IndexTargetNode node) -> void + def visit_index_target_node: (IndexTargetNode node) -> void + + # Visit a InstanceVariableAndWriteNode node + # -- + # : (InstanceVariableAndWriteNode node) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode node) -> void + + # Visit a InstanceVariableOperatorWriteNode node + # -- + # : (InstanceVariableOperatorWriteNode node) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode node) -> void + + # Visit a InstanceVariableOrWriteNode node + # -- + # : (InstanceVariableOrWriteNode node) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode node) -> void + + # Visit a InstanceVariableReadNode node + # -- + # : (InstanceVariableReadNode node) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode node) -> void + + # Visit a InstanceVariableTargetNode node + # -- + # : (InstanceVariableTargetNode node) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode node) -> void + + # Visit a InstanceVariableWriteNode node + # -- + # : (InstanceVariableWriteNode node) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode node) -> void + + # Visit a IntegerNode node + # -- + # : (IntegerNode node) -> void + def visit_integer_node: (IntegerNode node) -> void + + # Visit a InterpolatedMatchLastLineNode node + # -- + # : (InterpolatedMatchLastLineNode node) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode node) -> void + + # Visit a InterpolatedRegularExpressionNode node + # -- + # : (InterpolatedRegularExpressionNode node) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode node) -> void + + # Visit a InterpolatedStringNode node + # -- + # : (InterpolatedStringNode node) -> void + def visit_interpolated_string_node: (InterpolatedStringNode node) -> void + + # Visit a InterpolatedSymbolNode node + # -- + # : (InterpolatedSymbolNode node) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode node) -> void + + # Visit a InterpolatedXStringNode node + # -- + # : (InterpolatedXStringNode node) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode node) -> void + + # Visit a ItLocalVariableReadNode node + # -- + # : (ItLocalVariableReadNode node) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode node) -> void + + # Visit a ItParametersNode node + # -- + # : (ItParametersNode node) -> void + def visit_it_parameters_node: (ItParametersNode node) -> void + + # Visit a KeywordHashNode node + # -- + # : (KeywordHashNode node) -> void + def visit_keyword_hash_node: (KeywordHashNode node) -> void + + # Visit a KeywordRestParameterNode node + # -- + # : (KeywordRestParameterNode node) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode node) -> void + + # Visit a LambdaNode node + # -- + # : (LambdaNode node) -> void + def visit_lambda_node: (LambdaNode node) -> void + + # Visit a LocalVariableAndWriteNode node + # -- + # : (LocalVariableAndWriteNode node) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode node) -> void + + # Visit a LocalVariableOperatorWriteNode node + # -- + # : (LocalVariableOperatorWriteNode node) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode node) -> void + + # Visit a LocalVariableOrWriteNode node + # -- + # : (LocalVariableOrWriteNode node) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode node) -> void + + # Visit a LocalVariableReadNode node + # -- + # : (LocalVariableReadNode node) -> void + def visit_local_variable_read_node: (LocalVariableReadNode node) -> void + + # Visit a LocalVariableTargetNode node + # -- + # : (LocalVariableTargetNode node) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode node) -> void + + # Visit a LocalVariableWriteNode node + # -- + # : (LocalVariableWriteNode node) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode node) -> void + + # Visit a MatchLastLineNode node + # -- + # : (MatchLastLineNode node) -> void + def visit_match_last_line_node: (MatchLastLineNode node) -> void + + # Visit a MatchPredicateNode node + # -- + # : (MatchPredicateNode node) -> void + def visit_match_predicate_node: (MatchPredicateNode node) -> void + + # Visit a MatchRequiredNode node + # -- + # : (MatchRequiredNode node) -> void + def visit_match_required_node: (MatchRequiredNode node) -> void + + # Visit a MatchWriteNode node + # -- + # : (MatchWriteNode node) -> void + def visit_match_write_node: (MatchWriteNode node) -> void + + # Visit a MissingNode node + # -- + # : (MissingNode node) -> void + def visit_missing_node: (MissingNode node) -> void + + # Visit a ModuleNode node + # -- + # : (ModuleNode node) -> void + def visit_module_node: (ModuleNode node) -> void + + # Visit a MultiTargetNode node + # -- + # : (MultiTargetNode node) -> void + def visit_multi_target_node: (MultiTargetNode node) -> void + + # Visit a MultiWriteNode node + # -- + # : (MultiWriteNode node) -> void + def visit_multi_write_node: (MultiWriteNode node) -> void + + # Visit a NextNode node + # -- + # : (NextNode node) -> void + def visit_next_node: (NextNode node) -> void + + # Visit a NilNode node + # -- + # : (NilNode node) -> void + def visit_nil_node: (NilNode node) -> void + + # Visit a NoBlockParameterNode node + # -- + # : (NoBlockParameterNode node) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode node) -> void + + # Visit a NoKeywordsParameterNode node + # -- + # : (NoKeywordsParameterNode node) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode node) -> void + + # Visit a NumberedParametersNode node + # -- + # : (NumberedParametersNode node) -> void + def visit_numbered_parameters_node: (NumberedParametersNode node) -> void + + # Visit a NumberedReferenceReadNode node + # -- + # : (NumberedReferenceReadNode node) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode node) -> void + + # Visit a OptionalKeywordParameterNode node + # -- + # : (OptionalKeywordParameterNode node) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode node) -> void + + # Visit a OptionalParameterNode node + # -- + # : (OptionalParameterNode node) -> void + def visit_optional_parameter_node: (OptionalParameterNode node) -> void + + # Visit a OrNode node + # -- + # : (OrNode node) -> void + def visit_or_node: (OrNode node) -> void + + # Visit a ParametersNode node + # -- + # : (ParametersNode node) -> void + def visit_parameters_node: (ParametersNode node) -> void + + # Visit a ParenthesesNode node + # -- + # : (ParenthesesNode node) -> void + def visit_parentheses_node: (ParenthesesNode node) -> void + + # Visit a PinnedExpressionNode node + # -- + # : (PinnedExpressionNode node) -> void + def visit_pinned_expression_node: (PinnedExpressionNode node) -> void + + # Visit a PinnedVariableNode node + # -- + # : (PinnedVariableNode node) -> void + def visit_pinned_variable_node: (PinnedVariableNode node) -> void + + # Visit a PostExecutionNode node + # -- + # : (PostExecutionNode node) -> void + def visit_post_execution_node: (PostExecutionNode node) -> void + + # Visit a PreExecutionNode node + # -- + # : (PreExecutionNode node) -> void + def visit_pre_execution_node: (PreExecutionNode node) -> void + + # Visit a ProgramNode node + # -- + # : (ProgramNode node) -> void + def visit_program_node: (ProgramNode node) -> void + + # Visit a RangeNode node + # -- + # : (RangeNode node) -> void + def visit_range_node: (RangeNode node) -> void + + # Visit a RationalNode node + # -- + # : (RationalNode node) -> void + def visit_rational_node: (RationalNode node) -> void + + # Visit a RedoNode node + # -- + # : (RedoNode node) -> void + def visit_redo_node: (RedoNode node) -> void + + # Visit a RegularExpressionNode node + # -- + # : (RegularExpressionNode node) -> void + def visit_regular_expression_node: (RegularExpressionNode node) -> void + + # Visit a RequiredKeywordParameterNode node + # -- + # : (RequiredKeywordParameterNode node) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode node) -> void + + # Visit a RequiredParameterNode node + # -- + # : (RequiredParameterNode node) -> void + def visit_required_parameter_node: (RequiredParameterNode node) -> void + + # Visit a RescueModifierNode node + # -- + # : (RescueModifierNode node) -> void + def visit_rescue_modifier_node: (RescueModifierNode node) -> void + + # Visit a RescueNode node + # -- + # : (RescueNode node) -> void + def visit_rescue_node: (RescueNode node) -> void + + # Visit a RestParameterNode node + # -- + # : (RestParameterNode node) -> void + def visit_rest_parameter_node: (RestParameterNode node) -> void + + # Visit a RetryNode node + # -- + # : (RetryNode node) -> void + def visit_retry_node: (RetryNode node) -> void + + # Visit a ReturnNode node + # -- + # : (ReturnNode node) -> void + def visit_return_node: (ReturnNode node) -> void + + # Visit a SelfNode node + # -- + # : (SelfNode node) -> void + def visit_self_node: (SelfNode node) -> void + + # Visit a ShareableConstantNode node + # -- + # : (ShareableConstantNode node) -> void + def visit_shareable_constant_node: (ShareableConstantNode node) -> void + + # Visit a SingletonClassNode node + # -- + # : (SingletonClassNode node) -> void + def visit_singleton_class_node: (SingletonClassNode node) -> void + + # Visit a SourceEncodingNode node + # -- + # : (SourceEncodingNode node) -> void + def visit_source_encoding_node: (SourceEncodingNode node) -> void + + # Visit a SourceFileNode node + # -- + # : (SourceFileNode node) -> void + def visit_source_file_node: (SourceFileNode node) -> void + + # Visit a SourceLineNode node + # -- + # : (SourceLineNode node) -> void + def visit_source_line_node: (SourceLineNode node) -> void + + # Visit a SplatNode node + # -- + # : (SplatNode node) -> void + def visit_splat_node: (SplatNode node) -> void + + # Visit a StatementsNode node + # -- + # : (StatementsNode node) -> void + def visit_statements_node: (StatementsNode node) -> void + + # Visit a StringNode node + # -- + # : (StringNode node) -> void + def visit_string_node: (StringNode node) -> void + + # Visit a SuperNode node + # -- + # : (SuperNode node) -> void + def visit_super_node: (SuperNode node) -> void + + # Visit a SymbolNode node + # -- + # : (SymbolNode node) -> void + def visit_symbol_node: (SymbolNode node) -> void + + # Visit a TrueNode node + # -- + # : (TrueNode node) -> void + def visit_true_node: (TrueNode node) -> void + + # Visit a UndefNode node + # -- + # : (UndefNode node) -> void + def visit_undef_node: (UndefNode node) -> void + + # Visit a UnlessNode node + # -- + # : (UnlessNode node) -> void + def visit_unless_node: (UnlessNode node) -> void + + # Visit a UntilNode node + # -- + # : (UntilNode node) -> void + def visit_until_node: (UntilNode node) -> void + + # Visit a WhenNode node + # -- + # : (WhenNode node) -> void + def visit_when_node: (WhenNode node) -> void + + # Visit a WhileNode node + # -- + # : (WhileNode node) -> void + def visit_while_node: (WhileNode node) -> void + + # Visit a XStringNode node + # -- + # : (XStringNode node) -> void + def visit_x_string_node: (XStringNode node) -> void + + # Visit a YieldNode node + # -- + # : (YieldNode node) -> void + def visit_yield_node: (YieldNode node) -> void + end +end diff --git a/sig/prism/_private/node.rbs b/sig/prism/_private/node.rbs deleted file mode 100644 index b5918a7133..0000000000 --- a/sig/prism/_private/node.rbs +++ /dev/null @@ -1,8 +0,0 @@ -module Prism - class Node - @newline_flag: bool - - def newline_flag?: () -> bool - def newline_flag!: (Array[bool] lines) -> void - end -end diff --git a/sig/prism/_private/node_ext.rbs b/sig/prism/_private/node_ext.rbs deleted file mode 100644 index 82e08f4263..0000000000 --- a/sig/prism/_private/node_ext.rbs +++ /dev/null @@ -1,9 +0,0 @@ -module Prism - module RegularExpressionOptions: InterpolatedMatchLastLineNode, InterpolatedRegularExpressionNode, MatchLastLineNode, RegularExpressionNode - def options: () -> Integer - end - - module HeredocQuery: InterpolatedStringNode, InterpolatedXStringNode, StringNode, XStringNode - def heredoc?: () -> bool? - end -end diff --git a/sig/prism/_private/parse_result.rbs b/sig/prism/_private/parse_result.rbs deleted file mode 100644 index 380b6f9dd6..0000000000 --- a/sig/prism/_private/parse_result.rbs +++ /dev/null @@ -1,50 +0,0 @@ -module Prism - class Source - private - - def find_line: (Integer) -> Integer - end - - class CodeUnitsCache - class UTF16Counter - def initialize: (String source, Encoding encoding) -> void - def count: (Integer byte_offset, Integer byte_length) -> Integer - end - - class LengthCounter - def initialize: (String source, Encoding encoding) -> void - def count: (Integer byte_offset, Integer byte_length) -> Integer - end - end - - class Location - private - - def source!: () -> Source - end - - class ParseResult - def attach_comments!: () -> void - def mark_newlines!: () -> untyped - - class Errors - attr_reader parse_result: ParseResult - - def initialize: (ParseResult parse_result) -> void - def format: () -> String - end - - class Newlines < Visitor - @newline_marked: Array[bool] - - # Create a new Newlines visitor with the given newline offsets. - def initialize: (Array[bool] newline_marked) -> void - - def visit_block_node: (BlockNode node) -> void - def visit_lambda_node: (LambdaNode node) -> void - def visit_if_node: (IfNode node) -> void - def visit_unless_node: (UnlessNode node) -> void - def visit_statements_node: (StatementsNode node) -> void - end - end -end diff --git a/sig/prism/_private/pattern.rbs b/sig/prism/_private/pattern.rbs deleted file mode 100644 index 244206d15d..0000000000 --- a/sig/prism/_private/pattern.rbs +++ /dev/null @@ -1,26 +0,0 @@ -module Prism - class Pattern - class CompilationError < StandardError - def initialize: (String) -> void - end - - @compiled: Proc? - - private - - def combine_and: (Proc, Proc) -> Proc - def combine_or: (Proc, Proc) -> Proc - def compile_error: (Prism::node?) -> Proc - def compile_array_pattern_node: (ArrayPatternNode) -> Proc - def compile_alternation_pattern_node: (AlternationPatternNode) -> Proc - def compile_constant_path_node: (ConstantPathNode) -> Proc - def compile_constant_read_node: (ConstantReadNode) -> Proc - def compile_constant_name: (Prism::node, Symbol) -> Proc - def compile_hash_pattern_node: (HashPatternNode) -> Proc - def compile_nil_node: (NilNode) -> Proc - def compile_regular_expression_node: (RegularExpressionNode) -> Proc - def compile_string_node: (StringNode) -> Proc - def compile_symbol_node: (SymbolNode) -> Proc - def compile_node: (Prism::node?) -> Proc - end -end diff --git a/sig/prism/_private/relocation.rbs b/sig/prism/_private/relocation.rbs deleted file mode 100644 index fda123bb37..0000000000 --- a/sig/prism/_private/relocation.rbs +++ /dev/null @@ -1,12 +0,0 @@ -module Prism - module Relocation - class Entry - def reify!: (entry_values values) -> void - end - - class Repository - def enter: (Integer node_id, Symbol field_name) -> Entry - def reify!: () -> void - end - end -end diff --git a/sig/prism/_private/string_query.rbs b/sig/prism/_private/string_query.rbs deleted file mode 100644 index 47ea2ca1a0..0000000000 --- a/sig/prism/_private/string_query.rbs +++ /dev/null @@ -1,7 +0,0 @@ -module Prism - class StringQuery - def self.local?: (String string) -> bool - def self.constant?: (String string) -> bool - def self.method_name?: (String string) -> bool - end -end diff --git a/sig/prism/compiler.rbs b/sig/prism/compiler.rbs deleted file mode 100644 index 1afa7db74d..0000000000 --- a/sig/prism/compiler.rbs +++ /dev/null @@ -1,9 +0,0 @@ -module Prism - class Compiler - include _Visitor - - def visit: (Prism::node?) -> untyped - def visit_all: (Array[Prism::node?]) -> untyped - def visit_child_nodes: (Prism::node) -> void - end -end diff --git a/sig/prism/dispatcher.rbs b/sig/prism/dispatcher.rbs deleted file mode 100644 index f58b8661f3..0000000000 --- a/sig/prism/dispatcher.rbs +++ /dev/null @@ -1,19 +0,0 @@ -module Prism - class Dispatcher < Visitor - attr_reader listeners: Hash[Symbol, Array[untyped]] - - def initialize: () -> void - def register: (untyped, *Symbol) -> void - def register_public_methods: (untyped) -> void - def dispatch: (Prism::node) -> void - def dispatch_once: (Prism::node) -> void - - private def register_events: (untyped, Array[Symbol]) -> void - - class DispatchOnce < Visitor - attr_reader listeners: Hash[Symbol, Array[untyped]] - - def initialize: (Hash[Symbol, Array[untyped]]) -> void - end - end -end diff --git a/sig/prism/dot_visitor.rbs b/sig/prism/dot_visitor.rbs deleted file mode 100644 index 46b3dbf419..0000000000 --- a/sig/prism/dot_visitor.rbs +++ /dev/null @@ -1,6 +0,0 @@ -module Prism - class DotVisitor < Visitor - def initialize: () -> void - def to_dot: () -> String - end -end diff --git a/sig/prism/inspect_visitor.rbs b/sig/prism/inspect_visitor.rbs deleted file mode 100644 index 70fa878ac3..0000000000 --- a/sig/prism/inspect_visitor.rbs +++ /dev/null @@ -1,22 +0,0 @@ -module Prism - class InspectVisitor < Visitor - class Replace - attr_reader value: String - - def initialize: (String value) -> void - end - - attr_reader indent: String - attr_reader commands: Array[[String | node | Replace, String]] - - def initialize: (?String indent) -> void - def compose: () -> String - - def self.compose: (node node) -> String - - private - - def inspect_node: (String name, node node) -> String - def inspect_location: (Location? location) -> String - end -end diff --git a/sig/prism/lex_compat.rbs b/sig/prism/lex_compat.rbs deleted file mode 100644 index 5dc1f8764e..0000000000 --- a/sig/prism/lex_compat.rbs +++ /dev/null @@ -1,10 +0,0 @@ -module Prism - class LexCompat - class Result < Prism::Result - attr_reader value: Array[[[Integer, Integer], Symbol, String, untyped]] - - def initialize: (Array[[[Integer, Integer], Symbol, String, untyped]] value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - end -end diff --git a/sig/prism/node_ext.rbs b/sig/prism/node_ext.rbs deleted file mode 100644 index a187c1d246..0000000000 --- a/sig/prism/node_ext.rbs +++ /dev/null @@ -1,149 +0,0 @@ -module Prism - class Node - def deprecated: (*String replacements) -> void - end - - class InterpolatedMatchLastLineNode < Node - def options: () -> Integer - end - - class InterpolatedRegularExpressionNode < Node - def options: () -> Integer - end - - class MatchLastLineNode < Node - def options: () -> Integer - end - - class RegularExpressionNode < Node - def options: () -> Integer - end - - class InterpolatedStringNode < Node - def heredoc?: () -> bool - end - - class InterpolatedXStringNode < Node - def heredoc?: () -> bool - end - - class StringNode < Node - def heredoc?: () -> bool - def to_interpolated: () -> InterpolatedStringNode - end - - class XStringNode < Node - def heredoc?: () -> bool - def to_interpolated: () -> InterpolatedXStringNode - end - - class ImaginaryNode < Node - def value: () -> Complex - end - - class RationalNode < Node - def value: () -> Rational - def numeric: () -> (IntegerNode | FloatNode) - end - - class ConstantReadNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - end - - class ConstantWriteNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - end - - class ConstantPathNode < Node - class DynamicPartsInConstantPathError < StandardError - end - - class MissingNodesInConstantPathError < StandardError - end - - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - def child: () -> (ConstantReadNode | MissingNode) - end - - class ConstantPathTargetNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - def child: () -> (ConstantReadNode | MissingNode) - end - - class ConstantTargetNode < Node - def full_name_parts: () -> Array[Symbol] - def full_name: () -> String - end - - class ParametersNode < Node - def signature: () -> Array[[Symbol, Symbol] | [Symbol]] - end - - class CallNode < Node - def full_message_loc: () -> Location? - end - - class CallOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class ClassVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class ConstantOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class ConstantPathOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class GlobalVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class IndexOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class InstanceVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class LocalVariableOperatorWriteNode < Node - def operator: () -> Symbol - def operator_loc: () -> Location - end - - class CaseMatchNode < Node - def consequent: () -> ElseNode? - end - - class CaseNode < Node - def consequent: () -> ElseNode? - end - - class IfNode < Node - def consequent: () -> (ElseNode | IfNode | nil) - end - - class RescueNode < Node - def consequent: () -> RescueNode? - end - - class UnlessNode < Node - def consequent: () -> ElseNode? - end -end diff --git a/sig/prism/parse_result.rbs b/sig/prism/parse_result.rbs deleted file mode 100644 index cbcf3fc2f8..0000000000 --- a/sig/prism/parse_result.rbs +++ /dev/null @@ -1,197 +0,0 @@ -module Prism - interface _CodeUnitsCache - def []: (Integer byte_offset) -> Integer - end - - class Source - attr_reader source: String - attr_reader start_line: Integer - attr_reader offsets: Array[Integer] - - def initialize: (String source, ?Integer start_line, ?Array[Integer] offsets) -> void - def replace_start_line: (Integer start_line) -> void - def replace_offsets: (Array[Integer] offsets) -> void - def encoding: () -> Encoding - def lines: () -> Array[String] - def slice: (Integer byte_offset, Integer length) -> String - def byte_offset: (Integer line, Integer column) -> Integer - def line: (Integer byte_offset) -> Integer - def line_start: (Integer byte_offset) -> Integer - def line_end: (Integer byte_offset) -> Integer - def line_offset: (Integer byte_offset) -> Integer - def column: (Integer byte_offset) -> Integer - def character_offset: (Integer byte_offset) -> Integer - def character_column: (Integer byte_offset) -> Integer - def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer - def deep_freeze: () -> void - - def self.for: (String source) -> Source - end - - class CodeUnitsCache - def initialize: (String source, Encoding encoding) -> void - def []: (Integer byte_offset) -> Integer - end - - class ASCIISource < Source - def character_offset: (Integer byte_offset) -> Integer - def character_column: (Integer byte_offset) -> Integer - def code_units_offset: (Integer byte_offset, Encoding encoding) -> Integer - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - def code_units_column: (Integer byte_offset, Encoding encoding) -> Integer - end - - class Location - attr_reader source: Source - attr_reader start_offset: Integer - attr_reader length: Integer - - def initialize: (Source source, Integer start_offset, Integer length) -> void - def leading_comments: () -> Array[comment] - def leading_comment: (comment) -> void - def trailing_comments: () -> Array[comment] - def trailing_comment: (comment) -> void - def comments: () -> Array[comment] - def copy: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location - def chop: () -> Location - def source_lines: () -> Array[String] - def slice: () -> String - def slice_lines: () -> String - def start_character_offset: () -> Integer - def start_code_units_offset: (Encoding encoding) -> Integer - def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer - def end_offset: () -> Integer - def end_character_offset: () -> Integer - def end_code_units_offset: (Encoding encoding) -> Integer - def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer - def start_line: () -> Integer - def start_line_slice: () -> String - def end_line: () -> Integer - def start_column: () -> Integer - def start_character_column: () -> Integer - def start_code_units_column: (Encoding encoding) -> Integer - def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer - def end_column: () -> Integer - def end_character_column: () -> Integer - def end_code_units_column: (Encoding encoding) -> Integer - def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def pretty_print: (untyped q) -> untyped - def join: (Location other) -> Location - def adjoin: (String string) -> Location - end - - class Comment - attr_reader location: Location - - def initialize: (Location location) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def slice: () -> String - end - - interface _Comment - def trailing?: () -> bool - end - - type comment = Comment & _Comment - - class InlineComment < Comment - include _Comment - end - - class EmbDocComment < Comment - include _Comment - end - - class MagicComment - attr_reader key_loc: Location - attr_reader value_loc: Location - - def initialize: (Location key_loc, Location value_loc) -> void - - def key: () -> String - def value: () -> String - - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class ParseError - attr_reader type: Symbol - attr_reader message: String - attr_reader location: Location - attr_reader level: Symbol - - def initialize: (Symbol type, String message, Location location, Symbol level) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class ParseWarning - attr_reader type: Symbol - attr_reader message: String - attr_reader location: Location - attr_reader level: Symbol - - def initialize: (Symbol type, String message, Location location, Symbol level) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class Result - attr_reader comments: Array[comment] - attr_reader magic_comments: Array[MagicComment] - attr_reader data_loc: Location? - attr_reader errors: Array[ParseError] - attr_reader warnings: Array[ParseWarning] - attr_reader source: Source - - def initialize: (Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def encoding: () -> Encoding - def success?: () -> bool - def failure?: () -> bool - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - end - - class ParseResult < Result - attr_reader value: ProgramNode - - def initialize: (ProgramNode value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def errors_format: () -> String - end - - class LexResult < Result - attr_reader value: Array[[Token, Integer]] - - def initialize: (Array[[Token, Integer]] value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class ParseLexResult < Result - attr_reader value: [ProgramNode, Array[[Token, Integer]]] - - def initialize: ([ProgramNode, Array[[Token, Integer]]] value, Array[comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - end - - class Token - attr_reader source: Source - attr_reader type: Symbol - attr_reader value: String - attr_reader location: Location - - def initialize: (Source source, Symbol type, String value, Location location) -> void - def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped] - def pretty_print: (untyped q) -> untyped - def ==: (untyped other) -> bool - def deep_freeze: () -> void - end - - class Scope - attr_reader locals: Array[Symbol] - attr_reader forwarding: Array[Symbol] - - def initialize: (Array[Symbol] locals, Array[Symbol] forwarding) -> void - end -end diff --git a/sig/prism/parse_result/comments.rbs b/sig/prism/parse_result/comments.rbs deleted file mode 100644 index 5b9e315063..0000000000 --- a/sig/prism/parse_result/comments.rbs +++ /dev/null @@ -1,38 +0,0 @@ -module Prism - class ParseResult < Result - class Comments - interface _Target - def start_offset: () -> Integer - def end_offset: () -> Integer - def encloses?: (comment) -> bool - def leading_comment: (comment) -> void - def trailing_comment: (comment) -> void - end - - class NodeTarget - include _Target - - attr_reader node: node - - def initialize: (node) -> void - end - - class LocationTarget - include _Target - - attr_reader location: Location - - def initialize: (Location location) -> void - end - - attr_reader parse_result: ParseResult - - def initialize: (ParseResult parse_result) -> void - def attach!: () -> void - - private - - def nearest_targets: (node, comment) -> [_Target?, _Target, _Target?] - end - end -end diff --git a/sig/prism/pattern.rbs b/sig/prism/pattern.rbs deleted file mode 100644 index a70293e18b..0000000000 --- a/sig/prism/pattern.rbs +++ /dev/null @@ -1,13 +0,0 @@ -module Prism - class Pattern - class CompilationError < StandardError - end - - attr_reader query: String - - def initialize: (String query) -> void - def compile: () -> Proc - def scan: (Prism::node root) { (Prism::node) -> void } -> void - | (Prism::node root) -> ::Enumerator[Prism::node, void] - end -end diff --git a/sig/prism/reflection.rbs b/sig/prism/reflection.rbs deleted file mode 100644 index 047ea32a50..0000000000 --- a/sig/prism/reflection.rbs +++ /dev/null @@ -1,50 +0,0 @@ -module Prism - module Reflection - class Field - attr_reader name: Symbol - - def initialize: (Symbol name) -> void - end - - class NodeField < Field - end - - class OptionalNodeField < Field - end - - class NodeListField < Field - end - - class ConstantField < Field - end - - class OptionalConstantField < Field - end - - class ConstantListField < Field - end - - class StringField < Field - end - - class LocationField < Field - end - - class OptionalLocationField < Field - end - - class IntegerField < Field - end - - class FloatField < Field - end - - class FlagsField < Field - attr_reader flags: Array[Symbol] - - def initialize: (Symbol name, Array[Symbol] flags) -> void - end - - def self.fields_for: (singleton(Node) node) -> Array[Field] - end -end diff --git a/sig/prism/relocation.rbs b/sig/prism/relocation.rbs deleted file mode 100644 index 7f5637d5fa..0000000000 --- a/sig/prism/relocation.rbs +++ /dev/null @@ -1,185 +0,0 @@ -module Prism - module Relocation - interface _Value - def start_line: () -> Integer - def end_line: () -> Integer - def start_offset: () -> Integer - def end_offset: () -> Integer - def start_character_offset: () -> Integer - def end_character_offset: () -> Integer - def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer - def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer - def start_column: () -> Integer - def end_column: () -> Integer - def start_character_column: () -> Integer - def end_character_column: () -> Integer - def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer - def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer - def leading_comments: () -> Array[Comment] - def trailing_comments: () -> Array[Comment] - end - - interface _Field - def fields: (_Value value) -> entry_values - end - - type entry_value = untyped - type entry_values = Hash[Symbol, entry_value] - - class Entry - class MissingValueError < StandardError - end - - def initialize: (Repository repository) -> void - - def filepath: () -> String - - def start_line: () -> Integer - def end_line: () -> Integer - - def start_offset: () -> Integer - def end_offset: () -> Integer - def start_character_offset: () -> Integer - def end_character_offset: () -> Integer - def start_code_units_offset: () -> Integer - def end_code_units_offset: () -> Integer - - def start_column: () -> Integer - def end_column: () -> Integer - def start_character_column: () -> Integer - def end_character_column: () -> Integer - def start_code_units_column: () -> Integer - def end_code_units_column: () -> Integer - - def leading_comments: () -> Array[CommentsField::Comment] - def trailing_comments: () -> Array[CommentsField::Comment] - def comments: () -> Array[CommentsField::Comment] - - private - - def fetch_value: (Symbol name) -> entry_value - def values: () -> entry_values - end - - class Source - attr_reader value: untyped - - def initialize: (untyped value) -> void - - def result: () -> ParseResult - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - end - - class SourceFilepath < Source - def result: () -> ParseResult - end - - class SourceString < Source - def result: () -> ParseResult - end - - class FilepathField - attr_reader value: String - - def initialize: (String value) -> void - - def fields: (_Value value) -> entry_values - end - - class LinesField - def fields: (_Value value) -> entry_values - end - - class OffsetsField - def fields: (_Value value) -> entry_values - end - - class CharacterOffsetsField - def fields: (_Value value) -> entry_values - end - - class CodeUnitOffsetsField - attr_reader repository: Repository - attr_reader encoding: Encoding - - def initialize: (Repository repository, Encoding encoding) -> void - def fields: (_Value value) -> entry_values - - private - - def cache: () -> _CodeUnitsCache - end - - class ColumnsField - def fields: (_Value value) -> entry_values - end - - class CharacterColumnsField - def fields: (_Value value) -> entry_values - end - - class CodeUnitColumnsField - attr_reader repository: Repository - attr_reader encoding: Encoding - - def initialize: (Repository repository, Encoding encoding) -> void - def fields: (_Value value) -> entry_values - - private - - def cache: () -> _CodeUnitsCache - end - - class CommentsField - class Comment - attr_reader slice: String - - def initialize: (String slice) -> void - end - - private - - def comments: (entry_value value) -> Array[Comment] - end - - class LeadingCommentsField < CommentsField - def fields: (_Value value) -> entry_values - end - - class TrailingCommentsField < CommentsField - def fields: (_Value value) -> entry_values - end - - class Repository - class ConfigurationError < StandardError - end - - attr_reader source: Source - attr_reader fields: Hash[Symbol, _Field] - attr_reader entries: Hash[Integer, Hash[Symbol, Entry]] - - def initialize: (Source source) -> void - - def code_units_cache: (Encoding encoding) -> _CodeUnitsCache - - def filepath: () -> self - def lines: () -> self - def offsets: () -> self - def character_offsets: () -> self - def code_unit_offsets: (Encoding encoding) -> self - def columns: () -> self - def character_columns: () -> self - def code_unit_columns: (Encoding encoding) -> self - def leading_comments: () -> self - def trailing_comments: () -> self - def comments: () -> self - - private - - def field: (Symbol name, _Field) -> self - end - - def self.filepath: (String value) -> Repository - def self.string: (String value) -> Repository - end -end diff --git a/sig/prism/serialize.rbs b/sig/prism/serialize.rbs deleted file mode 100644 index 71a7c5c1c9..0000000000 --- a/sig/prism/serialize.rbs +++ /dev/null @@ -1,8 +0,0 @@ -module Prism - module Serialize - def self.load_parse: (String, String, bool) -> ParseResult - def self.load_lex: (String, String, bool) -> LexResult - def self.load_parse_comments: (String, String, bool) -> Array[comment] - def self.load_parse_lex: (String, String, bool) -> ParseLexResult - end -end diff --git a/sig/prism/string_query.rbs b/sig/prism/string_query.rbs deleted file mode 100644 index 098746e552..0000000000 --- a/sig/prism/string_query.rbs +++ /dev/null @@ -1,11 +0,0 @@ -module Prism - class StringQuery - attr_reader string: String - - def initialize: (String string) -> void - - def local?: () -> bool - def constant?: () -> bool - def method_name?: () -> bool - end -end diff --git a/templates/lib/prism/compiler.rb.erb b/templates/lib/prism/compiler.rb.erb index 031557a221..16035b5456 100644 --- a/templates/lib/prism/compiler.rb.erb +++ b/templates/lib/prism/compiler.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + module Prism # A compiler is a visitor that returns the value of each node as it visits. # This is as opposed to a visitor which will only walk the tree. This can be @@ -18,22 +20,29 @@ module Prism # class Compiler < Visitor # Visit an individual node. + #-- + #: (node?) -> untyped def visit(node) # :nodoc: node&.accept(self) end # Visit a list of nodes. + #-- + #: (Array[node?]) -> untyped def visit_all(nodes) # :nodoc: nodes.map { |node| node&.accept(self) } end # Visit the child nodes of the given node. + #-- + #: (node) -> Array[untyped] def visit_child_nodes(node) # :nodoc: node.each_child_node.map { |node| node.accept(self) } end <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> + #: (<%= node.name %>) -> Array[untyped] def visit_<%= node.human %>(node) # :nodoc: node.each_child_node.map { |node| node.accept(self) } end diff --git a/templates/lib/prism/dispatcher.rb.erb b/templates/lib/prism/dispatcher.rb.erb index e4ca84db24..f1bd80a7cd 100644 --- a/templates/lib/prism/dispatcher.rb.erb +++ b/templates/lib/prism/dispatcher.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + module Prism # The dispatcher class fires events for nodes that are found while walking an # AST to all registered listeners. It's useful for performing different types @@ -32,26 +34,35 @@ module Prism # dispatcher.dispatch_once(integer) # class Dispatcher < Visitor - # attr_reader listeners: Hash[Symbol, Array[Listener]] - attr_reader :listeners + # A hash mapping event names to arrays of listeners that should be notified + # when that event is fired. + attr_reader :listeners #: Hash[Symbol, Array[untyped]] # Initialize a new dispatcher. + #-- + #: () -> void def initialize @listeners = {} end # Register a listener for one or more events. + #-- + #: (untyped, *Symbol) -> void def register(listener, *events) register_events(listener, events) end # Register all public methods of a listener that match the pattern # `on__(enter|leave)`. + #-- + #: (untyped) -> void def register_public_methods(listener) register_events(listener, listener.public_methods(false).grep(/\Aon_.+_(?:enter|leave)\z/)) end # Register a listener for the given events. + #-- + #: (untyped, Array[Symbol]) -> void private def register_events(listener, events) # :nodoc: events.each { |event| (listeners[event] ||= []) << listener } end @@ -60,11 +71,14 @@ module Prism alias dispatch visit # Dispatches a single event for `node` to all registered listeners. + #-- + #: (node node) -> void def dispatch_once(node) node.accept(DispatchOnce.new(listeners)) end <%- nodes.each do |node| -%> + #: (<%= node.name %> node) -> void def visit_<%= node.human %>(node) # :nodoc: listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) } super @@ -73,14 +87,17 @@ module Prism <%- end -%> class DispatchOnce < Visitor # :nodoc: - attr_reader :listeners + attr_reader :listeners #: Hash[Symbol, Array[untyped]] + #: (Hash[Symbol, Array[untyped]] listeners) -> void def initialize(listeners) @listeners = listeners end <%- nodes.each do |node| -%> # Dispatch enter and leave events for <%= node.name %> nodes. + #-- + #: (<%= node.name %> node) -> void def visit_<%= node.human %>(node) listeners[:on_<%= node.human %>_enter]&.each { |listener| listener.on_<%= node.human %>_enter(node) } listeners[:on_<%= node.human %>_leave]&.each { |listener| listener.on_<%= node.human %>_leave(node) } diff --git a/templates/lib/prism/dot_visitor.rb.erb b/templates/lib/prism/dot_visitor.rb.erb index 13c53af0d4..3e37cf1a57 100644 --- a/templates/lib/prism/dot_visitor.rb.erb +++ b/templates/lib/prism/dot_visitor.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + require "cgi/escape" require "cgi/util" unless defined?(CGI::EscapeExt) @@ -6,14 +8,18 @@ module Prism # subtree into a graphviz dot graph. class DotVisitor < Visitor class Field # :nodoc: - attr_reader :name, :value, :port + attr_reader :name #: String + attr_reader :value #: String? + attr_reader :port #: bool + #: (String name, String? value, bool port) -> void def initialize(name, value, port) @name = name @value = value @port = port end + #: () -> String def to_dot if port "#{name}" @@ -24,17 +30,21 @@ module Prism end class Table # :nodoc: - attr_reader :name, :fields + attr_reader :name #: String + attr_reader :fields #: Array[Field] + #: (String name) -> void def initialize(name) @name = name @fields = [] end + #: (String name, ?String? value, ?port: bool) -> void def field(name, value = nil, port: false) fields << Field.new(name, value, port) end + #: () -> String def to_dot dot = <<~DOT @@ -50,26 +60,31 @@ module Prism end class Digraph # :nodoc: - attr_reader :nodes, :waypoints, :edges + attr_reader :nodes, :waypoints, :edges #: Array[String] + #: () -> void def initialize @nodes = [] @waypoints = [] @edges = [] end + #: (String value) -> void def node(value) nodes << value end + #: (String value) -> void def waypoint(value) waypoints << value end + #: (String value) -> void def edge(value) edges << value end + #: () -> String def to_dot <<~DOT digraph "Prism" { @@ -93,19 +108,24 @@ module Prism private_constant :Field, :Table, :Digraph # The digraph that is being built. - attr_reader :digraph + attr_reader :digraph #: Digraph # Initialize a new dot visitor. + #-- + #: () -> void def initialize @digraph = Digraph.new end # Convert this visitor into a graphviz dot graph string. + #-- + #: () -> String def to_dot digraph.to_dot end <%- nodes.each do |node| -%> + # (<%= node.name %>) -> void def visit_<%= node.human %>(node) # :nodoc: table = Table.new("<%= node.name %>") id = node_id(node) @@ -151,7 +171,7 @@ module Prism <%- end -%> <%- end -%> - digraph.nodes << <<~DOT + digraph.node(<<~DOT) #{id} [ label=<#{table.to_dot.gsub(/\n/, "\n ")}> ]; @@ -164,11 +184,15 @@ module Prism private # Generate a unique node ID for a node throughout the digraph. + #-- + #: (node) -> String def node_id(node) # :nodoc: "Node_#{node.object_id}" end # Inspect a location to display the start and end line and columns in bytes. + #-- + #: (Location) -> String def location_inspect(location) # :nodoc: "(#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column})" end @@ -176,6 +200,8 @@ module Prism # Inspect a node that has <%= flag.human %> flags to display the flags as a # comma-separated list. + #-- + #: (<%= nodes.filter_map { |node| node.name if node.flags == flag }.join(" | ") %> node) -> String def <%= flag.human %>_inspect(node) # :nodoc: flags = [] #: Array[String] <%- flag.values.each do |value| -%> diff --git a/templates/lib/prism/dsl.rb.erb b/templates/lib/prism/dsl.rb.erb index e16ebb7110..de265a095b 100644 --- a/templates/lib/prism/dsl.rb.erb +++ b/templates/lib/prism/dsl.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: @@ -56,17 +58,31 @@ module Prism extend self # Create a new Source object. + #-- + #: (String string) -> Source def source(string) Source.for(string) end # Create a new Location object. + #-- + #: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location def location(source: default_source, start_offset: 0, length: 0) Location.new(source, start_offset, length) end <%- nodes.each do |node| -%> + <%- + params = [ + ["source", "Source"], + ["node_id", "Integer"], + ["location", "Location"], + ["flags", "Integer"] + ].concat(node.fields.map { |field| [field.name, field.rbs_class] }) + -%> # Create a new <%= node.name %> node. + #-- + #: (<%= params.map { |(name, type)| "?#{name}: #{type}" }.join(", ") %>) -> <%= node.name %> def <%= node.human %>(<%= ["source: default_source", "node_id: 0", "location: default_location", "flags: 0", *node.fields.map { |field| case field when Prism::Template::NodeField @@ -100,6 +116,8 @@ module Prism <%- flags.each do |flag| -%> # Retrieve the value of one of the <%= flag.name %> flags. + #-- + #: (Symbol name) -> Integer def <%= flag.human.chomp("s") %>(name) case name <%- flag.values.each do |value| -%> @@ -114,18 +132,24 @@ module Prism # The default source object that gets attached to nodes and locations if no # source is specified. + #-- + #: () -> Source def default_source Source.for("") end # The default location object that gets attached to nodes if no location is # specified, which uses the given source. + #-- + #: () -> Location def default_location Location.new(default_source, 0, 0) end # The default node that gets attached to nodes if no node is specified for a # required node field. + #-- + #: (Source source, Location location) -> node def default_node(source, location) MissingNode.new(source, -1, location, 0) end diff --git a/templates/lib/prism/inspect_visitor.rb.erb b/templates/lib/prism/inspect_visitor.rb.erb index 9a33cb8110..9b15cb3d8a 100644 --- a/templates/lib/prism/inspect_visitor.rb.erb +++ b/templates/lib/prism/inspect_visitor.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + module Prism # This visitor is responsible for composing the strings that get returned by # the various #inspect methods defined on each of the nodes. @@ -7,8 +9,9 @@ module Prism # when we hit an element in that list. In this case, we have a special # command that replaces the subsequent indent with the given value. class Replace # :nodoc: - attr_reader :value + attr_reader :value #: String + #: (String value) -> void def initialize(value) @value = value end @@ -17,18 +20,25 @@ module Prism private_constant :Replace # The current prefix string. - attr_reader :indent # :nodoc: + # :stopdoc: + attr_reader :indent #: String + # :startdoc: # The list of commands that we need to execute in order to compose the # final string. - attr_reader :commands # :nodoc: + #: stopdoc: + attr_reader :commands #: Array[[String | node | Replace, String]] + # :startdoc: + #: (?String indent) -> void def initialize(indent = +"") # :nodoc: @indent = indent @commands = [] end # Compose an inspect string for the given node. + #-- + #: (node node) -> String def self.compose(node) visitor = new node.accept(visitor) @@ -36,6 +46,8 @@ module Prism end # Compose the final string. + #-- + #: () -> String def compose # :nodoc: buffer = +"" replace = nil @@ -65,6 +77,7 @@ module Prism end <%- nodes.each do |node| -%> + #: (<%= node.name %> node) -> void def visit_<%= node.human %>(node) # :nodoc: commands << [inspect_node(<%= node.name.inspect %>, node), indent] <%- (fields = [node.flags || Prism::Template::Flags.empty, *node.fields]).each_with_index do |field, index| -%> @@ -112,12 +125,16 @@ module Prism private # Compose a header for the given node. + #-- + #: (String name, node node) -> String def inspect_node(name, node) # :nodoc: location = node.location "@ #{name} (location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}))\n" end # Compose a string representing the given inner location field. + #-- + #: (Location? location) -> String def inspect_location(location) # :nodoc: if location "(#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}) = #{location.slice.inspect}" diff --git a/templates/lib/prism/mutation_compiler.rb.erb b/templates/lib/prism/mutation_compiler.rb.erb index b223860f2f..6fcbb25dcc 100644 --- a/templates/lib/prism/mutation_compiler.rb.erb +++ b/templates/lib/prism/mutation_compiler.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + module Prism # This visitor walks through the tree and copies each node as it is being # visited. This is useful for consumers that want to mutate the tree, as you @@ -5,6 +7,7 @@ module Prism class MutationCompiler < Compiler <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> + #: (<%= node.name %>) -> node? def visit_<%= node.human %>(node) # :nodoc: <%- fields = node.fields.select { |field| [Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::NodeListField].include?(field.class) } -%> <%- if fields.any? -%> diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index 8c88529c66..195200e482 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -1,26 +1,48 @@ -# :markup: markdown +# rbs_inline: enabled module Prism + # @rbs! + # interface _Repository + # def enter: (Integer node_id, Symbol field_name) -> Relocation::Entry + # end + # + # interface _Node + # def deconstruct: () -> Array[Prism::node?] + # def inspect: () -> String + # end + # + # type node = Node & _Node + # This represents a node in the tree. It is the parent class of all of the # various node types. class Node # A pointer to the source that this node was created from. - attr_reader :source # :nodoc: + # :stopdoc: + attr_reader :source #: Source private :source + # :startdoc: # A unique identifier for this node. This is used in a very specific # use case where you want to keep around a reference to a node without # having to keep around the syntax tree in memory. This unique identifier # will be consistent across multiple parses of the same source code. - attr_reader :node_id + attr_reader :node_id #: Integer + + # The location associated with this node. For lazily loading Location + # objects, we keep it as a packed integer until it is accessed. + # @rbs @location: Location | Integer # Save this node using a saved source so that it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry def save(repository) repository.enter(node_id, :itself) end # A Location instance that represents the location of this node in the # source. + #-- + #: () -> Location def location location = @location return location if location.is_a?(Location) @@ -28,6 +50,8 @@ module Prism end # Save the location using a saved source so that it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry def save_location(repository) repository.enter(node_id, :location) end @@ -38,22 +62,30 @@ module Prism # -------------------------------------------------------------------------- # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. + #-- + #: () -> Integer def start_line location.start_line end # Delegates to [`end_line`](rdoc-ref:Location#end_line) of the associated location object. + #-- + #: () -> Integer def end_line location.end_line end # Delegates to [`start_offset`](rdoc-ref:Location#start_offset) of the associated location object. + #-- + #: () -> Integer def start_offset location = @location location.is_a?(Location) ? location.start_offset : location >> 32 end # Delegates to [`end_offset`](rdoc-ref:Location#end_offset) of the associated location object. + #-- + #: () -> Integer def end_offset location = @location location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF)) @@ -61,73 +93,99 @@ module Prism # Delegates to [`start_character_offset`](rdoc-ref:Location#start_character_offset) # of the associated location object. + #-- + #: () -> Integer def start_character_offset location.start_character_offset end # Delegates to [`end_character_offset`](rdoc-ref:Location#end_character_offset) # of the associated location object. + #-- + #: () -> Integer def end_character_offset location.end_character_offset end # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_offset(cache) location.cached_start_code_units_offset(cache) end # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_end_code_units_offset(cache) location.cached_end_code_units_offset(cache) end # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. + #-- + #: () -> Integer def start_column location.start_column end # Delegates to [`end_column`](rdoc-ref:Location#end_column) of the associated location object. + #-- + #: () -> Integer def end_column location.end_column end # Delegates to [`start_character_column`](rdoc-ref:Location#start_character_column) # of the associated location object. + #-- + #: () -> Integer def start_character_column location.start_character_column end # Delegates to [`end_character_column`](rdoc-ref:Location#end_character_column) # of the associated location object. + #-- + #: () -> Integer def end_character_column location.end_character_column end # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_start_code_units_column(cache) location.cached_start_code_units_column(cache) end # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) # of the associated location object. + #-- + #: (_CodeUnitsCache cache) -> Integer def cached_end_code_units_column(cache) location.cached_end_code_units_column(cache) end # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. + #-- + #: () -> Array[Comment] def leading_comments location.leading_comments end # Delegates to [`trailing_comments`](rdoc-ref:Location#trailing_comments) of the associated location object. + #-- + #: () -> Array[Comment] def trailing_comments location.trailing_comments end # Delegates to [`comments`](rdoc-ref:Location#comments) of the associated location object. + #-- + #: () -> Array[Comment] def comments location.comments end @@ -135,6 +193,8 @@ module Prism # :section: # Returns all of the lines of the source code associated with this node. + #-- + #: () -> Array[String] def source_lines location.source_lines end @@ -144,6 +204,8 @@ module Prism alias script_lines source_lines # Slice the location of the node from the source. + #-- + #: () -> String def slice location.slice end @@ -151,27 +213,37 @@ module Prism # Slice the location of the node from the source, starting at the beginning # of the line that the location starts on, ending at the end of the line # that the location ends on. + #-- + #: () -> String def slice_lines location.slice_lines end # An bitset of flags for this node. There are certain flags that are common # for all nodes, and then some nodes have specific flags. - attr_reader :flags # :nodoc: + # :stopdoc: + attr_reader :flags #: Integer protected :flags + # :startdoc: # Returns true if the node has the newline flag set. + #-- + #: () -> bool def newline? flags.anybits?(NodeFlags::NEWLINE) end # Returns true if the node has the static literal flag set. + #-- + #: () -> bool def static_literal? flags.anybits?(NodeFlags::STATIC_LITERAL) end # Similar to inspect, but respects the current level of indentation given by # the pretty print object. + #-- + #: (PP q) -> void def pretty_print(q) # :nodoc: q.seplist(inspect.chomp.each_line, -> { q.breakable }) do |line| q.text(line.chomp) @@ -180,6 +252,8 @@ module Prism end # Convert this node into a graphviz dot graph string. + #-- + #: () -> String def to_dot # @type self: node DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot @@ -191,9 +265,11 @@ module Prism # # Important to note is that the column given to this method should be in # bytes, as opposed to characters or code units. + #-- + #: (Integer line, Integer column) -> Array[node] def tunnel(line, column) - queue = [self] #: Array[Prism::node] - result = [] #: Array[Prism::node] + queue = [self] #: Array[node] + result = [] #: Array[node] offset = source.byte_offset(line, column) while (node = queue.shift) @@ -215,9 +291,10 @@ module Prism # particular condition. # # node.breadth_first_search { |node| node.node_id == node_id } - # + #-- + #: () { (node) -> bool } -> node? def breadth_first_search(&block) - queue = [self] #: Array[Prism::node] + queue = [self] #: Array[node] while (node = queue.shift) return node if yield node @@ -233,7 +310,8 @@ module Prism # particular condition. # # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } - # + #-- + #: () { (node) -> bool } -> Array[node] def breadth_first_search_all(&block) queue = [self] #: Array[Prism::node] results = [] #: Array[Prism::node] @@ -250,6 +328,8 @@ module Prism # Returns a list of the fields that exist for this node class. Fields # describe the structure of the node. This kind of reflection is useful for # things like recursively visiting each node _and_ field in the tree. + #-- + #: () -> Array[Reflection::Field] def self.fields # This method should only be called on subclasses of Node, not Node # itself. @@ -265,12 +345,16 @@ module Prism # -------------------------------------------------------------------------- # Accepts a visitor and calls back into the specialized visit function. + #-- + #: (_Visitor visitor) -> untyped def accept(visitor) raise NoMethodError, "undefined method `accept' for #{inspect}" end # Returns an array of child nodes, including `nil`s in the place of optional # nodes that were not present. + #-- + #: () -> Array[node?] def child_nodes raise NoMethodError, "undefined method `child_nodes' for #{inspect}" end @@ -280,23 +364,32 @@ module Prism # With a block given, yields each child node. Without a block, returns # an enumerator that contains each child node. Excludes any `nil`s in # the place of optional nodes that were not present. + #-- + #: () { (node) -> void } -> void + #: () -> Enumerator[node, void] def each_child_node raise NoMethodError, "undefined method `each_child_node' for #{inspect}" end # Returns an array of child nodes, excluding any `nil`s in the place of # optional nodes that were not present. + #-- + #: () -> Array[node] def compact_child_nodes raise NoMethodError, "undefined method `compact_child_nodes' for #{inspect}" end # Returns an array of child nodes and locations that could potentially have # comments attached to them. + #-- + #: () -> Array[node | Location] def comment_targets raise NoMethodError, "undefined method `comment_targets' for #{inspect}" end # Returns a string representation of the node. + #-- + #: () -> String def inspect raise NoMethodError, "undefined method `inspect' for #{inspect}" end @@ -313,6 +406,8 @@ module Prism # it uses a single integer comparison, but also because if you're on CRuby # you can take advantage of the fact that case statements with all symbol # keys will use a jump table. + #-- + #: () -> Symbol def type raise NoMethodError, "undefined method `type' for #{inspect}" end @@ -321,6 +416,8 @@ module Prism # splitting on the type of the node without having to do a long === chain. # Note that like #type, it will still be slower than using == for a single # class, but should be faster in a case statement or an array comparison. + #-- + #: () -> Symbol def self.type raise NoMethodError, "undefined method `type' for #{inspect}" end @@ -331,7 +428,13 @@ module Prism #<%= line %> <%- end -%> class <%= node.name -%> < Node + <%- node.fields.each do |field| -%> + # @rbs @<%= field.name %>: <%= field.rbs_class %> + <%- end -%> + # Initialize a new <%= node.name %> node. + #-- + #: (Source source, Integer node_id, Location location, Integer flags, <%= node.fields.map { |field| "#{field.rbs_class} #{field.name}" }.join(", ") %>) -> void def initialize(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>) @source = source @node_id = node_id @@ -357,11 +460,15 @@ module Prism # ---------------------------------------------------------------------------------- # See Node.accept. + #-- + #: (_Visitor visitor) -> untyped def accept(visitor) visitor.visit_<%= node.human %>(self) end # See Node.child_nodes. + #-- + #: () -> Array[node?] def child_nodes [<%= node.fields.map { |field| case field @@ -372,6 +479,9 @@ module Prism end # See Node.each_child_node. + #-- + #: () { (node) -> void } -> void + #: () -> Enumerator[node, void] def each_child_node return to_enum(:each_child_node) unless block_given? @@ -380,7 +490,7 @@ module Prism <%- when Prism::Template::NodeField -%> yield <%= field.name %> <%- when Prism::Template::OptionalNodeField -%> - yield <%= field.name %> if <%= field.name %> + if (<%= field.name %> = self.<%= field.name %>); yield <%= field.name %>; end <%- when Prism::Template::NodeListField -%> <%= field.name %>.each { |node| yield node } <%- end -%> @@ -388,6 +498,8 @@ module Prism end # See Node.compact_child_nodes. + #-- + #: () -> Array[node] def compact_child_nodes <%- if node.fields.any? { |field| field.is_a?(Prism::Template::OptionalNodeField) } -%> compact = [] #: Array[Prism::node] @@ -396,7 +508,7 @@ module Prism <%- when Prism::Template::NodeField -%> compact << <%= field.name %> <%- when Prism::Template::OptionalNodeField -%> - compact << <%= field.name %> if <%= field.name %> + if (<%= field.name %> = self.<%= field.name %>); compact << <%= field.name %>; end <%- when Prism::Template::NodeListField -%> compact.concat(<%= field.name %>) <%- end -%> @@ -413,6 +525,8 @@ module Prism end # See Node.comment_targets. + #-- + #: () -> Array[node | Location] def comment_targets [<%= node.fields.map { |field| case field @@ -426,26 +540,34 @@ module Prism # copy(**fields) -> <%= node.name %> # # Creates a copy of self with the given fields, using self as the template. + #-- + #: (?node_id: Integer, ?location: Location, ?flags: Integer, <%= node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" }.join(", ") %>) -> <%= node.name %> def copy(<%= (["node_id", "location", "flags"] + node.fields.map(&:name)).map { |field| "#{field}: self.#{field}" }.join(", ") %>) <%= node.name %>.new(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>) end alias deconstruct child_nodes + #: (Array[Symbol]? keys) -> Hash[Symbol, untyped] def deconstruct_keys(keys) # :nodoc: { <%= (["node_id: node_id", "location: location"] + node.fields.map { |field| "#{field.name}: #{field.name}" }).join(", ") %> } end # See `Node#type`. + #-- + #: () -> :<%= node.human %> def type :<%= node.human %> end # See `Node.type`. + #-- + #: () -> :<%= node.human %> def self.type :<%= node.human %> end + #: () -> String def inspect # :nodoc: InspectVisitor.compose(self) end @@ -456,6 +578,8 @@ module Prism <%- node_flags.values.each do |value| -%> # :category: Flags # <%= value.comment %> + #-- + #: () -> bool def <%= value.name.downcase %>? flags.anybits?(<%= node_flags.name %>::<%= value.name %>) end @@ -476,6 +600,8 @@ module Prism #<%= line %> <%- end -%> <%- end -%> + #-- + #: () -> Location def <%= field.name %> location = @<%= field.name %> return location if location.is_a?(Location) @@ -485,6 +611,8 @@ module Prism # :category: Repository # Save the <%= field.name %> location using the given saved source so that # it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry def save_<%= field.name %>(repository) repository.enter(node_id, :<%= field.name %>) end @@ -501,6 +629,8 @@ module Prism #<%= line %> <%- end -%> <%- end -%> + #-- + #: () -> Location? def <%= field.name %> location = @<%= field.name %> case location @@ -516,6 +646,8 @@ module Prism # :category: Repository # Save the <%= field.name %> location using the given saved source so that # it can be retrieved later. + #-- + #: (_Repository repository) -> Relocation::Entry? def save_<%= field.name %>(repository) repository.enter(node_id, :<%= field.name %>) unless @<%= field.name %>.nil? end @@ -530,6 +662,8 @@ module Prism #<%= line %> <%- end -%> <%- end -%> + #-- + #: () -> <%= field.rbs_class %> def <%= field.name %> @<%= field.name %> end @@ -547,6 +681,8 @@ module Prism # <%= field.name.delete_suffix("_loc") %> -> String # # Slice the location of <%= field.name %> from the source. + #-- + #: () -> String def <%= field.name.delete_suffix("_loc") %> <%= field.name %>.slice end @@ -558,6 +694,8 @@ module Prism # <%= field.name.delete_suffix("_loc") %> -> String | nil # # Slice the location of <%= field.name %> from the source. + #-- + #: () -> String? def <%= field.name.delete_suffix("_loc") %> <%= field.name %>&.slice end @@ -566,6 +704,7 @@ module Prism <%- end -%> # :section: + #: (untyped other) -> bool def ===(other) # :nodoc: other.is_a?(<%= node.name %>)<%= " &&" if (fields = [*node.flags, *node.fields]).any? %> <%- fields.each_with_index do |field, index| -%> diff --git a/templates/lib/prism/reflection.rb.erb b/templates/lib/prism/reflection.rb.erb index 6c8b2f4d25..d5ace99259 100644 --- a/templates/lib/prism/reflection.rb.erb +++ b/templates/lib/prism/reflection.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + module Prism # The Reflection module provides the ability to reflect on the structure of # the syntax tree itself, as opposed to looking at a single syntax tree. This @@ -7,9 +9,11 @@ module Prism # for all other field types. class Field # The name of the field. - attr_reader :name + attr_reader :name #: Symbol # Initializes the field with the given name. + #-- + #: (Symbol name) -> void def initialize(name) @name = name end @@ -83,9 +87,11 @@ module Prism # the bitset should be accessed through their query methods. class FlagsField < Field # The names of the flags in the bitset. - attr_reader :flags + attr_reader :flags #: Array[Symbol] # Initializes the flags field with the given name and flags. + #-- + #: (Symbol name, Array[Symbol] flags) -> void def initialize(name, flags) super(name) @flags = flags @@ -93,6 +99,8 @@ module Prism end # Returns the fields for the given node. + #-- + #: (singleton(Node) node) -> Array[Field] def self.fields_for(node) case node.type <%- nodes.each do |node| -%> diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index 63ef07cb6e..229322291e 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -1,3 +1,5 @@ +# rbs_inline: enabled + require "stringio" require_relative "polyfill/unpack1" @@ -20,6 +22,8 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> ParseResult def self.load_parse(input, serialized, freeze) input = input.dup source = Source.for(input) @@ -43,7 +47,7 @@ module Prism constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size) - node = loader.load_node(constant_pool, encoding, freeze) + node = loader.load_node(constant_pool, encoding, freeze) #: ProgramNode loader.load_constant_pool(constant_pool) raise unless loader.eof? @@ -73,6 +77,8 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> LexResult def self.load_lex(input, serialized, freeze) source = Source.for(input) loader = Loader.new(source, serialized) @@ -117,6 +123,8 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> Array[Comment] def self.load_parse_comments(input, serialized, freeze) source = Source.for(input) loader = Loader.new(source, serialized) @@ -139,6 +147,8 @@ module Prism # # The formatting of the source of this method is purposeful to illustrate # the structure of the serialized data. + #-- + #: (String input, String serialized, bool freeze) -> ParseLexResult def self.load_parse_lex(input, serialized, freeze) source = Source.for(input) loader = Loader.new(source, serialized) @@ -162,11 +172,11 @@ module Prism constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size) - node = loader.load_node(constant_pool, encoding, freeze) + node = loader.load_node(constant_pool, encoding, freeze) #: ProgramNode loader.load_constant_pool(constant_pool) raise unless loader.eof? - value = [node, tokens] + value = [node, tokens] #: [ProgramNode, Array[[Token, Integer]]] result = ParseLexResult.new(value, comments, magic_comments, data_loc, errors, warnings, source) tokens.each do |token| @@ -189,8 +199,14 @@ module Prism end class ConstantPool # :nodoc: - attr_reader :size + attr_reader :size #: Integer + + # @rbs @input: String + # @rbs @serialized: String + # @rbs @base: Integer + # @rbs @pool: Array[Symbol?] + #: (String input, String serialized, Integer base, Integer size) -> void def initialize(input, serialized, base, size) @input = input @serialized = serialized @@ -199,17 +215,18 @@ module Prism @pool = Array.new(size, nil) end + #: (Integer index, Encoding encoding) -> Symbol def get(index, encoding) @pool[index] ||= begin offset = @base + index * 8 - start = @serialized.unpack1("L", offset: offset) - length = @serialized.unpack1("L", offset: offset + 4) + start = @serialized.unpack1("L", offset: offset) #: Integer + length = @serialized.unpack1("L", offset: offset + 4) #: Integer if start.nobits?(1 << 31) - @input.byteslice(start, length).force_encoding(encoding).to_sym + (@input.byteslice(start, length) or raise).force_encoding(encoding).to_sym else - @serialized.byteslice(start & ((1 << 31) - 1), length).force_encoding(encoding).to_sym + (@serialized.byteslice(start & ((1 << 31) - 1), length) or raise).force_encoding(encoding).to_sym end end end @@ -217,6 +234,7 @@ module Prism if RUBY_ENGINE == "truffleruby" # StringIO is synchronized and that adds a high overhead on TruffleRuby. + # @rbs skip class FastStringIO # :nodoc: attr_accessor :pos @@ -246,8 +264,11 @@ module Prism end class Loader # :nodoc: - attr_reader :input, :io, :source + attr_reader :input #: String + attr_reader :io #: StringIO + attr_reader :source #: Source + #: (Source source, String serialized) -> void def initialize(source, serialized) @input = source.source.dup raise unless serialized.encoding == Encoding::BINARY @@ -256,40 +277,46 @@ module Prism define_load_node_lambdas if RUBY_ENGINE != "ruby" end + #: () -> bool def eof? io.getbyte io.eof? end + #: (ConstantPool constant_pool) -> void def load_constant_pool(constant_pool) trailer = 0 constant_pool.size.times do |index| - start, length = io.read(8).unpack("L2") + start, length = (io.read(8) or raise).unpack("L2") #: [Integer, Integer] trailer += length if start.anybits?(1 << 31) end io.read(trailer) end + #: () -> void def load_header raise "Invalid serialization" if io.read(5) != "PRISM" - raise "Invalid serialization" if io.read(3).unpack("C3") != [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION] + raise "Invalid serialization" if (io.read(3) or raise).unpack("C3") != [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION] raise "Invalid serialization (location fields must be included but are not)" if io.getbyte != 0 end + #: () -> Encoding def load_encoding - encoding = Encoding.find(io.read(load_varuint)) + encoding = Encoding.find((io.read(load_varuint) or raise)) or raise @input = input.force_encoding(encoding).freeze encoding end + #: (bool freeze) -> Array[Integer] def load_line_offsets(freeze) offsets = Array.new(load_varuint) { load_varuint } offsets.freeze if freeze offsets end + #: (bool freeze) -> Array[Comment] def load_comments(freeze) comments = Array.new(load_varuint) do @@ -297,6 +324,7 @@ module Prism case load_varuint when 0 then InlineComment.new(load_location_object(freeze)) when 1 then EmbDocComment.new(load_location_object(freeze)) + else raise end comment.freeze if freeze @@ -307,6 +335,7 @@ module Prism comments end + #: (bool freeze) -> Array[MagicComment] def load_magic_comments(freeze) magic_comments = Array.new(load_varuint) do @@ -331,10 +360,11 @@ module Prism <%- warnings.each do |warning| -%> <%= warning.name.downcase.to_sym.inspect %>, <%- end -%> - ].freeze + ].freeze #: Array[Symbol] private_constant :DIAGNOSTIC_TYPES + #: () -> Symbol def load_error_level level = io.getbyte @@ -350,6 +380,7 @@ module Prism end end + #: (Encoding encoding, bool freeze) -> Array[ParseError] def load_errors(encoding, freeze) errors = Array.new(load_varuint) do @@ -369,6 +400,7 @@ module Prism errors end + #: () -> Symbol def load_warning_level level = io.getbyte @@ -382,6 +414,7 @@ module Prism end end + #: (Encoding encoding, bool freeze) -> Array[ParseWarning] def load_warnings(encoding, freeze) warnings = Array.new(load_varuint) do @@ -401,8 +434,9 @@ module Prism warnings end + #: () -> Array[[Token, Integer]] def load_tokens - tokens = [] + tokens = [] #: Array[[Token, Integer]] while (type = TOKEN_TYPES.fetch(load_varuint)) start = load_varuint @@ -420,25 +454,29 @@ module Prism # variable-length integer using https://en.wikipedia.org/wiki/LEB128 # This is also what protobuf uses: https://protobuf.dev/programming-guides/encoding/#varints + #-- + #: () -> Integer def load_varuint - n = io.getbyte + n = (io.getbyte or raise) if n < 128 n else n -= 128 shift = 0 - while (b = io.getbyte) >= 128 + while (b = (io.getbyte or raise)) >= 128 n += (b - 128) << (shift += 7) end n + (b << (shift + 7)) end end + #: () -> Integer def load_varsint n = load_varuint (n >> 1) ^ (-(n & 1)) end + #: () -> Integer def load_integer negative = io.getbyte != 0 length = load_varuint @@ -450,14 +488,17 @@ module Prism value end + #: () -> Float def load_double - io.read(8).unpack1("D") + (io.read(8) or raise).unpack1("D") #: Float end + #: () -> Integer def load_uint32 - io.read(4).unpack1("L") + (io.read(4) or raise).unpack1("L") #: Integer end + #: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? def load_optional_node(constant_pool, encoding, freeze) if io.getbyte != 0 io.pos -= 1 @@ -465,14 +506,16 @@ module Prism end end + #: (Encoding encoding) -> String def load_embedded_string(encoding) - io.read(load_varuint).force_encoding(encoding).freeze + (io.read(load_varuint) or raise).force_encoding(encoding).freeze end + #: (Encoding encoding) -> String def load_string(encoding) case (type = io.getbyte) when 1 - input.byteslice(load_varuint, load_varuint).force_encoding(encoding).freeze + (input.byteslice(load_varuint, load_varuint) or raise).force_encoding(encoding).freeze when 2 load_embedded_string(encoding) else @@ -480,75 +523,116 @@ module Prism end end + #: (bool freeze) -> Location def load_location_object(freeze) location = Location.new(source, load_varuint, load_varuint) location.freeze if freeze location end + # Load a location object from the serialized data. Note that we are lying + # about the signature a bit here, because we sometimes load it as a packed + # integer instead of an object. + #-- + #: (bool freeze) -> Location def load_location(freeze) return load_location_object(freeze) if freeze - (load_varuint << 32) | load_varuint + (load_varuint << 32) | load_varuint #: Location end + # Load an optional location object from the serialized data if it is + # present. Note that we are lying about the signature a bit here, because + # we sometimes load it as a packed integer instead of an object. + #-- + #: (bool freeze) -> Location? def load_optional_location(freeze) load_location(freeze) if io.getbyte != 0 end + #: (bool freeze) -> Location? def load_optional_location_object(freeze) load_location_object(freeze) if io.getbyte != 0 end + #: (ConstantPool constant_pool, Encoding encoding) -> Symbol def load_constant(constant_pool, encoding) index = load_varuint constant_pool.get(index - 1, encoding) end + #: (ConstantPool constant_pool, Encoding encoding) -> Symbol? def load_optional_constant(constant_pool, encoding) index = load_varuint constant_pool.get(index - 1, encoding) if index != 0 end if RUBY_ENGINE == "ruby" + #: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node def load_node(constant_pool, encoding, freeze) type = io.getbyte node_id = load_varuint - location = load_location(freeze) - value = case type - <%- nodes.each_with_index do |node, index| -%> - when <%= index + 1 %> then - <%- if node.needs_serialized_length? -%> - load_uint32 - <%- end -%> - <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field| - case field - when Prism::Template::NodeField then "load_node(constant_pool, encoding, freeze)" - when Prism::Template::OptionalNodeField then "load_optional_node(constant_pool, encoding, freeze)" - when Prism::Template::StringField then "load_string(encoding)" - when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node(constant_pool, encoding, freeze) }.tap { |nodes| nodes.freeze if freeze }" - when Prism::Template::ConstantField then "load_constant(constant_pool, encoding)" - when Prism::Template::OptionalConstantField then "load_optional_constant(constant_pool, encoding)" - when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_constant(constant_pool, encoding) }.tap { |constants| constants.freeze if freeze }" - when Prism::Template::LocationField then "load_location(freeze)" - when Prism::Template::OptionalLocationField then "load_optional_location(freeze)" - when Prism::Template::UInt8Field then "io.getbyte" - when Prism::Template::UInt32Field then "load_varuint" - when Prism::Template::IntegerField then "load_integer" - when Prism::Template::DoubleField then "load_double" - else raise - end - }].join(", ") -%>) + location = load_location(freeze) #: Location + value = + case type + <%- nodes.each_with_index do |node, index| -%> + when <%= index + 1 %> + <%- if node.needs_serialized_length? -%> + load_uint32 + <%- end -%> + <%= node.name %>.new( + source, + node_id, + location, + load_varuint, + <%- node.fields.each do |field| -%> + <%- case field -%> + <%- when Prism::Template::NodeField -%> + load_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::OptionalNodeField -%> + load_optional_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::StringField -%> + load_string(encoding), + <%- when Prism::Template::NodeListField -%> + Array.new(load_varuint) do + load_node(constant_pool, encoding, freeze) #: <%= field.element_rbs_class %> + end.tap { |nodes| nodes.freeze if freeze }, + <%- when Prism::Template::ConstantField -%> + load_constant(constant_pool, encoding), + <%- when Prism::Template::OptionalConstantField -%> + load_optional_constant(constant_pool, encoding), + <%- when Prism::Template::ConstantListField -%> + Array.new(load_varuint) { load_constant(constant_pool, encoding) }.tap { |constants| constants.freeze if freeze }, + <%- when Prism::Template::LocationField -%> + load_location(freeze), + <%- when Prism::Template::OptionalLocationField -%> + load_optional_location(freeze), + <%- when Prism::Template::UInt8Field -%> + (io.getbyte or raise), + <%- when Prism::Template::UInt32Field -%> + load_varuint, + <%- when Prism::Template::IntegerField -%> + load_integer, + <%- when Prism::Template::DoubleField -%> + load_double, + <%- else raise -%> + <%- end -%> + <%- end -%> + ) <%- end -%> - end + else + raise "Unknown node type: #{type}" + end value.freeze if freeze value end else + # @rbs skip def load_node(constant_pool, encoding, freeze) - @load_node_lambdas[io.getbyte].call(constant_pool, encoding, freeze) + @load_node_lambdas[(io.getbyte or raise)].call(constant_pool, encoding, freeze) end + # @rbs skip def define_load_node_lambdas @load_node_lambdas = [ nil, @@ -559,24 +643,46 @@ module Prism <%- if node.needs_serialized_length? -%> load_uint32 <%- end -%> - value = <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field| - case field - when Prism::Template::NodeField then "load_node(constant_pool, encoding, freeze)" - when Prism::Template::OptionalNodeField then "load_optional_node(constant_pool, encoding, freeze)" - when Prism::Template::StringField then "load_string(encoding)" - when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node(constant_pool, encoding, freeze) }" - when Prism::Template::ConstantField then "load_constant(constant_pool, encoding)" - when Prism::Template::OptionalConstantField then "load_optional_constant(constant_pool, encoding)" - when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_constant(constant_pool, encoding) }" - when Prism::Template::LocationField then "load_location(freeze)" - when Prism::Template::OptionalLocationField then "load_optional_location(freeze)" - when Prism::Template::UInt8Field then "io.getbyte" - when Prism::Template::UInt32Field then "load_varuint" - when Prism::Template::IntegerField then "load_integer" - when Prism::Template::DoubleField then "load_double" - else raise - end - }].join(", ") -%>) + value = + <%= node.name %>.new( + source, + node_id, + location, + load_varuint, + <%- node.fields.map do |field| -%> + <%- case field -%> + <%- when Prism::Template::NodeField -%> + load_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::OptionalNodeField -%> + load_optional_node(constant_pool, encoding, freeze), #: <%= field.rbs_class %> + <%- when Prism::Template::StringField -%> + load_string(encoding), + <%- when Prism::Template::NodeListField -%> + Array.new(load_varuint) do + load_node(constant_pool, encoding, freeze) #: <%= field.element_rbs_class %> + end, + <%- when Prism::Template::ConstantField -%> + load_constant(constant_pool, encoding), + <%- when Prism::Template::OptionalConstantField -%> + load_optional_constant(constant_pool, encoding), + <%- when Prism::Template::ConstantListField -%> + Array.new(load_varuint) { load_constant(constant_pool, encoding) }, + <%- when Prism::Template::LocationField -%> + load_location(freeze), + <%- when Prism::Template::OptionalLocationField -%> + load_optional_location(freeze), + <%- when Prism::Template::UInt8Field -%> + (io.getbyte or raise), + <%- when Prism::Template::UInt32Field -%> + load_varuint, + <%- when Prism::Template::IntegerField -%> + load_integer, + <%- when Prism::Template::DoubleField -%> + load_double, + <%- else raise -%> + <%- end -%> + <%- end -%> + ) value.freeze if freeze value }, @@ -584,6 +690,10 @@ module Prism ] end end + + # @rbs! + # @load_node_lambdas: Array[Proc] + # def define_load_node_lambdas: () -> void end # The token types that can be indexed by their enum values. @@ -592,7 +702,7 @@ module Prism <%- tokens.each do |token| -%> <%= token.name.to_sym.inspect %>, <%- end -%> - ].freeze + ].freeze #: Array[Symbol?] private_constant :MAJOR_VERSION, :MINOR_VERSION, :PATCH_VERSION private_constant :ConstantPool, :FastStringIO, :Loader, :TOKEN_TYPES diff --git a/templates/lib/prism/visitor.rb.erb b/templates/lib/prism/visitor.rb.erb index 76f907724f..78726c53f1 100644 --- a/templates/lib/prism/visitor.rb.erb +++ b/templates/lib/prism/visitor.rb.erb @@ -1,4 +1,13 @@ +# rbs_inline: enabled + module Prism + # @rbs! + # interface _Visitor + # <% nodes.each do |node| %> + # def visit_<%= node.human %>: (<%= node.name %>) -> void + # <% end %> + # end + # A class that knows how to walk down the tree. None of the individual visit # methods are implemented on this visitor, so it forces the consumer to # implement each one that they need. For a default implementation that @@ -6,18 +15,24 @@ module Prism class BasicVisitor # Calls `accept` on the given node if it is not `nil`, which in turn should # call back into this visitor by calling the appropriate `visit_*` method. + #-- + #: (node? node) -> void def visit(node) # @type self: _Visitor node&.accept(self) end # Visits each node in `nodes` by calling `accept` on each one. + #-- + #: (Array[node?] nodes) -> void def visit_all(nodes) # @type self: _Visitor nodes.each { |node| node&.accept(self) } end # Visits the child nodes of `node` by calling `accept` on each one. + #-- + #: (node node) -> void def visit_child_nodes(node) # @type self: _Visitor node.each_child_node { |node| node.accept(self) } @@ -47,6 +62,8 @@ module Prism <%- nodes.each_with_index do |node, index| -%> <%= "\n" if index != 0 -%> # Visit a <%= node.name %> node + #-- + #: (<%= node.name %> node) -> void def visit_<%= node.human %>(node) node.each_child_node { |node| node.accept(self) } end diff --git a/templates/sig/prism.rbs.erb b/templates/sig/prism.rbs.erb deleted file mode 100644 index ee35feccb8..0000000000 --- a/templates/sig/prism.rbs.erb +++ /dev/null @@ -1,92 +0,0 @@ -module Prism - BACKEND: :CEXT | :FFI - VERSION: String - - class CurrentVersionError < ArgumentError - def initialize: (String version) -> void - end - - # Methods taking a Ruby source code string: - <%- - { - parse: "ParseResult", - profile: "nil", - lex: "LexResult", - lex_compat: "LexCompat::Result", - parse_lex: "ParseLexResult", - dump: "String", - parse_comments: "Array[comment]", - parse_success?: "bool", - parse_failure?: "bool", - }.each do |method, return_type| - -%> - - def self.<%= method %>: ( - String source, - ?command_line: String, - ?encoding: Encoding | false, - ?filepath: String, - ?freeze: bool, - ?frozen_string_literal: bool, - ?line: Integer, - ?main_script: bool, - ?partial_script: bool, - ?scopes: Array[Array[Symbol]], - ?version: String - ) -> <%= return_type %> - <%- end -%> - - def self.load: ( - String source, - String serialized, - ?bool freeze - ) -> ParseResult - - # Methods taking a path to a Ruby file: - <%- - { - parse_file: "ParseResult", - profile_file: "nil", - lex_file: "LexResult", - parse_lex_file: "ParseLexResult", - dump_file: "String", - parse_file_comments: "Array[comment]", - parse_file_success?: "bool", - parse_file_failure?: "bool", - }.each do |method, return_type| - -%> - - def self.<%= method %>: ( - String filepath, - ?command_line: String, - ?encoding: Encoding | false, - ?freeze: bool, - ?frozen_string_literal: bool, - ?line: Integer, - ?main_script: bool, - ?partial_script: bool, - ?scopes: Array[Array[Symbol]], - ?version: String - ) -> <%= return_type %> - <%- end -%> - - interface _Stream - def gets: (?Integer integer) -> (String | nil) - end - - def self.parse_stream: ( - _Stream stream, - ?command_line: String, - ?encoding: Encoding | false, - ?filepath: String, - ?freeze: bool, - ?frozen_string_literal: bool, - ?line: Integer, - ?main_script: bool, - ?partial_script: bool, - ?scopes: Array[Array[Symbol]], - ?version: String - ) -> ParseResult - - def self.scope: (?locals: Array[Symbol], ?forwarding: Array[Symbol]) -> Scope -end diff --git a/templates/sig/prism/_private/dot_visitor.rbs.erb b/templates/sig/prism/_private/dot_visitor.rbs.erb deleted file mode 100644 index 4b380ecc97..0000000000 --- a/templates/sig/prism/_private/dot_visitor.rbs.erb +++ /dev/null @@ -1,45 +0,0 @@ -module Prism - class DotVisitor < Visitor - class Field - attr_reader name: String - attr_reader value: String? - attr_reader port: bool - - def initialize: (String name, String? value, bool port) -> void - def to_dot: () -> String - end - - class Table - attr_reader name: String - attr_reader fields: Array[Field] - - def initialize: (String name) -> void - def field: (String name, ?String? value, ?port: bool) -> void - def to_dot: () -> String - end - - class Digraph - attr_reader nodes: Array[String] - attr_reader waypoints: Array[String] - attr_reader edges: Array[String] - - def initialize: () -> void - def node: (String value) -> void - def waypoint: (String value) -> void - def edge: (String value) -> void - - def to_dot: () -> String - end - - attr_reader digraph: Digraph - - private - - def node_id: (Prism::node node) -> String - def location_inspect: (Location location) -> String - - <%- flags.each do |flag| -%> - def <%= flag.human %>_inspect: (<%= nodes.filter_map { |node| node.name if node.flags == flag }.join(" | ") %> node) -> String - <%- end -%> - end -end diff --git a/templates/sig/prism/dsl.rbs.erb b/templates/sig/prism/dsl.rbs.erb deleted file mode 100644 index 401467c0d8..0000000000 --- a/templates/sig/prism/dsl.rbs.erb +++ /dev/null @@ -1,31 +0,0 @@ -module Prism - module DSL - def source: (String string) -> Source - - def location: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location - <%- nodes.each do |node| -%> - <%- - params = [ - ["source", "Source"], - ["node_id", "Integer"], - ["location", "Location"], - ["flags", "Integer"] - ].concat(node.fields.map { |field| [field.name, field.rbs_class] }) - -%> - - def <%= node.human %>: (<%= params.map { |(name, type)| "?#{name}: #{type}" }.join(", ") %>) -> <%= node.name %> - <%- end -%> - <%- flags.each do |flag| -%> - - def <%= flag.human.chomp("s") %>: (Symbol name) -> Integer - <%- end -%> - - private - - def default_source: () -> Source - - def default_location: () -> Location - - def default_node: (Source source, Location location) -> node - end -end diff --git a/templates/sig/prism/mutation_compiler.rbs.erb b/templates/sig/prism/mutation_compiler.rbs.erb deleted file mode 100644 index 303269ba49..0000000000 --- a/templates/sig/prism/mutation_compiler.rbs.erb +++ /dev/null @@ -1,7 +0,0 @@ -module Prism - class MutationCompiler < Compiler - <%- nodes.each do |node| -%> - def visit_<%= node.human %>: (<%= node.name %>) -> node? - <%- end -%> - end -end diff --git a/templates/sig/prism/node.rbs.erb b/templates/sig/prism/node.rbs.erb deleted file mode 100644 index 138edc11f4..0000000000 --- a/templates/sig/prism/node.rbs.erb +++ /dev/null @@ -1,136 +0,0 @@ -module Prism - class Node - attr_reader source: Source - attr_reader node_id: Integer - attr_reader location: Location - attr_reader flags: Integer - - def newline?: () -> bool - def static_literal?: () -> bool - - def accept: (_Visitor) -> void - def child_nodes: () -> Array[Prism::node?] - def comment_targets: () -> Array[Prism::node | Location] - def compact_child_nodes: () -> Array[Prism::node] - def each_child_node: () { (Prism::node) -> void } -> void | () -> Enumerator[Prism::node] - def self.fields: () -> Array[Prism::Reflection::Field] - def type: () -> Symbol - def self.type: () -> Symbol - - def source_lines: () -> Array[String] - alias script_lines source_lines - def slice: () -> String - def slice_lines: () -> String - def pretty_print: (untyped q) -> untyped - def to_dot: () -> String - def tunnel: (Integer line, Integer column) -> Array[Prism::node] - def breadth_first_search: () { (Prism::node) -> bool } -> Prism::node? - alias find breadth_first_search - def breadth_first_search_all: () { (Prism::node) -> bool } -> Array[Prism::node] - alias find_all breadth_first_search_all - def newline!: (Array[untyped]) -> void - - def save: (_Repository repository) -> void - def save_location: (_Repository repository) -> void - - def leading_comments: () -> Array[comment] - def trailing_comments: () -> Array[comment] - def comments: () -> Array[comment] - - def start_offset: () -> Integer - def start_character_offset: () -> Integer - def start_code_units_offset: (Encoding encoding) -> Integer - def cached_start_code_units_offset: (_CodeUnitsCache cache) -> Integer - - def end_offset: () -> Integer - def end_character_offset: () -> Integer - def end_code_units_offset: (Encoding encoding) -> Integer - def cached_end_code_units_offset: (_CodeUnitsCache cache) -> Integer - - def start_line: () -> Integer - def end_line: () -> Integer - - def start_column: () -> Integer - def start_character_column: () -> Integer - def start_code_units_column: (Encoding encoding) -> Integer - def cached_start_code_units_column: (_CodeUnitsCache cache) -> Integer - - def end_column: () -> Integer - def end_character_column: () -> Integer - def end_code_units_column: (Encoding encoding) -> Integer - def cached_end_code_units_column: (_CodeUnitsCache cache) -> Integer - end - - # Methods implemented by every subclass of Node - interface _Node - def deconstruct: () -> Array[Prism::node?] - def inspect: () -> String - end - - type node = Node & _Node - - interface _Repository - def enter: (Integer node_id, Symbol field_name) -> void - end - - <%- nodes.each do |node| -%> - - <%- node.each_comment_line do |line| -%> - #<%= line %> - <%- end -%> - class <%= node.name -%> < Node - include _Node - <%- if (node_flags = node.flags) -%> - - <%- node_flags.values.each do |value| -%> - def <%= value.name.downcase %>?: () -> bool - <%- end -%> - <%- end -%> - - <%- node.fields.each do |field| -%> - attr_reader <%= field.name %>: <%= field.rbs_class %> - <%- end -%> - <%- if (locations = node.fields.select { |field| field.is_a?(Prism::Template::LocationField) || field.is_a?(Prism::Template::OptionalLocationField) }) -%> - - <%- locations.each do |field| -%> - def save_<%= field.name %>: (_Repository repository) -> void - <%- end -%> - <%- end -%> - - def initialize: (<%= ["Source source", "Integer node_id", "Location location", "Integer flags", *node.fields.map { |field| "#{field.rbs_class} #{field.name}" }].join(", ") %>) -> void - def copy: (<%= (["?node_id: Integer", "?location: Location", "?flags: Integer"] + node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" }).join(", ") %>) -> <%= node.name %> - def deconstruct_keys: (Array[Symbol] keys) -> { <%= (["node_id: Integer", "location: Location"] + node.fields.map { |field| "#{field.name}: #{field.rbs_class}" }).join(", ") %> } - <%- node.fields.each do |field| -%> - <%- case field -%> - <%- when Prism::Template::LocationField -%> - <%- raise unless field.name.end_with?("_loc") -%> - <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - def <%= field.name.delete_suffix("_loc") %>: () -> String - <%- when Prism::Template::OptionalLocationField -%> - <%- raise unless field.name.end_with?("_loc") -%> - <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - def <%= field.name.delete_suffix("_loc") %>: () -> String? - <%- end -%> - <%- end -%> - def type: () -> :<%= node.human %> - | ... - def self.type: () -> :<%= node.human %> - end - <%- end -%> - <%- flags.each do |flag| -%> - - # <%= flag.comment %> - module <%= flag.name %> - <%- flag.values.each do |value| -%> - # <%= value.comment %> - <%= value.name %>: Integer - <%- end -%> - end - <%- end -%> - - # The flags that are common to all nodes. - module NodeFlags - NEWLINE: Integer - STATIC_LITERAL: Integer - end -end diff --git a/templates/sig/prism/visitor.rbs.erb b/templates/sig/prism/visitor.rbs.erb deleted file mode 100644 index 2e8de030f6..0000000000 --- a/templates/sig/prism/visitor.rbs.erb +++ /dev/null @@ -1,17 +0,0 @@ -module Prism - class BasicVisitor - def visit: (Prism::node?) -> void - def visit_all: (Array[Prism::node?]) -> void - def visit_child_nodes: (Prism::node) -> void - end - - interface _Visitor - <%- nodes.each do |node| -%> - def visit_<%= node.human %>: (<%= node.name %>) -> void - <%- end -%> - end - - class Visitor < BasicVisitor - include _Visitor - end -end diff --git a/templates/template.rb b/templates/template.rb index 18da0647a0..a39f8bbb78 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -150,7 +150,7 @@ def rbs_class if specific_kind specific_kind elsif union_kind - union_kind.join(" | ") + "(#{union_kind.join(" | ")})" else "Prism::node" end @@ -192,7 +192,7 @@ def rbs_class if specific_kind "#{specific_kind}?" elsif union_kind - [*union_kind, "nil"].join(" | ") + "(#{union_kind.join(" | ")})?" else "Prism::node?" end @@ -230,16 +230,20 @@ def check_field_kind # This represents a field on a node that is a list of nodes. We pass them as # references and store them directly on the struct. class NodeListField < NodeKindField - def rbs_class + def element_rbs_class if specific_kind - "Array[#{specific_kind}]" + "#{specific_kind}" elsif union_kind - "Array[#{union_kind.join(" | ")}]" + "#{union_kind.join(" | ")}" else - "Array[Prism::node]" + "Prism::node" end end + def rbs_class + "Array[#{element_rbs_class}]" + end + def call_seq_type if specific_kind "Array[#{specific_kind}]" @@ -639,13 +643,6 @@ def render(name, write_to: nil) ++ =end - HEADING - when ".rbs" - <<~HEADING - # This file is generated by the templates/template.rb script and should not be - # modified manually. See #{filepath} - # if you are looking to modify the template - HEADING when ".rbi" <<~HEADING @@ -744,13 +741,7 @@ def locals "src/token_type.c", "rbi/prism/dsl.rbi", "rbi/prism/node.rbi", - "rbi/prism/visitor.rbi", - "sig/prism.rbs", - "sig/prism/dsl.rbs", - "sig/prism/mutation_compiler.rbs", - "sig/prism/node.rbs", - "sig/prism/visitor.rbs", - "sig/prism/_private/dot_visitor.rbs" + "rbi/prism/visitor.rbi" ] end end From e371985c916648737724e340e26676a772df9ef5 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:05:31 +0100 Subject: [PATCH 066/289] Don't document rbs inline magic comment --- lib/prism.rb | 3 ++- lib/prism/desugar_compiler.rb | 3 ++- lib/prism/lex_compat.rb | 3 ++- lib/prism/node_ext.rb | 3 ++- lib/prism/parse_result.rb | 3 ++- lib/prism/parse_result/comments.rb | 3 ++- lib/prism/parse_result/errors.rb | 3 ++- lib/prism/parse_result/newlines.rb | 3 ++- lib/prism/pattern.rb | 3 ++- lib/prism/relocation.rb | 3 ++- lib/prism/string_query.rb | 3 ++- lib/prism/translation.rb | 3 ++- lib/prism/translation/parser_current.rb | 1 + templates/lib/prism/compiler.rb.erb | 1 + templates/lib/prism/dispatcher.rb.erb | 1 + templates/lib/prism/dot_visitor.rb.erb | 1 + templates/lib/prism/dsl.rb.erb | 1 + templates/lib/prism/inspect_visitor.rb.erb | 1 + templates/lib/prism/mutation_compiler.rb.erb | 1 + templates/lib/prism/node.rb.erb | 1 + templates/lib/prism/reflection.rb.erb | 1 + templates/lib/prism/serialize.rb.erb | 1 + templates/lib/prism/visitor.rb.erb | 1 + 23 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/prism.rb b/lib/prism.rb index c7530e5874..079026cf89 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled # The Prism Ruby parser. # diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb index e08faa3219..c64d03f64a 100644 --- a/lib/prism/desugar_compiler.rb +++ b/lib/prism/desugar_compiler.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism class DesugarAndWriteNode # :nodoc: diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index bdef99acfc..7f3f30b88d 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism # @rbs! diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 57593a1612..61f36e09be 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled #-- # Here we are reopening the prism module to provide methods on nodes that aren't diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index e2e1145bdc..9825d559af 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism # @rbs! diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index 7b54ce7fd6..df80792d39 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism class ParseResult < Result diff --git a/lib/prism/parse_result/errors.rb b/lib/prism/parse_result/errors.rb index 03d65daecf..388309d23d 100644 --- a/lib/prism/parse_result/errors.rb +++ b/lib/prism/parse_result/errors.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled require "stringio" diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index cfbc1ea1d0..82e72bd564 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism class ParseResult < Result diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index b15b04d9bc..cbfb2c69b7 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism # A pattern is an object that wraps a Ruby pattern matching expression. The diff --git a/lib/prism/relocation.rb b/lib/prism/relocation.rb index 2ac471d425..af0f792827 100644 --- a/lib/prism/relocation.rb +++ b/lib/prism/relocation.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism # Prism parses deterministically for the same input. This provides a nice diff --git a/lib/prism/string_query.rb b/lib/prism/string_query.rb index c0dee63d3f..99ce57e5fe 100644 --- a/lib/prism/string_query.rb +++ b/lib/prism/string_query.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism # Query methods that allow categorizing strings based on their context for diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb index d1afa5d8c5..5a086a7542 100644 --- a/lib/prism/translation.rb +++ b/lib/prism/translation.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# rbs_inline: enabled # :markup: markdown +#-- +# rbs_inline: enabled module Prism # This module is responsible for converting the prism syntax tree into other diff --git a/lib/prism/translation/parser_current.rb b/lib/prism/translation/parser_current.rb index 2dd018627c..f7c1070e30 100644 --- a/lib/prism/translation/parser_current.rb +++ b/lib/prism/translation/parser_current.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true # :markup: markdown +#-- # typed: ignore module Prism diff --git a/templates/lib/prism/compiler.rb.erb b/templates/lib/prism/compiler.rb.erb index 16035b5456..13317cac04 100644 --- a/templates/lib/prism/compiler.rb.erb +++ b/templates/lib/prism/compiler.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism diff --git a/templates/lib/prism/dispatcher.rb.erb b/templates/lib/prism/dispatcher.rb.erb index f1bd80a7cd..5991b0c904 100644 --- a/templates/lib/prism/dispatcher.rb.erb +++ b/templates/lib/prism/dispatcher.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism diff --git a/templates/lib/prism/dot_visitor.rb.erb b/templates/lib/prism/dot_visitor.rb.erb index 3e37cf1a57..bdac9cfd3c 100644 --- a/templates/lib/prism/dot_visitor.rb.erb +++ b/templates/lib/prism/dot_visitor.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled require "cgi/escape" diff --git a/templates/lib/prism/dsl.rb.erb b/templates/lib/prism/dsl.rb.erb index de265a095b..a75b8b253e 100644 --- a/templates/lib/prism/dsl.rb.erb +++ b/templates/lib/prism/dsl.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism diff --git a/templates/lib/prism/inspect_visitor.rb.erb b/templates/lib/prism/inspect_visitor.rb.erb index 9b15cb3d8a..820f5ae75f 100644 --- a/templates/lib/prism/inspect_visitor.rb.erb +++ b/templates/lib/prism/inspect_visitor.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism diff --git a/templates/lib/prism/mutation_compiler.rb.erb b/templates/lib/prism/mutation_compiler.rb.erb index 6fcbb25dcc..2d555048d2 100644 --- a/templates/lib/prism/mutation_compiler.rb.erb +++ b/templates/lib/prism/mutation_compiler.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index 195200e482..2e42eeea13 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism diff --git a/templates/lib/prism/reflection.rb.erb b/templates/lib/prism/reflection.rb.erb index d5ace99259..0012f120b2 100644 --- a/templates/lib/prism/reflection.rb.erb +++ b/templates/lib/prism/reflection.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index 229322291e..433b520788 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled require "stringio" diff --git a/templates/lib/prism/visitor.rb.erb b/templates/lib/prism/visitor.rb.erb index 78726c53f1..f23e87d99e 100644 --- a/templates/lib/prism/visitor.rb.erb +++ b/templates/lib/prism/visitor.rb.erb @@ -1,3 +1,4 @@ +#-- # rbs_inline: enabled module Prism From 2c88ed893ffb9012e29d544f5e970e55267a96fc Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 22 Feb 2026 16:40:04 -0500 Subject: [PATCH 067/289] Generate RBI from RBS --- gemfiles/typecheck/Gemfile | 2 +- gemfiles/typecheck/Gemfile.lock | 5 +- lib/prism.rb | 4 +- lib/prism/lex_compat.rb | 9 + lib/prism/node_ext.rb | 3 +- lib/prism/parse_result/newlines.rb | 24 +- lib/prism/pattern.rb | 4 +- prism.gemspec | 32 +- rakelib/typecheck.rake | 318 +- rbi/generated/prism.rbi | 79 + rbi/generated/prism/compiler.rbi | 489 + rbi/generated/prism/desugar_compiler.rbi | 306 + rbi/generated/prism/dispatcher.rbi | 1134 ++ rbi/generated/prism/dot_visitor.rbi | 618 + rbi/generated/prism/dsl.rbi | 747 + rbi/generated/prism/inspect_visitor.rbi | 503 + rbi/generated/prism/lex_compat.rbi | 155 + rbi/generated/prism/mutation_compiler.rbi | 464 + rbi/generated/prism/node.rbi | 13811 ++++++++++++++++ rbi/generated/prism/node_ext.rbi | 333 + rbi/generated/prism/parse_result.rbi | 707 + rbi/generated/prism/parse_result/comments.rbi | 90 + rbi/generated/prism/parse_result/errors.rbi | 21 + rbi/generated/prism/parse_result/newlines.rbi | 121 + rbi/generated/prism/pattern.rbi | 134 + rbi/generated/prism/reflection.rbi | 89 + rbi/generated/prism/relocation.rbi | 389 + rbi/generated/prism/serialize.rbi | 172 + rbi/generated/prism/string_query.rbi | 36 + rbi/generated/prism/translation.rbi | 7 + rbi/generated/prism/visitor.rbi | 650 + rbi/prism.rbi | 63 - rbi/prism/compiler.rbi | 12 - rbi/prism/inspect_visitor.rbi | 12 - rbi/prism/node_ext.rbi | 107 - rbi/prism/parse_result.rbi | 404 - rbi/prism/reflection.rbi | 58 - rbi/prism/string_query.rbi | 12 - rbi/prism/translation/parser_versions.rbi | 5 + sig/generated/prism/dot_visitor.rbs | 608 +- sig/generated/prism/lex_compat.rbs | 9 + sig/generated/prism/node.rbs | 1526 +- sig/generated/prism/parse_result/newlines.rbs | 48 +- sig/generated/prism/pattern.rbs | 6 +- templates/lib/prism/dot_visitor.rb.erb | 2 +- templates/lib/prism/node.rb.erb | 14 +- templates/rbi/prism/dsl.rbi.erb | 68 - templates/rbi/prism/node.rbi.erb | 167 - templates/rbi/prism/visitor.rbi.erb | 18 - templates/template.rb | 89 +- 50 files changed, 22526 insertions(+), 2158 deletions(-) create mode 100644 rbi/generated/prism.rbi create mode 100644 rbi/generated/prism/compiler.rbi create mode 100644 rbi/generated/prism/desugar_compiler.rbi create mode 100644 rbi/generated/prism/dispatcher.rbi create mode 100644 rbi/generated/prism/dot_visitor.rbi create mode 100644 rbi/generated/prism/dsl.rbi create mode 100644 rbi/generated/prism/inspect_visitor.rbi create mode 100644 rbi/generated/prism/lex_compat.rbi create mode 100644 rbi/generated/prism/mutation_compiler.rbi create mode 100644 rbi/generated/prism/node.rbi create mode 100644 rbi/generated/prism/node_ext.rbi create mode 100644 rbi/generated/prism/parse_result.rbi create mode 100644 rbi/generated/prism/parse_result/comments.rbi create mode 100644 rbi/generated/prism/parse_result/errors.rbi create mode 100644 rbi/generated/prism/parse_result/newlines.rbi create mode 100644 rbi/generated/prism/pattern.rbi create mode 100644 rbi/generated/prism/reflection.rbi create mode 100644 rbi/generated/prism/relocation.rbi create mode 100644 rbi/generated/prism/serialize.rbi create mode 100644 rbi/generated/prism/string_query.rbi create mode 100644 rbi/generated/prism/translation.rbi create mode 100644 rbi/generated/prism/visitor.rbi delete mode 100644 rbi/prism.rbi delete mode 100644 rbi/prism/compiler.rbi delete mode 100644 rbi/prism/inspect_visitor.rbi delete mode 100644 rbi/prism/node_ext.rbi delete mode 100644 rbi/prism/parse_result.rbi delete mode 100644 rbi/prism/reflection.rbi delete mode 100644 rbi/prism/string_query.rbi delete mode 100644 templates/rbi/prism/dsl.rbi.erb delete mode 100644 templates/rbi/prism/node.rbi.erb delete mode 100644 templates/rbi/prism/visitor.rbi.erb diff --git a/gemfiles/typecheck/Gemfile b/gemfiles/typecheck/Gemfile index 63003220c3..3965a1c17d 100644 --- a/gemfiles/typecheck/Gemfile +++ b/gemfiles/typecheck/Gemfile @@ -5,10 +5,10 @@ source "https://rubygems.org" gem "parser" gem "rake-compiler" gem "rake" +gem "rbi" gem "rbs-inline" gem "ruby_parser" gem "sorbet", "<= 0.6.12666" # until tapioca is bumped gem "steep", ">= 1.7.0.dev.1" gem "tapioca" gem "test-unit" -gem "tsort" # until rbs is bumped diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index 5e22e9088e..4460d320e9 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -54,8 +54,9 @@ GEM rbi (0.3.7) prism (~> 1.0) rbs (>= 3.4.4) - rbs (3.10.2) + rbs (3.10.3) logger + tsort rbs-inline (0.13.0) prism (>= 0.29) rbs (>= 3.8.0) @@ -133,13 +134,13 @@ DEPENDENCIES parser rake rake-compiler + rbi rbs-inline ruby_parser sorbet (<= 0.6.12666) steep (>= 1.7.0.dev.1) tapioca test-unit - tsort BUNDLED WITH 2.5.16 diff --git a/lib/prism.rb b/lib/prism.rb index 079026cf89..6b34ab12bf 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -43,12 +43,12 @@ class CurrentVersionError < ArgumentError #: (String version) -> void def initialize(version) message = +"invalid version: Requested to parse as `version: 'current'`; " - segments = + major, minor, = if version.match?(/\A\d+\.\d+.\d+\z/) version.split(".").map(&:to_i) end - if segments && ((segments[0] < 3) || (segments[0] == 3 && segments[1] < 3)) + if major && minor && ((major < 3) || (major == 3 && minor < 3)) message << " #{version} is below the minimum supported syntax." else message << " #{version} is unknown. Please update the `prism` gem." diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 7f3f30b88d..99d8daacdd 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -7,7 +7,16 @@ module Prism # @rbs! # module Translation # class Ripper + # EXPR_NONE: Integer # EXPR_BEG: Integer + # EXPR_MID: Integer + # EXPR_END: Integer + # EXPR_CLASS: Integer + # EXPR_VALUE: Integer + # EXPR_ARG: Integer + # EXPR_CMDARG: Integer + # EXPR_ENDARG: Integer + # EXPR_ENDFN: Integer # # class Lexer < Ripper # class State diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 61f36e09be..4457c26fbe 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -11,8 +11,7 @@ module Prism class Node #: (*String replacements) -> void def deprecated(*replacements) # :nodoc: - location = caller_locations(1, 1) - location = location[0].label if location + location = caller_locations(1, 1)&.[](0)&.label suggest = replacements.map { |replacement| "#{self.class}##{replacement}" } warn(<<~MSG, uplevel: 1, category: :deprecated) diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index 82e72bd564..450c790226 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -114,56 +114,56 @@ def newline_flag!(lines) # :nodoc: end class BeginNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: # Never mark BeginNode with a newline flag, mark children instead. end end class ParenthesesNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: # Never mark ParenthesesNode with a newline flag, mark children instead. end end class IfNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class UnlessNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class UntilNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class WhileNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: predicate.newline_flag!(lines) end end class RescueModifierNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: expression.newline_flag!(lines) end end class InterpolatedMatchLastLineNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -171,7 +171,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedRegularExpressionNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -179,7 +179,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedStringNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -187,7 +187,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedSymbolNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first @@ -195,7 +195,7 @@ def newline_flag!(lines) # :nodoc: end class InterpolatedXStringNode < Node - # @rbs override + #: (Array[bool] lines) -> void def newline_flag!(lines) # :nodoc: first = parts.first first.newline_flag!(lines) if first diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index cbfb2c69b7..be0493df05 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -94,9 +94,9 @@ def compile # matches the pattern. If no block is given, an enumerator will be returned # that will yield each node that matches the pattern. #-- - #: (node root) { (node) -> void } -> void #: (node root) -> Enumerator[node, void] - def scan(root) + #: (node root) { (node) -> void } -> void + def scan(root, &blk) return to_enum(:scan, root) unless block_given? @compiled ||= compile diff --git a/prism.gemspec b/prism.gemspec index f3cba41a43..ca2db717ba 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -110,19 +110,31 @@ Gem::Specification.new do |spec| "lib/prism/translation/ruby_parser.rb", "lib/prism/visitor.rb", "prism.gemspec", - "rbi/prism.rbi", - "rbi/prism/compiler.rbi", - "rbi/prism/dsl.rbi", - "rbi/prism/inspect_visitor.rbi", - "rbi/prism/node_ext.rbi", - "rbi/prism/node.rbi", - "rbi/prism/parse_result.rbi", - "rbi/prism/reflection.rbi", - "rbi/prism/string_query.rbi", + "rbi/generated/prism.rbi", + "rbi/generated/prism/compiler.rbi", + "rbi/generated/prism/desugar_compiler.rbi", + "rbi/generated/prism/dispatcher.rbi", + "rbi/generated/prism/dot_visitor.rbi", + "rbi/generated/prism/dsl.rbi", + "rbi/generated/prism/inspect_visitor.rbi", + "rbi/generated/prism/lex_compat.rbi", + "rbi/generated/prism/mutation_compiler.rbi", + "rbi/generated/prism/node.rbi", + "rbi/generated/prism/node_ext.rbi", + "rbi/generated/prism/parse_result.rbi", + "rbi/generated/prism/pattern.rbi", + "rbi/generated/prism/reflection.rbi", + "rbi/generated/prism/relocation.rbi", + "rbi/generated/prism/serialize.rbi", + "rbi/generated/prism/string_query.rbi", + "rbi/generated/prism/translation.rbi", + "rbi/generated/prism/visitor.rbi", + "rbi/generated/prism/parse_result/comments.rbi", + "rbi/generated/prism/parse_result/errors.rbi", + "rbi/generated/prism/parse_result/newlines.rbi", "rbi/prism/translation/parser.rbi", "rbi/prism/translation/parser_versions.rbi", "rbi/prism/translation/ripper.rbi", - "rbi/prism/visitor.rbi", "sig/generated/prism.rbs", "sig/generated/prism/compiler.rbs", "sig/generated/prism/desugar_compiler.rbs", diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index 52cc0d17f1..8fd2b09f25 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -1,6 +1,265 @@ # frozen_string_literal: true namespace :typecheck do + class RBICompiler + INODE = Set.new(%i[accept child_nodes comment_targets compact_child_nodes deconstruct each_child_node inspect type]) + + attr_reader :parent + + def initialize(parent, abstract: Set.new, override: Set.new) + @parent = parent + @abstract = abstract + @override = override + @visibility = RBI::Public.new + end + + def compile_comments(node) + comments = [] + + if (comment = node.comment) + index = 0 + lines = comment.string.lines(chomp: true) + + while index < lines.length + case (line = lines[index]) + when ":call-seq:" + # skip RDoc call-seq annotations + index += 1 until index >= lines.length || lines[index + 1].empty? + index += 1 + when "--" + # break when RDoc private starts + break + when /\A:/ + # skip RBS type annotations + else + comments << RBI::Comment.new(line) + end + + index += 1 + end + end + + comments + end + + def compile(node) + case node + when RBS::AST::Members::AttrReader + parent << + RBI::AttrReader.new( + node.name.name, + visibility: @visibility, + sigs: [RBI::Sig.new(return_type: compile_type(node.type).to_rbi)], + comments: compile_comments(node) + ) + when RBS::AST::Members::Include + parent << RBI::Include.new(compile_name(node.name)) + when RBS::AST::Members::Private + @visibility = RBI::Private.new + when RBS::AST::Declarations::Constant + parent << + RBI::Const.new( + compile_name(node.name), + "T.let(nil, #{compile_type(node.type).to_rbi})", + comments: compile_comments(node) + ) + when RBS::AST::Declarations::Class + parent << RBI::Class.new(compile_name(node.name), comments: compile_comments(node)) do |cls| + abstract = Set.new + override = Set.new + + if parent && parent.name.name == "Prism" && cls.name.name == "Node" + cls << RBI::Helper.new("abstract") + abstract = INODE + end + + if (super_class = node.super_class).is_a?(RBS::AST::Declarations::Class::Super) + cls.superclass_name = compile_name(super_class.name) + override = INODE if parent && parent.name.name == "Prism" && super_class.name.name.name == "Node" + end + + compiler = RBICompiler.new(cls, abstract: abstract, override: override) + node.members.each { |member| compiler.compile(member) } + end + when RBS::AST::Declarations::Module + parent << RBI::Module.new(compile_name(node.name), comments: compile_comments(node)) do |mod| + compiler = RBICompiler.new(mod) + node.members.each { |member| compiler.compile(member) } + end + when RBS::AST::Members::MethodDefinition + parent << + RBI::Method.new( + node.name.name, + visibility: @visibility, + is_singleton: node.kind == :singleton, + comments: compile_comments(node) + ) do |method| + params = Set.new + node.overloads.each_with_index do |overload, index| + method_type = overload.method_type + func = method_type.type + + sig = + RBI::Sig.new( + return_type: compile_type(func.return_type).to_rbi, + is_abstract: @abstract.include?(node.name), + is_override: @override.include?(node.name) + ) + + compile_function(func) do |kind, name, type| + if !params.include?(name) + case kind + when :param then method.add_param(name) + when :opt_param then method.add_opt_param(name, "T.unsafe(nil)") + when :rest_param then method.add_rest_param(name) + when :kw_opt_param then method.add_kw_opt_param(name, "T.unsafe(nil)") + when :kw_rest_param then method.add_kw_rest_param(name) + else raise + end + params.add(name) + end + + sig.params << RBI::SigParam.new(name, type) + end + + if (block = method_type.block) + if !params.include?("blk") + method.add_block_param("blk") + params.add("blk") + end + + proc = RBI::Type.proc + compile_function(block.type) { |kind, name, type| proc.proc_params[name] = type } + proc.returns(compile_type(block.type.return_type)) + + sig.params << RBI::SigParam.new("blk", proc) + end + + method.sigs << sig + end + end + when RBS::AST::Members::Alias, RBS::AST::Members::InstanceVariable, + RBS::AST::Declarations::Interface, RBS::AST::Declarations::TypeAlias + # skip + else + raise + end + end + + private + + def compile_name(name) + RBI::Type.simple(name.to_namespace.path.join("::")) + end + + def compile_function(func) + argidx = -1 + kwargidx = -1 + + func.required_positionals.each do |param| + yield :param, param.name&.name || "arg#{argidx += 1}", compile_type(param.type) + end + + func.optional_positionals.each do |param| + yield :opt_param, param.name&.name || "arg#{argidx += 1}", compile_type(param.type) + end + + if (rest_positionals = func.rest_positionals) + yield :rest_param, rest_positionals.name&.name || "args", compile_type(rest_positionals.type) + end + + func.trailing_positionals.each do |param| + raise + end + + func.required_keywords.each do |param| + raise + end + + func.optional_keywords.each do |name, param| + yield :kw_opt_param, name, compile_type(param.type) + end + + if (rest_keywords = func.rest_keywords) + yield :kw_rest_param, rest_keywords.name&.name || "kwargs", compile_type(rest_keywords.type) + end + end + + def compile_type(type) + case type + when RBS::Types::Literal + case type.literal + when FalseClass + RBI::Type.simple("FalseClass") + when Symbol + RBI::Type.simple("Symbol") + else + raise + end + when RBS::Types::Bases::Any + RBI::Type.untyped + when RBS::Types::Bases::Bool + RBI::Type.boolean + when RBS::Types::Bases::Bottom + RBI::Type.noreturn + when RBS::Types::Bases::Self + RBI::Type.self_type + when RBS::Types::Bases::Void + RBI::Type.void + when RBS::Types::Union + RBI::Type.any(*type.types.map { |child| compile_type(child) }) + when RBS::Types::Tuple + RBI::Type.tuple(*type.types.map { |child| compile_type(child) }) + when RBS::Types::ClassSingleton + RBI::Type.class_of(compile_name(type.name)) + when RBS::Types::Optional + RBI::Type.nilable(compile_type(type.type)) + when RBS::Types::ClassInstance + if (args = type.args).any? + case (name = type.name.name) + when :Array, :Hash + RBI::Type.generic("T::#{name.name}", *args.map { |arg| compile_type(arg) }) + when :Enumerator + RBI::Type.generic("T::Enumerator", compile_type(args.first)) + else + raise + end + else + compile_name(type.name) + end + when RBS::Types::Alias + case type.name.name + when :node + RBI::Type.simple("Node") + when :lex_compat_token + RBI::Type.tuple( + RBI::Type.tuple(RBI::Type.simple("Integer"), RBI::Type.simple("Integer")), + RBI::Type.simple("Symbol"), + RBI::Type.simple("String"), + RBI::Type.untyped + ) + when :entry_values + RBI::Type.generic("T::Hash", RBI::Type.simple("Symbol"), RBI::Type.untyped) + when :entry_value + RBI::Type.untyped + when :boolish + RBI::Type.nilable(RBI::Type.boolean) + else + raise + end + when RBS::Types::Interface + case type.name.name + when :_CodeUnitsCache, :_CommentTarget, :_Field, :_Repository, :_Stream, :_Value, :_Visitor + RBI::Type.untyped + else + raise + end + else + raise + end + end + end + def with_gemfile Bundler.with_original_env do ENV['BUNDLE_GEMFILE'] = "gemfiles/typecheck/Gemfile" @@ -8,6 +267,46 @@ namespace :typecheck do end end + desc "Generate RBS with rbs-inline" + task rbs_inline: :templates do + with_gemfile do + sh "bundle", "exec", "rbs-inline", "lib", "--output", "lib" + end + end + + desc "Generate RBIs from RBSs" + task rbi: :rbs_inline do + with_gemfile do + require "fileutils" + require "rbs" + require "rbi" + require "set" + + rbs_base = File.expand_path("../sig/generated", __dir__) + rbi_base = File.expand_path("../rbi/generated", __dir__) + + Dir["**/*.rbs", base: rbs_base].each do |filepath| + RBI::File.new(strictness: "true") do |file| + compiler = RBICompiler.new(file) + + _, _, decls = RBS::Parser.parse_signature(File.read(File.join(rbs_base, filepath))) + decls.each { |decl| compiler.compile(decl) } + + mkdir_p((dirpath = File.join(rbi_base, File.dirname(filepath)))) + File.write(File.join(dirpath, "#{File.basename(filepath, ".rbs")}.rbi"), file.string) + end + end + end + end + + desc "Typecheck with Steep" + task steep: :templates do + with_gemfile do + sh "bundle", "exec", "steep", "check" + end + end + + desc "Generate RBIs with Tapioca" task tapioca: :templates do Rake::Task["compile:prism"].invoke @@ -28,13 +327,12 @@ namespace :typecheck do File.write("sorbet/typed_overrides.yml", ERB.new(<<~YAML, trim_mode: "-").result_with_hash(locals)) false: - ./lib/prism/lex_compat.rb + - ./lib/prism/node.rb - ./lib/prism/node_ext.rb - ./lib/prism/parse_result.rb - - ./lib/prism/visitor.rb + - ./lib/prism/pattern.rb - ./lib/prism/translation/parser/lexer.rb - ./lib/prism/translation/ripper.rb - - ./lib/prism/translation/ripper/filter.rb - - ./lib/prism/translation/ripper/lexer.rb - ./lib/prism/translation/ripper/sexp.rb - ./lib/prism/translation/ruby_parser.rb - ./lib/prism/inspect_visitor.rb @@ -76,18 +374,4 @@ namespace :typecheck do sh "bundle", "exec", "srb" end end - - desc "Generate RBS with rbs-inline" - task rbs_inline: :templates do - with_gemfile do - sh "bundle", "exec", "rbs-inline", "lib", "--output", "lib" - end - end - - desc "Typecheck with Steep" - task steep: :templates do - with_gemfile do - sh "bundle", "exec", "steep", "check" - end - end end diff --git a/rbi/generated/prism.rbi b/rbi/generated/prism.rbi new file mode 100644 index 0000000000..355ebd2073 --- /dev/null +++ b/rbi/generated/prism.rbi @@ -0,0 +1,79 @@ +# typed: true + +# The Prism Ruby parser. +# +# "Parsing Ruby is suddenly manageable!" +# - You, hopefully +module Prism + # Raised when requested to parse as the currently running Ruby version but Prism has no support for it. + class CurrentVersionError < ArgumentError + # Initialize a new exception for the given ruby version string. + sig { params(version: String).void } + def initialize(version); end + end + + # Returns a parse result whose value is an array of tokens that closely + # resembles the return value of Ripper.lex. + # + # For supported options, see Prism.parse. + sig { params(source: String, options: T.untyped).returns(LexCompat::Result) } + def self.lex_compat(source, **options); end + + # Load the serialized AST using the source as a reference into a tree. + sig { params(source: String, serialized: String, freeze: T::Boolean).returns(ParseResult) } + def self.load(source, serialized, freeze = T.unsafe(nil)); end + + VERSION = T.let(nil, String) + BACKEND = T.let(nil, Symbol) + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + def self.parse(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } + def self.profile(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } + def self.lex(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } + def self.parse_lex(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } + def self.dump(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } + def self.parse_comments(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_success?(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_failure?(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(stream: T.untyped, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + def self.parse_stream(stream, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + def self.parse_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } + def self.profile_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } + def self.lex_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } + def self.parse_lex_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } + def self.dump_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } + def self.parse_file_comments(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_file_success?(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end + + sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + def self.parse_file_failure?(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end +end diff --git a/rbi/generated/prism/compiler.rbi b/rbi/generated/prism/compiler.rbi new file mode 100644 index 0000000000..4a47221123 --- /dev/null +++ b/rbi/generated/prism/compiler.rbi @@ -0,0 +1,489 @@ +# typed: true + +module Prism + # A compiler is a visitor that returns the value of each node as it visits. + # This is as opposed to a visitor which will only walk the tree. This can be + # useful when you are trying to compile a tree into a different format. + # + # For example, to build a representation of the tree as s-expressions, you + # could write: + # + # class SExpressions < Prism::Compiler + # def visit_arguments_node(node) = [:arguments, super] + # def visit_call_node(node) = [:call, super] + # def visit_integer_node(node) = [:integer] + # def visit_program_node(node) = [:program, super] + # end + # + # Prism.parse("1 + 2").value.accept(SExpressions.new) + # # => [:program, [[[:call, [[:integer], [:arguments, [[:integer]]]]]]]] + class Compiler < Visitor + # Visit an individual node. + sig { params(arg0: T.nilable(Node)).returns(T.untyped) } + def visit(arg0); end + + # Visit a list of nodes. + sig { params(arg0: T::Array[T.nilable(Node)]).returns(T.untyped) } + def visit_all(arg0); end + + # Visit the child nodes of the given node. + sig { params(arg0: Node).returns(T::Array[T.untyped]) } + def visit_child_nodes(arg0); end + + sig { params(arg0: AliasGlobalVariableNode).returns(T::Array[T.untyped]) } + def visit_alias_global_variable_node(arg0); end + + sig { params(arg0: AliasMethodNode).returns(T::Array[T.untyped]) } + def visit_alias_method_node(arg0); end + + sig { params(arg0: AlternationPatternNode).returns(T::Array[T.untyped]) } + def visit_alternation_pattern_node(arg0); end + + sig { params(arg0: AndNode).returns(T::Array[T.untyped]) } + def visit_and_node(arg0); end + + sig { params(arg0: ArgumentsNode).returns(T::Array[T.untyped]) } + def visit_arguments_node(arg0); end + + sig { params(arg0: ArrayNode).returns(T::Array[T.untyped]) } + def visit_array_node(arg0); end + + sig { params(arg0: ArrayPatternNode).returns(T::Array[T.untyped]) } + def visit_array_pattern_node(arg0); end + + sig { params(arg0: AssocNode).returns(T::Array[T.untyped]) } + def visit_assoc_node(arg0); end + + sig { params(arg0: AssocSplatNode).returns(T::Array[T.untyped]) } + def visit_assoc_splat_node(arg0); end + + sig { params(arg0: BackReferenceReadNode).returns(T::Array[T.untyped]) } + def visit_back_reference_read_node(arg0); end + + sig { params(arg0: BeginNode).returns(T::Array[T.untyped]) } + def visit_begin_node(arg0); end + + sig { params(arg0: BlockArgumentNode).returns(T::Array[T.untyped]) } + def visit_block_argument_node(arg0); end + + sig { params(arg0: BlockLocalVariableNode).returns(T::Array[T.untyped]) } + def visit_block_local_variable_node(arg0); end + + sig { params(arg0: BlockNode).returns(T::Array[T.untyped]) } + def visit_block_node(arg0); end + + sig { params(arg0: BlockParameterNode).returns(T::Array[T.untyped]) } + def visit_block_parameter_node(arg0); end + + sig { params(arg0: BlockParametersNode).returns(T::Array[T.untyped]) } + def visit_block_parameters_node(arg0); end + + sig { params(arg0: BreakNode).returns(T::Array[T.untyped]) } + def visit_break_node(arg0); end + + sig { params(arg0: CallAndWriteNode).returns(T::Array[T.untyped]) } + def visit_call_and_write_node(arg0); end + + sig { params(arg0: CallNode).returns(T::Array[T.untyped]) } + def visit_call_node(arg0); end + + sig { params(arg0: CallOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_call_operator_write_node(arg0); end + + sig { params(arg0: CallOrWriteNode).returns(T::Array[T.untyped]) } + def visit_call_or_write_node(arg0); end + + sig { params(arg0: CallTargetNode).returns(T::Array[T.untyped]) } + def visit_call_target_node(arg0); end + + sig { params(arg0: CapturePatternNode).returns(T::Array[T.untyped]) } + def visit_capture_pattern_node(arg0); end + + sig { params(arg0: CaseMatchNode).returns(T::Array[T.untyped]) } + def visit_case_match_node(arg0); end + + sig { params(arg0: CaseNode).returns(T::Array[T.untyped]) } + def visit_case_node(arg0); end + + sig { params(arg0: ClassNode).returns(T::Array[T.untyped]) } + def visit_class_node(arg0); end + + sig { params(arg0: ClassVariableAndWriteNode).returns(T::Array[T.untyped]) } + def visit_class_variable_and_write_node(arg0); end + + sig { params(arg0: ClassVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_class_variable_operator_write_node(arg0); end + + sig { params(arg0: ClassVariableOrWriteNode).returns(T::Array[T.untyped]) } + def visit_class_variable_or_write_node(arg0); end + + sig { params(arg0: ClassVariableReadNode).returns(T::Array[T.untyped]) } + def visit_class_variable_read_node(arg0); end + + sig { params(arg0: ClassVariableTargetNode).returns(T::Array[T.untyped]) } + def visit_class_variable_target_node(arg0); end + + sig { params(arg0: ClassVariableWriteNode).returns(T::Array[T.untyped]) } + def visit_class_variable_write_node(arg0); end + + sig { params(arg0: ConstantAndWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_and_write_node(arg0); end + + sig { params(arg0: ConstantOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_operator_write_node(arg0); end + + sig { params(arg0: ConstantOrWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_or_write_node(arg0); end + + sig { params(arg0: ConstantPathAndWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_path_and_write_node(arg0); end + + sig { params(arg0: ConstantPathNode).returns(T::Array[T.untyped]) } + def visit_constant_path_node(arg0); end + + sig { params(arg0: ConstantPathOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_path_operator_write_node(arg0); end + + sig { params(arg0: ConstantPathOrWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_path_or_write_node(arg0); end + + sig { params(arg0: ConstantPathTargetNode).returns(T::Array[T.untyped]) } + def visit_constant_path_target_node(arg0); end + + sig { params(arg0: ConstantPathWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_path_write_node(arg0); end + + sig { params(arg0: ConstantReadNode).returns(T::Array[T.untyped]) } + def visit_constant_read_node(arg0); end + + sig { params(arg0: ConstantTargetNode).returns(T::Array[T.untyped]) } + def visit_constant_target_node(arg0); end + + sig { params(arg0: ConstantWriteNode).returns(T::Array[T.untyped]) } + def visit_constant_write_node(arg0); end + + sig { params(arg0: DefNode).returns(T::Array[T.untyped]) } + def visit_def_node(arg0); end + + sig { params(arg0: DefinedNode).returns(T::Array[T.untyped]) } + def visit_defined_node(arg0); end + + sig { params(arg0: ElseNode).returns(T::Array[T.untyped]) } + def visit_else_node(arg0); end + + sig { params(arg0: EmbeddedStatementsNode).returns(T::Array[T.untyped]) } + def visit_embedded_statements_node(arg0); end + + sig { params(arg0: EmbeddedVariableNode).returns(T::Array[T.untyped]) } + def visit_embedded_variable_node(arg0); end + + sig { params(arg0: EnsureNode).returns(T::Array[T.untyped]) } + def visit_ensure_node(arg0); end + + sig { params(arg0: FalseNode).returns(T::Array[T.untyped]) } + def visit_false_node(arg0); end + + sig { params(arg0: FindPatternNode).returns(T::Array[T.untyped]) } + def visit_find_pattern_node(arg0); end + + sig { params(arg0: FlipFlopNode).returns(T::Array[T.untyped]) } + def visit_flip_flop_node(arg0); end + + sig { params(arg0: FloatNode).returns(T::Array[T.untyped]) } + def visit_float_node(arg0); end + + sig { params(arg0: ForNode).returns(T::Array[T.untyped]) } + def visit_for_node(arg0); end + + sig { params(arg0: ForwardingArgumentsNode).returns(T::Array[T.untyped]) } + def visit_forwarding_arguments_node(arg0); end + + sig { params(arg0: ForwardingParameterNode).returns(T::Array[T.untyped]) } + def visit_forwarding_parameter_node(arg0); end + + sig { params(arg0: ForwardingSuperNode).returns(T::Array[T.untyped]) } + def visit_forwarding_super_node(arg0); end + + sig { params(arg0: GlobalVariableAndWriteNode).returns(T::Array[T.untyped]) } + def visit_global_variable_and_write_node(arg0); end + + sig { params(arg0: GlobalVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_global_variable_operator_write_node(arg0); end + + sig { params(arg0: GlobalVariableOrWriteNode).returns(T::Array[T.untyped]) } + def visit_global_variable_or_write_node(arg0); end + + sig { params(arg0: GlobalVariableReadNode).returns(T::Array[T.untyped]) } + def visit_global_variable_read_node(arg0); end + + sig { params(arg0: GlobalVariableTargetNode).returns(T::Array[T.untyped]) } + def visit_global_variable_target_node(arg0); end + + sig { params(arg0: GlobalVariableWriteNode).returns(T::Array[T.untyped]) } + def visit_global_variable_write_node(arg0); end + + sig { params(arg0: HashNode).returns(T::Array[T.untyped]) } + def visit_hash_node(arg0); end + + sig { params(arg0: HashPatternNode).returns(T::Array[T.untyped]) } + def visit_hash_pattern_node(arg0); end + + sig { params(arg0: IfNode).returns(T::Array[T.untyped]) } + def visit_if_node(arg0); end + + sig { params(arg0: ImaginaryNode).returns(T::Array[T.untyped]) } + def visit_imaginary_node(arg0); end + + sig { params(arg0: ImplicitNode).returns(T::Array[T.untyped]) } + def visit_implicit_node(arg0); end + + sig { params(arg0: ImplicitRestNode).returns(T::Array[T.untyped]) } + def visit_implicit_rest_node(arg0); end + + sig { params(arg0: InNode).returns(T::Array[T.untyped]) } + def visit_in_node(arg0); end + + sig { params(arg0: IndexAndWriteNode).returns(T::Array[T.untyped]) } + def visit_index_and_write_node(arg0); end + + sig { params(arg0: IndexOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_index_operator_write_node(arg0); end + + sig { params(arg0: IndexOrWriteNode).returns(T::Array[T.untyped]) } + def visit_index_or_write_node(arg0); end + + sig { params(arg0: IndexTargetNode).returns(T::Array[T.untyped]) } + def visit_index_target_node(arg0); end + + sig { params(arg0: InstanceVariableAndWriteNode).returns(T::Array[T.untyped]) } + def visit_instance_variable_and_write_node(arg0); end + + sig { params(arg0: InstanceVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_instance_variable_operator_write_node(arg0); end + + sig { params(arg0: InstanceVariableOrWriteNode).returns(T::Array[T.untyped]) } + def visit_instance_variable_or_write_node(arg0); end + + sig { params(arg0: InstanceVariableReadNode).returns(T::Array[T.untyped]) } + def visit_instance_variable_read_node(arg0); end + + sig { params(arg0: InstanceVariableTargetNode).returns(T::Array[T.untyped]) } + def visit_instance_variable_target_node(arg0); end + + sig { params(arg0: InstanceVariableWriteNode).returns(T::Array[T.untyped]) } + def visit_instance_variable_write_node(arg0); end + + sig { params(arg0: IntegerNode).returns(T::Array[T.untyped]) } + def visit_integer_node(arg0); end + + sig { params(arg0: InterpolatedMatchLastLineNode).returns(T::Array[T.untyped]) } + def visit_interpolated_match_last_line_node(arg0); end + + sig { params(arg0: InterpolatedRegularExpressionNode).returns(T::Array[T.untyped]) } + def visit_interpolated_regular_expression_node(arg0); end + + sig { params(arg0: InterpolatedStringNode).returns(T::Array[T.untyped]) } + def visit_interpolated_string_node(arg0); end + + sig { params(arg0: InterpolatedSymbolNode).returns(T::Array[T.untyped]) } + def visit_interpolated_symbol_node(arg0); end + + sig { params(arg0: InterpolatedXStringNode).returns(T::Array[T.untyped]) } + def visit_interpolated_x_string_node(arg0); end + + sig { params(arg0: ItLocalVariableReadNode).returns(T::Array[T.untyped]) } + def visit_it_local_variable_read_node(arg0); end + + sig { params(arg0: ItParametersNode).returns(T::Array[T.untyped]) } + def visit_it_parameters_node(arg0); end + + sig { params(arg0: KeywordHashNode).returns(T::Array[T.untyped]) } + def visit_keyword_hash_node(arg0); end + + sig { params(arg0: KeywordRestParameterNode).returns(T::Array[T.untyped]) } + def visit_keyword_rest_parameter_node(arg0); end + + sig { params(arg0: LambdaNode).returns(T::Array[T.untyped]) } + def visit_lambda_node(arg0); end + + sig { params(arg0: LocalVariableAndWriteNode).returns(T::Array[T.untyped]) } + def visit_local_variable_and_write_node(arg0); end + + sig { params(arg0: LocalVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + def visit_local_variable_operator_write_node(arg0); end + + sig { params(arg0: LocalVariableOrWriteNode).returns(T::Array[T.untyped]) } + def visit_local_variable_or_write_node(arg0); end + + sig { params(arg0: LocalVariableReadNode).returns(T::Array[T.untyped]) } + def visit_local_variable_read_node(arg0); end + + sig { params(arg0: LocalVariableTargetNode).returns(T::Array[T.untyped]) } + def visit_local_variable_target_node(arg0); end + + sig { params(arg0: LocalVariableWriteNode).returns(T::Array[T.untyped]) } + def visit_local_variable_write_node(arg0); end + + sig { params(arg0: MatchLastLineNode).returns(T::Array[T.untyped]) } + def visit_match_last_line_node(arg0); end + + sig { params(arg0: MatchPredicateNode).returns(T::Array[T.untyped]) } + def visit_match_predicate_node(arg0); end + + sig { params(arg0: MatchRequiredNode).returns(T::Array[T.untyped]) } + def visit_match_required_node(arg0); end + + sig { params(arg0: MatchWriteNode).returns(T::Array[T.untyped]) } + def visit_match_write_node(arg0); end + + sig { params(arg0: MissingNode).returns(T::Array[T.untyped]) } + def visit_missing_node(arg0); end + + sig { params(arg0: ModuleNode).returns(T::Array[T.untyped]) } + def visit_module_node(arg0); end + + sig { params(arg0: MultiTargetNode).returns(T::Array[T.untyped]) } + def visit_multi_target_node(arg0); end + + sig { params(arg0: MultiWriteNode).returns(T::Array[T.untyped]) } + def visit_multi_write_node(arg0); end + + sig { params(arg0: NextNode).returns(T::Array[T.untyped]) } + def visit_next_node(arg0); end + + sig { params(arg0: NilNode).returns(T::Array[T.untyped]) } + def visit_nil_node(arg0); end + + sig { params(arg0: NoBlockParameterNode).returns(T::Array[T.untyped]) } + def visit_no_block_parameter_node(arg0); end + + sig { params(arg0: NoKeywordsParameterNode).returns(T::Array[T.untyped]) } + def visit_no_keywords_parameter_node(arg0); end + + sig { params(arg0: NumberedParametersNode).returns(T::Array[T.untyped]) } + def visit_numbered_parameters_node(arg0); end + + sig { params(arg0: NumberedReferenceReadNode).returns(T::Array[T.untyped]) } + def visit_numbered_reference_read_node(arg0); end + + sig { params(arg0: OptionalKeywordParameterNode).returns(T::Array[T.untyped]) } + def visit_optional_keyword_parameter_node(arg0); end + + sig { params(arg0: OptionalParameterNode).returns(T::Array[T.untyped]) } + def visit_optional_parameter_node(arg0); end + + sig { params(arg0: OrNode).returns(T::Array[T.untyped]) } + def visit_or_node(arg0); end + + sig { params(arg0: ParametersNode).returns(T::Array[T.untyped]) } + def visit_parameters_node(arg0); end + + sig { params(arg0: ParenthesesNode).returns(T::Array[T.untyped]) } + def visit_parentheses_node(arg0); end + + sig { params(arg0: PinnedExpressionNode).returns(T::Array[T.untyped]) } + def visit_pinned_expression_node(arg0); end + + sig { params(arg0: PinnedVariableNode).returns(T::Array[T.untyped]) } + def visit_pinned_variable_node(arg0); end + + sig { params(arg0: PostExecutionNode).returns(T::Array[T.untyped]) } + def visit_post_execution_node(arg0); end + + sig { params(arg0: PreExecutionNode).returns(T::Array[T.untyped]) } + def visit_pre_execution_node(arg0); end + + sig { params(arg0: ProgramNode).returns(T::Array[T.untyped]) } + def visit_program_node(arg0); end + + sig { params(arg0: RangeNode).returns(T::Array[T.untyped]) } + def visit_range_node(arg0); end + + sig { params(arg0: RationalNode).returns(T::Array[T.untyped]) } + def visit_rational_node(arg0); end + + sig { params(arg0: RedoNode).returns(T::Array[T.untyped]) } + def visit_redo_node(arg0); end + + sig { params(arg0: RegularExpressionNode).returns(T::Array[T.untyped]) } + def visit_regular_expression_node(arg0); end + + sig { params(arg0: RequiredKeywordParameterNode).returns(T::Array[T.untyped]) } + def visit_required_keyword_parameter_node(arg0); end + + sig { params(arg0: RequiredParameterNode).returns(T::Array[T.untyped]) } + def visit_required_parameter_node(arg0); end + + sig { params(arg0: RescueModifierNode).returns(T::Array[T.untyped]) } + def visit_rescue_modifier_node(arg0); end + + sig { params(arg0: RescueNode).returns(T::Array[T.untyped]) } + def visit_rescue_node(arg0); end + + sig { params(arg0: RestParameterNode).returns(T::Array[T.untyped]) } + def visit_rest_parameter_node(arg0); end + + sig { params(arg0: RetryNode).returns(T::Array[T.untyped]) } + def visit_retry_node(arg0); end + + sig { params(arg0: ReturnNode).returns(T::Array[T.untyped]) } + def visit_return_node(arg0); end + + sig { params(arg0: SelfNode).returns(T::Array[T.untyped]) } + def visit_self_node(arg0); end + + sig { params(arg0: ShareableConstantNode).returns(T::Array[T.untyped]) } + def visit_shareable_constant_node(arg0); end + + sig { params(arg0: SingletonClassNode).returns(T::Array[T.untyped]) } + def visit_singleton_class_node(arg0); end + + sig { params(arg0: SourceEncodingNode).returns(T::Array[T.untyped]) } + def visit_source_encoding_node(arg0); end + + sig { params(arg0: SourceFileNode).returns(T::Array[T.untyped]) } + def visit_source_file_node(arg0); end + + sig { params(arg0: SourceLineNode).returns(T::Array[T.untyped]) } + def visit_source_line_node(arg0); end + + sig { params(arg0: SplatNode).returns(T::Array[T.untyped]) } + def visit_splat_node(arg0); end + + sig { params(arg0: StatementsNode).returns(T::Array[T.untyped]) } + def visit_statements_node(arg0); end + + sig { params(arg0: StringNode).returns(T::Array[T.untyped]) } + def visit_string_node(arg0); end + + sig { params(arg0: SuperNode).returns(T::Array[T.untyped]) } + def visit_super_node(arg0); end + + sig { params(arg0: SymbolNode).returns(T::Array[T.untyped]) } + def visit_symbol_node(arg0); end + + sig { params(arg0: TrueNode).returns(T::Array[T.untyped]) } + def visit_true_node(arg0); end + + sig { params(arg0: UndefNode).returns(T::Array[T.untyped]) } + def visit_undef_node(arg0); end + + sig { params(arg0: UnlessNode).returns(T::Array[T.untyped]) } + def visit_unless_node(arg0); end + + sig { params(arg0: UntilNode).returns(T::Array[T.untyped]) } + def visit_until_node(arg0); end + + sig { params(arg0: WhenNode).returns(T::Array[T.untyped]) } + def visit_when_node(arg0); end + + sig { params(arg0: WhileNode).returns(T::Array[T.untyped]) } + def visit_while_node(arg0); end + + sig { params(arg0: XStringNode).returns(T::Array[T.untyped]) } + def visit_x_string_node(arg0); end + + sig { params(arg0: YieldNode).returns(T::Array[T.untyped]) } + def visit_yield_node(arg0); end + end +end diff --git a/rbi/generated/prism/desugar_compiler.rbi b/rbi/generated/prism/desugar_compiler.rbi new file mode 100644 index 0000000000..3e7c745cc9 --- /dev/null +++ b/rbi/generated/prism/desugar_compiler.rbi @@ -0,0 +1,306 @@ +# typed: true + +module Prism + class DesugarAndWriteNode + include DSL + + sig { returns(T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, T.untyped]) } + attr_reader :arguments + + sig { params(node: T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x &&= y` to `x && x = y` + sig { returns(Node) } + def compile; end + end + + class DesugarOrWriteDefinedNode + include DSL + + sig { returns(T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, T.untyped]) } + attr_reader :arguments + + sig { params(node: T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x ||= y` to `defined?(x) ? x : x = y` + sig { returns(Node) } + def compile; end + end + + class DesugarOperatorWriteNode + include DSL + + sig { returns(T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, T.untyped]) } + attr_reader :arguments + + sig { params(node: T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x += y` to `x = x + y` + sig { returns(Node) } + def compile; end + end + + class DesugarOrWriteNode + include DSL + + sig { returns(T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode)) } + attr_reader :node + + sig { returns(Source) } + attr_reader :default_source + + sig { returns(Symbol) } + attr_reader :read_class + + sig { returns(Symbol) } + attr_reader :write_class + + sig { returns(T::Hash[Symbol, T.untyped]) } + attr_reader :arguments + + sig { params(node: T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + def initialize(node, default_source, read_class, write_class, **arguments); end + + # Desugar `x ||= y` to `x || x = y` + sig { returns(Node) } + def compile; end + end + + class ClassVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class ClassVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class ClassVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class ConstantAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class ConstantOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class ConstantOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class GlobalVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class GlobalVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class GlobalVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class InstanceVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class InstanceVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class InstanceVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + class LocalVariableAndWriteNode + sig { returns(Node) } + def desugar; end + end + + class LocalVariableOrWriteNode + sig { returns(Node) } + def desugar; end + end + + class LocalVariableOperatorWriteNode + sig { returns(Node) } + def desugar; end + end + + # DesugarCompiler is a compiler that desugars Ruby code into a more primitive + # form. This is useful for consumers that want to deal with fewer node types. + class DesugarCompiler < MutationCompiler + # `@@foo &&= bar` + # + # becomes + # + # `@@foo && @@foo = bar` + sig { params(node: ClassVariableAndWriteNode).returns(Node) } + def visit_class_variable_and_write_node(node); end + + # `@@foo ||= bar` + # + # becomes + # + # `defined?(@@foo) ? @@foo : @@foo = bar` + sig { params(node: ClassVariableOrWriteNode).returns(Node) } + def visit_class_variable_or_write_node(node); end + + # `@@foo += bar` + # + # becomes + # + # `@@foo = @@foo + bar` + sig { params(node: ClassVariableOperatorWriteNode).returns(Node) } + def visit_class_variable_operator_write_node(node); end + + # `Foo &&= bar` + # + # becomes + # + # `Foo && Foo = bar` + sig { params(node: ConstantAndWriteNode).returns(Node) } + def visit_constant_and_write_node(node); end + + # `Foo ||= bar` + # + # becomes + # + # `defined?(Foo) ? Foo : Foo = bar` + sig { params(node: ConstantOrWriteNode).returns(Node) } + def visit_constant_or_write_node(node); end + + # `Foo += bar` + # + # becomes + # + # `Foo = Foo + bar` + sig { params(node: ConstantOperatorWriteNode).returns(Node) } + def visit_constant_operator_write_node(node); end + + # `$foo &&= bar` + # + # becomes + # + # `$foo && $foo = bar` + sig { params(node: GlobalVariableAndWriteNode).returns(Node) } + def visit_global_variable_and_write_node(node); end + + # `$foo ||= bar` + # + # becomes + # + # `defined?($foo) ? $foo : $foo = bar` + sig { params(node: GlobalVariableOrWriteNode).returns(Node) } + def visit_global_variable_or_write_node(node); end + + # `$foo += bar` + # + # becomes + # + # `$foo = $foo + bar` + sig { params(node: GlobalVariableOperatorWriteNode).returns(Node) } + def visit_global_variable_operator_write_node(node); end + + # `@foo &&= bar` + # + # becomes + # + # `@foo && @foo = bar` + sig { params(node: InstanceVariableAndWriteNode).returns(Node) } + def visit_instance_variable_and_write_node(node); end + + # `@foo ||= bar` + # + # becomes + # + # `@foo || @foo = bar` + sig { params(node: InstanceVariableOrWriteNode).returns(Node) } + def visit_instance_variable_or_write_node(node); end + + # `@foo += bar` + # + # becomes + # + # `@foo = @foo + bar` + sig { params(node: InstanceVariableOperatorWriteNode).returns(Node) } + def visit_instance_variable_operator_write_node(node); end + + # `foo &&= bar` + # + # becomes + # + # `foo && foo = bar` + sig { params(node: LocalVariableAndWriteNode).returns(Node) } + def visit_local_variable_and_write_node(node); end + + # `foo ||= bar` + # + # becomes + # + # `foo || foo = bar` + sig { params(node: LocalVariableOrWriteNode).returns(Node) } + def visit_local_variable_or_write_node(node); end + + # `foo += bar` + # + # becomes + # + # `foo = foo + bar` + sig { params(node: LocalVariableOperatorWriteNode).returns(Node) } + def visit_local_variable_operator_write_node(node); end + end +end diff --git a/rbi/generated/prism/dispatcher.rbi b/rbi/generated/prism/dispatcher.rbi new file mode 100644 index 0000000000..728ab5942e --- /dev/null +++ b/rbi/generated/prism/dispatcher.rbi @@ -0,0 +1,1134 @@ +# typed: true + +module Prism + # The dispatcher class fires events for nodes that are found while walking an + # AST to all registered listeners. It's useful for performing different types + # of analysis on the AST while only having to walk the tree once. + # + # To use the dispatcher, you would first instantiate it and register listeners + # for the events you're interested in: + # + # class OctalListener + # def on_integer_node_enter(node) + # if node.octal? && !node.slice.start_with?("0o") + # warn("Octal integers should be written with the 0o prefix") + # end + # end + # end + # + # listener = OctalListener.new + # dispatcher = Prism::Dispatcher.new + # dispatcher.register(listener, :on_integer_node_enter) + # + # Then, you can walk any number of trees and dispatch events to the listeners: + # + # result = Prism.parse("001 + 002 + 003") + # dispatcher.dispatch(result.value) + # + # Optionally, you can also use `#dispatch_once` to dispatch enter and leave + # events for a single node without recursing further down the tree. This can + # be useful in circumstances where you want to reuse the listeners you already + # have registers but want to stop walking the tree at a certain point. + # + # integer = result.value.statements.body.first.receiver.receiver + # dispatcher.dispatch_once(integer) + class Dispatcher < Visitor + # A hash mapping event names to arrays of listeners that should be notified + # when that event is fired. + sig { returns(T::Hash[Symbol, T::Array[T.untyped]]) } + attr_reader :listeners + + # Initialize a new dispatcher. + sig { void } + def initialize; end + + # Register a listener for one or more events. + sig { params(arg0: T.untyped, args: Symbol).void } + def register(arg0, *args); end + + # Register all public methods of a listener that match the pattern + # `on__(enter|leave)`. + sig { params(arg0: T.untyped).void } + def register_public_methods(arg0); end + + # Register a listener for the given events. + sig { params(arg0: T.untyped, arg1: T::Array[Symbol]).void } + def register_events(arg0, arg1); end + + # Dispatches a single event for `node` to all registered listeners. + sig { params(node: Node).void } + def dispatch_once(node); end + + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + sig { params(node: AndNode).void } + def visit_and_node(node); end + + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + sig { params(node: CallNode).void } + def visit_call_node(node); end + + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + sig { params(node: DefNode).void } + def visit_def_node(node); end + + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + sig { params(node: ForNode).void } + def visit_for_node(node); end + + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + sig { params(node: IfNode).void } + def visit_if_node(node); end + + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + sig { params(node: InNode).void } + def visit_in_node(node); end + + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + sig { params(node: NextNode).void } + def visit_next_node(node); end + + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + sig { params(node: OrNode).void } + def visit_or_node(node); end + + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + sig { params(node: StringNode).void } + def visit_string_node(node); end + + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + + class DispatchOnce < Visitor + sig { returns(T::Hash[Symbol, T::Array[T.untyped]]) } + attr_reader :listeners + + sig { params(listeners: T::Hash[Symbol, T::Array[T.untyped]]).void } + def initialize(listeners); end + + # Dispatch enter and leave events for AliasGlobalVariableNode nodes. + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + # Dispatch enter and leave events for AliasMethodNode nodes. + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + # Dispatch enter and leave events for AlternationPatternNode nodes. + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + # Dispatch enter and leave events for AndNode nodes. + sig { params(node: AndNode).void } + def visit_and_node(node); end + + # Dispatch enter and leave events for ArgumentsNode nodes. + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + # Dispatch enter and leave events for ArrayNode nodes. + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + # Dispatch enter and leave events for ArrayPatternNode nodes. + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + # Dispatch enter and leave events for AssocNode nodes. + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + # Dispatch enter and leave events for AssocSplatNode nodes. + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + # Dispatch enter and leave events for BackReferenceReadNode nodes. + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + # Dispatch enter and leave events for BeginNode nodes. + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + # Dispatch enter and leave events for BlockArgumentNode nodes. + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + # Dispatch enter and leave events for BlockLocalVariableNode nodes. + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + # Dispatch enter and leave events for BlockNode nodes. + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + # Dispatch enter and leave events for BlockParameterNode nodes. + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + # Dispatch enter and leave events for BlockParametersNode nodes. + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + # Dispatch enter and leave events for BreakNode nodes. + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + # Dispatch enter and leave events for CallAndWriteNode nodes. + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + # Dispatch enter and leave events for CallNode nodes. + sig { params(node: CallNode).void } + def visit_call_node(node); end + + # Dispatch enter and leave events for CallOperatorWriteNode nodes. + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + # Dispatch enter and leave events for CallOrWriteNode nodes. + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + # Dispatch enter and leave events for CallTargetNode nodes. + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + # Dispatch enter and leave events for CapturePatternNode nodes. + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + # Dispatch enter and leave events for CaseMatchNode nodes. + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + # Dispatch enter and leave events for CaseNode nodes. + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + # Dispatch enter and leave events for ClassNode nodes. + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + # Dispatch enter and leave events for ClassVariableAndWriteNode nodes. + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + # Dispatch enter and leave events for ClassVariableOperatorWriteNode nodes. + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + # Dispatch enter and leave events for ClassVariableOrWriteNode nodes. + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + # Dispatch enter and leave events for ClassVariableReadNode nodes. + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + # Dispatch enter and leave events for ClassVariableTargetNode nodes. + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + # Dispatch enter and leave events for ClassVariableWriteNode nodes. + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + # Dispatch enter and leave events for ConstantAndWriteNode nodes. + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + # Dispatch enter and leave events for ConstantOperatorWriteNode nodes. + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + # Dispatch enter and leave events for ConstantOrWriteNode nodes. + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + # Dispatch enter and leave events for ConstantPathAndWriteNode nodes. + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + # Dispatch enter and leave events for ConstantPathNode nodes. + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + # Dispatch enter and leave events for ConstantPathOperatorWriteNode nodes. + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + # Dispatch enter and leave events for ConstantPathOrWriteNode nodes. + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + # Dispatch enter and leave events for ConstantPathTargetNode nodes. + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + # Dispatch enter and leave events for ConstantPathWriteNode nodes. + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + # Dispatch enter and leave events for ConstantReadNode nodes. + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + # Dispatch enter and leave events for ConstantTargetNode nodes. + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + # Dispatch enter and leave events for ConstantWriteNode nodes. + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + # Dispatch enter and leave events for DefNode nodes. + sig { params(node: DefNode).void } + def visit_def_node(node); end + + # Dispatch enter and leave events for DefinedNode nodes. + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + # Dispatch enter and leave events for ElseNode nodes. + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + # Dispatch enter and leave events for EmbeddedStatementsNode nodes. + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + # Dispatch enter and leave events for EmbeddedVariableNode nodes. + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + # Dispatch enter and leave events for EnsureNode nodes. + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + # Dispatch enter and leave events for FalseNode nodes. + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + # Dispatch enter and leave events for FindPatternNode nodes. + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + # Dispatch enter and leave events for FlipFlopNode nodes. + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + # Dispatch enter and leave events for FloatNode nodes. + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + # Dispatch enter and leave events for ForNode nodes. + sig { params(node: ForNode).void } + def visit_for_node(node); end + + # Dispatch enter and leave events for ForwardingArgumentsNode nodes. + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + # Dispatch enter and leave events for ForwardingParameterNode nodes. + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + # Dispatch enter and leave events for ForwardingSuperNode nodes. + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + # Dispatch enter and leave events for GlobalVariableAndWriteNode nodes. + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + # Dispatch enter and leave events for GlobalVariableOperatorWriteNode nodes. + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + # Dispatch enter and leave events for GlobalVariableOrWriteNode nodes. + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + # Dispatch enter and leave events for GlobalVariableReadNode nodes. + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + # Dispatch enter and leave events for GlobalVariableTargetNode nodes. + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + # Dispatch enter and leave events for GlobalVariableWriteNode nodes. + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + # Dispatch enter and leave events for HashNode nodes. + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + # Dispatch enter and leave events for HashPatternNode nodes. + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + # Dispatch enter and leave events for IfNode nodes. + sig { params(node: IfNode).void } + def visit_if_node(node); end + + # Dispatch enter and leave events for ImaginaryNode nodes. + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + # Dispatch enter and leave events for ImplicitNode nodes. + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + # Dispatch enter and leave events for ImplicitRestNode nodes. + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + # Dispatch enter and leave events for InNode nodes. + sig { params(node: InNode).void } + def visit_in_node(node); end + + # Dispatch enter and leave events for IndexAndWriteNode nodes. + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + # Dispatch enter and leave events for IndexOperatorWriteNode nodes. + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + # Dispatch enter and leave events for IndexOrWriteNode nodes. + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + # Dispatch enter and leave events for IndexTargetNode nodes. + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + # Dispatch enter and leave events for InstanceVariableAndWriteNode nodes. + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + # Dispatch enter and leave events for InstanceVariableOperatorWriteNode nodes. + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + # Dispatch enter and leave events for InstanceVariableOrWriteNode nodes. + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + # Dispatch enter and leave events for InstanceVariableReadNode nodes. + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + # Dispatch enter and leave events for InstanceVariableTargetNode nodes. + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + # Dispatch enter and leave events for InstanceVariableWriteNode nodes. + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + # Dispatch enter and leave events for IntegerNode nodes. + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + # Dispatch enter and leave events for InterpolatedMatchLastLineNode nodes. + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + # Dispatch enter and leave events for InterpolatedRegularExpressionNode nodes. + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + # Dispatch enter and leave events for InterpolatedStringNode nodes. + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + # Dispatch enter and leave events for InterpolatedSymbolNode nodes. + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + # Dispatch enter and leave events for InterpolatedXStringNode nodes. + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + # Dispatch enter and leave events for ItLocalVariableReadNode nodes. + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + # Dispatch enter and leave events for ItParametersNode nodes. + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + # Dispatch enter and leave events for KeywordHashNode nodes. + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + # Dispatch enter and leave events for KeywordRestParameterNode nodes. + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + # Dispatch enter and leave events for LambdaNode nodes. + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + # Dispatch enter and leave events for LocalVariableAndWriteNode nodes. + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + # Dispatch enter and leave events for LocalVariableOperatorWriteNode nodes. + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + # Dispatch enter and leave events for LocalVariableOrWriteNode nodes. + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + # Dispatch enter and leave events for LocalVariableReadNode nodes. + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + # Dispatch enter and leave events for LocalVariableTargetNode nodes. + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + # Dispatch enter and leave events for LocalVariableWriteNode nodes. + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + # Dispatch enter and leave events for MatchLastLineNode nodes. + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + # Dispatch enter and leave events for MatchPredicateNode nodes. + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + # Dispatch enter and leave events for MatchRequiredNode nodes. + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + # Dispatch enter and leave events for MatchWriteNode nodes. + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + # Dispatch enter and leave events for MissingNode nodes. + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + # Dispatch enter and leave events for ModuleNode nodes. + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + # Dispatch enter and leave events for MultiTargetNode nodes. + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + # Dispatch enter and leave events for MultiWriteNode nodes. + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + # Dispatch enter and leave events for NextNode nodes. + sig { params(node: NextNode).void } + def visit_next_node(node); end + + # Dispatch enter and leave events for NilNode nodes. + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + # Dispatch enter and leave events for NoBlockParameterNode nodes. + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + # Dispatch enter and leave events for NoKeywordsParameterNode nodes. + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + # Dispatch enter and leave events for NumberedParametersNode nodes. + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + # Dispatch enter and leave events for NumberedReferenceReadNode nodes. + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + # Dispatch enter and leave events for OptionalKeywordParameterNode nodes. + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + # Dispatch enter and leave events for OptionalParameterNode nodes. + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + # Dispatch enter and leave events for OrNode nodes. + sig { params(node: OrNode).void } + def visit_or_node(node); end + + # Dispatch enter and leave events for ParametersNode nodes. + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + # Dispatch enter and leave events for ParenthesesNode nodes. + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + # Dispatch enter and leave events for PinnedExpressionNode nodes. + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + # Dispatch enter and leave events for PinnedVariableNode nodes. + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + # Dispatch enter and leave events for PostExecutionNode nodes. + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + # Dispatch enter and leave events for PreExecutionNode nodes. + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + # Dispatch enter and leave events for ProgramNode nodes. + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + # Dispatch enter and leave events for RangeNode nodes. + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + # Dispatch enter and leave events for RationalNode nodes. + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + # Dispatch enter and leave events for RedoNode nodes. + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + # Dispatch enter and leave events for RegularExpressionNode nodes. + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + # Dispatch enter and leave events for RequiredKeywordParameterNode nodes. + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + # Dispatch enter and leave events for RequiredParameterNode nodes. + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + # Dispatch enter and leave events for RescueModifierNode nodes. + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + # Dispatch enter and leave events for RescueNode nodes. + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + # Dispatch enter and leave events for RestParameterNode nodes. + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + # Dispatch enter and leave events for RetryNode nodes. + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + # Dispatch enter and leave events for ReturnNode nodes. + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + # Dispatch enter and leave events for SelfNode nodes. + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + # Dispatch enter and leave events for ShareableConstantNode nodes. + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + # Dispatch enter and leave events for SingletonClassNode nodes. + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + # Dispatch enter and leave events for SourceEncodingNode nodes. + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + # Dispatch enter and leave events for SourceFileNode nodes. + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + # Dispatch enter and leave events for SourceLineNode nodes. + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + # Dispatch enter and leave events for SplatNode nodes. + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + # Dispatch enter and leave events for StatementsNode nodes. + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + # Dispatch enter and leave events for StringNode nodes. + sig { params(node: StringNode).void } + def visit_string_node(node); end + + # Dispatch enter and leave events for SuperNode nodes. + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + # Dispatch enter and leave events for SymbolNode nodes. + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + # Dispatch enter and leave events for TrueNode nodes. + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + # Dispatch enter and leave events for UndefNode nodes. + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + # Dispatch enter and leave events for UnlessNode nodes. + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + # Dispatch enter and leave events for UntilNode nodes. + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + # Dispatch enter and leave events for WhenNode nodes. + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + # Dispatch enter and leave events for WhileNode nodes. + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + # Dispatch enter and leave events for XStringNode nodes. + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + # Dispatch enter and leave events for YieldNode nodes. + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + end + end +end diff --git a/rbi/generated/prism/dot_visitor.rbi b/rbi/generated/prism/dot_visitor.rbi new file mode 100644 index 0000000000..835dd112b6 --- /dev/null +++ b/rbi/generated/prism/dot_visitor.rbi @@ -0,0 +1,618 @@ +# typed: true + +module Prism + # This visitor provides the ability to call Node#to_dot, which converts a + # subtree into a graphviz dot graph. + class DotVisitor < Visitor + class Field + sig { returns(String) } + attr_reader :name + + sig { returns(T.nilable(String)) } + attr_reader :value + + sig { returns(T::Boolean) } + attr_reader :port + + sig { params(name: String, value: T.nilable(String), port: T::Boolean).void } + def initialize(name, value, port); end + + sig { returns(String) } + def to_dot; end + end + + class Table + sig { returns(String) } + attr_reader :name + + sig { returns(T::Array[Field]) } + attr_reader :fields + + sig { params(name: String).void } + def initialize(name); end + + sig { params(name: String, value: T.nilable(String), port: T::Boolean).void } + def field(name, value = T.unsafe(nil), port: T.unsafe(nil)); end + + sig { returns(String) } + def to_dot; end + end + + class Digraph + sig { returns(T::Array[String]) } + attr_reader :nodes + + sig { returns(T::Array[String]) } + attr_reader :waypoints + + sig { returns(T::Array[String]) } + attr_reader :edges + + sig { void } + def initialize; end + + sig { params(value: String).void } + def node(value); end + + sig { params(value: String).void } + def waypoint(value); end + + sig { params(value: String).void } + def edge(value); end + + sig { returns(String) } + def to_dot; end + end + + # The digraph that is being built. + sig { returns(Digraph) } + attr_reader :digraph + + # Initialize a new dot visitor. + sig { void } + def initialize; end + + # Convert this visitor into a graphviz dot graph string. + sig { returns(String) } + def to_dot; end + + sig { params(arg0: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(arg0); end + + sig { params(arg0: AliasMethodNode).void } + def visit_alias_method_node(arg0); end + + sig { params(arg0: AlternationPatternNode).void } + def visit_alternation_pattern_node(arg0); end + + sig { params(arg0: AndNode).void } + def visit_and_node(arg0); end + + sig { params(arg0: ArgumentsNode).void } + def visit_arguments_node(arg0); end + + sig { params(arg0: ArrayNode).void } + def visit_array_node(arg0); end + + sig { params(arg0: ArrayPatternNode).void } + def visit_array_pattern_node(arg0); end + + sig { params(arg0: AssocNode).void } + def visit_assoc_node(arg0); end + + sig { params(arg0: AssocSplatNode).void } + def visit_assoc_splat_node(arg0); end + + sig { params(arg0: BackReferenceReadNode).void } + def visit_back_reference_read_node(arg0); end + + sig { params(arg0: BeginNode).void } + def visit_begin_node(arg0); end + + sig { params(arg0: BlockArgumentNode).void } + def visit_block_argument_node(arg0); end + + sig { params(arg0: BlockLocalVariableNode).void } + def visit_block_local_variable_node(arg0); end + + sig { params(arg0: BlockNode).void } + def visit_block_node(arg0); end + + sig { params(arg0: BlockParameterNode).void } + def visit_block_parameter_node(arg0); end + + sig { params(arg0: BlockParametersNode).void } + def visit_block_parameters_node(arg0); end + + sig { params(arg0: BreakNode).void } + def visit_break_node(arg0); end + + sig { params(arg0: CallAndWriteNode).void } + def visit_call_and_write_node(arg0); end + + sig { params(arg0: CallNode).void } + def visit_call_node(arg0); end + + sig { params(arg0: CallOperatorWriteNode).void } + def visit_call_operator_write_node(arg0); end + + sig { params(arg0: CallOrWriteNode).void } + def visit_call_or_write_node(arg0); end + + sig { params(arg0: CallTargetNode).void } + def visit_call_target_node(arg0); end + + sig { params(arg0: CapturePatternNode).void } + def visit_capture_pattern_node(arg0); end + + sig { params(arg0: CaseMatchNode).void } + def visit_case_match_node(arg0); end + + sig { params(arg0: CaseNode).void } + def visit_case_node(arg0); end + + sig { params(arg0: ClassNode).void } + def visit_class_node(arg0); end + + sig { params(arg0: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(arg0); end + + sig { params(arg0: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(arg0); end + + sig { params(arg0: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(arg0); end + + sig { params(arg0: ClassVariableReadNode).void } + def visit_class_variable_read_node(arg0); end + + sig { params(arg0: ClassVariableTargetNode).void } + def visit_class_variable_target_node(arg0); end + + sig { params(arg0: ClassVariableWriteNode).void } + def visit_class_variable_write_node(arg0); end + + sig { params(arg0: ConstantAndWriteNode).void } + def visit_constant_and_write_node(arg0); end + + sig { params(arg0: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(arg0); end + + sig { params(arg0: ConstantOrWriteNode).void } + def visit_constant_or_write_node(arg0); end + + sig { params(arg0: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(arg0); end + + sig { params(arg0: ConstantPathNode).void } + def visit_constant_path_node(arg0); end + + sig { params(arg0: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(arg0); end + + sig { params(arg0: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(arg0); end + + sig { params(arg0: ConstantPathTargetNode).void } + def visit_constant_path_target_node(arg0); end + + sig { params(arg0: ConstantPathWriteNode).void } + def visit_constant_path_write_node(arg0); end + + sig { params(arg0: ConstantReadNode).void } + def visit_constant_read_node(arg0); end + + sig { params(arg0: ConstantTargetNode).void } + def visit_constant_target_node(arg0); end + + sig { params(arg0: ConstantWriteNode).void } + def visit_constant_write_node(arg0); end + + sig { params(arg0: DefNode).void } + def visit_def_node(arg0); end + + sig { params(arg0: DefinedNode).void } + def visit_defined_node(arg0); end + + sig { params(arg0: ElseNode).void } + def visit_else_node(arg0); end + + sig { params(arg0: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(arg0); end + + sig { params(arg0: EmbeddedVariableNode).void } + def visit_embedded_variable_node(arg0); end + + sig { params(arg0: EnsureNode).void } + def visit_ensure_node(arg0); end + + sig { params(arg0: FalseNode).void } + def visit_false_node(arg0); end + + sig { params(arg0: FindPatternNode).void } + def visit_find_pattern_node(arg0); end + + sig { params(arg0: FlipFlopNode).void } + def visit_flip_flop_node(arg0); end + + sig { params(arg0: FloatNode).void } + def visit_float_node(arg0); end + + sig { params(arg0: ForNode).void } + def visit_for_node(arg0); end + + sig { params(arg0: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(arg0); end + + sig { params(arg0: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(arg0); end + + sig { params(arg0: ForwardingSuperNode).void } + def visit_forwarding_super_node(arg0); end + + sig { params(arg0: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(arg0); end + + sig { params(arg0: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(arg0); end + + sig { params(arg0: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(arg0); end + + sig { params(arg0: GlobalVariableReadNode).void } + def visit_global_variable_read_node(arg0); end + + sig { params(arg0: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(arg0); end + + sig { params(arg0: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(arg0); end + + sig { params(arg0: HashNode).void } + def visit_hash_node(arg0); end + + sig { params(arg0: HashPatternNode).void } + def visit_hash_pattern_node(arg0); end + + sig { params(arg0: IfNode).void } + def visit_if_node(arg0); end + + sig { params(arg0: ImaginaryNode).void } + def visit_imaginary_node(arg0); end + + sig { params(arg0: ImplicitNode).void } + def visit_implicit_node(arg0); end + + sig { params(arg0: ImplicitRestNode).void } + def visit_implicit_rest_node(arg0); end + + sig { params(arg0: InNode).void } + def visit_in_node(arg0); end + + sig { params(arg0: IndexAndWriteNode).void } + def visit_index_and_write_node(arg0); end + + sig { params(arg0: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(arg0); end + + sig { params(arg0: IndexOrWriteNode).void } + def visit_index_or_write_node(arg0); end + + sig { params(arg0: IndexTargetNode).void } + def visit_index_target_node(arg0); end + + sig { params(arg0: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(arg0); end + + sig { params(arg0: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(arg0); end + + sig { params(arg0: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(arg0); end + + sig { params(arg0: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(arg0); end + + sig { params(arg0: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(arg0); end + + sig { params(arg0: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(arg0); end + + sig { params(arg0: IntegerNode).void } + def visit_integer_node(arg0); end + + sig { params(arg0: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(arg0); end + + sig { params(arg0: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(arg0); end + + sig { params(arg0: InterpolatedStringNode).void } + def visit_interpolated_string_node(arg0); end + + sig { params(arg0: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(arg0); end + + sig { params(arg0: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(arg0); end + + sig { params(arg0: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(arg0); end + + sig { params(arg0: ItParametersNode).void } + def visit_it_parameters_node(arg0); end + + sig { params(arg0: KeywordHashNode).void } + def visit_keyword_hash_node(arg0); end + + sig { params(arg0: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(arg0); end + + sig { params(arg0: LambdaNode).void } + def visit_lambda_node(arg0); end + + sig { params(arg0: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(arg0); end + + sig { params(arg0: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(arg0); end + + sig { params(arg0: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(arg0); end + + sig { params(arg0: LocalVariableReadNode).void } + def visit_local_variable_read_node(arg0); end + + sig { params(arg0: LocalVariableTargetNode).void } + def visit_local_variable_target_node(arg0); end + + sig { params(arg0: LocalVariableWriteNode).void } + def visit_local_variable_write_node(arg0); end + + sig { params(arg0: MatchLastLineNode).void } + def visit_match_last_line_node(arg0); end + + sig { params(arg0: MatchPredicateNode).void } + def visit_match_predicate_node(arg0); end + + sig { params(arg0: MatchRequiredNode).void } + def visit_match_required_node(arg0); end + + sig { params(arg0: MatchWriteNode).void } + def visit_match_write_node(arg0); end + + sig { params(arg0: MissingNode).void } + def visit_missing_node(arg0); end + + sig { params(arg0: ModuleNode).void } + def visit_module_node(arg0); end + + sig { params(arg0: MultiTargetNode).void } + def visit_multi_target_node(arg0); end + + sig { params(arg0: MultiWriteNode).void } + def visit_multi_write_node(arg0); end + + sig { params(arg0: NextNode).void } + def visit_next_node(arg0); end + + sig { params(arg0: NilNode).void } + def visit_nil_node(arg0); end + + sig { params(arg0: NoBlockParameterNode).void } + def visit_no_block_parameter_node(arg0); end + + sig { params(arg0: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(arg0); end + + sig { params(arg0: NumberedParametersNode).void } + def visit_numbered_parameters_node(arg0); end + + sig { params(arg0: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(arg0); end + + sig { params(arg0: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(arg0); end + + sig { params(arg0: OptionalParameterNode).void } + def visit_optional_parameter_node(arg0); end + + sig { params(arg0: OrNode).void } + def visit_or_node(arg0); end + + sig { params(arg0: ParametersNode).void } + def visit_parameters_node(arg0); end + + sig { params(arg0: ParenthesesNode).void } + def visit_parentheses_node(arg0); end + + sig { params(arg0: PinnedExpressionNode).void } + def visit_pinned_expression_node(arg0); end + + sig { params(arg0: PinnedVariableNode).void } + def visit_pinned_variable_node(arg0); end + + sig { params(arg0: PostExecutionNode).void } + def visit_post_execution_node(arg0); end + + sig { params(arg0: PreExecutionNode).void } + def visit_pre_execution_node(arg0); end + + sig { params(arg0: ProgramNode).void } + def visit_program_node(arg0); end + + sig { params(arg0: RangeNode).void } + def visit_range_node(arg0); end + + sig { params(arg0: RationalNode).void } + def visit_rational_node(arg0); end + + sig { params(arg0: RedoNode).void } + def visit_redo_node(arg0); end + + sig { params(arg0: RegularExpressionNode).void } + def visit_regular_expression_node(arg0); end + + sig { params(arg0: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(arg0); end + + sig { params(arg0: RequiredParameterNode).void } + def visit_required_parameter_node(arg0); end + + sig { params(arg0: RescueModifierNode).void } + def visit_rescue_modifier_node(arg0); end + + sig { params(arg0: RescueNode).void } + def visit_rescue_node(arg0); end + + sig { params(arg0: RestParameterNode).void } + def visit_rest_parameter_node(arg0); end + + sig { params(arg0: RetryNode).void } + def visit_retry_node(arg0); end + + sig { params(arg0: ReturnNode).void } + def visit_return_node(arg0); end + + sig { params(arg0: SelfNode).void } + def visit_self_node(arg0); end + + sig { params(arg0: ShareableConstantNode).void } + def visit_shareable_constant_node(arg0); end + + sig { params(arg0: SingletonClassNode).void } + def visit_singleton_class_node(arg0); end + + sig { params(arg0: SourceEncodingNode).void } + def visit_source_encoding_node(arg0); end + + sig { params(arg0: SourceFileNode).void } + def visit_source_file_node(arg0); end + + sig { params(arg0: SourceLineNode).void } + def visit_source_line_node(arg0); end + + sig { params(arg0: SplatNode).void } + def visit_splat_node(arg0); end + + sig { params(arg0: StatementsNode).void } + def visit_statements_node(arg0); end + + sig { params(arg0: StringNode).void } + def visit_string_node(arg0); end + + sig { params(arg0: SuperNode).void } + def visit_super_node(arg0); end + + sig { params(arg0: SymbolNode).void } + def visit_symbol_node(arg0); end + + sig { params(arg0: TrueNode).void } + def visit_true_node(arg0); end + + sig { params(arg0: UndefNode).void } + def visit_undef_node(arg0); end + + sig { params(arg0: UnlessNode).void } + def visit_unless_node(arg0); end + + sig { params(arg0: UntilNode).void } + def visit_until_node(arg0); end + + sig { params(arg0: WhenNode).void } + def visit_when_node(arg0); end + + sig { params(arg0: WhileNode).void } + def visit_while_node(arg0); end + + sig { params(arg0: XStringNode).void } + def visit_x_string_node(arg0); end + + sig { params(arg0: YieldNode).void } + def visit_yield_node(arg0); end + + # Generate a unique node ID for a node throughout the digraph. + sig { params(arg0: Node).returns(String) } + private def node_id(arg0); end + + # Inspect a location to display the start and end line and columns in bytes. + sig { params(arg0: Location).returns(String) } + private def location_inspect(arg0); end + + # Inspect a node that has arguments_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ArgumentsNode).returns(String) } + private def arguments_node_flags_inspect(node); end + + # Inspect a node that has array_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ArrayNode).returns(String) } + private def array_node_flags_inspect(node); end + + # Inspect a node that has call_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: T.any(CallAndWriteNode, CallNode, CallOperatorWriteNode, CallOrWriteNode, CallTargetNode, IndexAndWriteNode, IndexOperatorWriteNode, IndexOrWriteNode, IndexTargetNode)).returns(String) } + private def call_node_flags_inspect(node); end + + # Inspect a node that has encoding_flags flags to display the flags as a + # comma-separated list. + sig { params(node: XStringNode).returns(String) } + private def encoding_flags_inspect(node); end + + # Inspect a node that has integer_base_flags flags to display the flags as a + # comma-separated list. + sig { params(node: T.any(IntegerNode, RationalNode)).returns(String) } + private def integer_base_flags_inspect(node); end + + # Inspect a node that has interpolated_string_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: InterpolatedStringNode).returns(String) } + private def interpolated_string_node_flags_inspect(node); end + + # Inspect a node that has keyword_hash_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: KeywordHashNode).returns(String) } + private def keyword_hash_node_flags_inspect(node); end + + # Inspect a node that has loop_flags flags to display the flags as a + # comma-separated list. + sig { params(node: T.any(UntilNode, WhileNode)).returns(String) } + private def loop_flags_inspect(node); end + + # Inspect a node that has parameter_flags flags to display the flags as a + # comma-separated list. + sig { params(node: T.any(BlockLocalVariableNode, BlockParameterNode, KeywordRestParameterNode, OptionalKeywordParameterNode, OptionalParameterNode, RequiredKeywordParameterNode, RequiredParameterNode, RestParameterNode)).returns(String) } + private def parameter_flags_inspect(node); end + + # Inspect a node that has parentheses_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ParenthesesNode).returns(String) } + private def parentheses_node_flags_inspect(node); end + + # Inspect a node that has range_flags flags to display the flags as a + # comma-separated list. + sig { params(node: T.any(FlipFlopNode, RangeNode)).returns(String) } + private def range_flags_inspect(node); end + + # Inspect a node that has regular_expression_flags flags to display the flags as a + # comma-separated list. + sig { params(node: T.any(InterpolatedMatchLastLineNode, InterpolatedRegularExpressionNode, MatchLastLineNode, RegularExpressionNode)).returns(String) } + private def regular_expression_flags_inspect(node); end + + # Inspect a node that has shareable_constant_node_flags flags to display the flags as a + # comma-separated list. + sig { params(node: ShareableConstantNode).returns(String) } + private def shareable_constant_node_flags_inspect(node); end + + # Inspect a node that has string_flags flags to display the flags as a + # comma-separated list. + sig { params(node: T.any(SourceFileNode, StringNode)).returns(String) } + private def string_flags_inspect(node); end + + # Inspect a node that has symbol_flags flags to display the flags as a + # comma-separated list. + sig { params(node: SymbolNode).returns(String) } + private def symbol_flags_inspect(node); end + end +end diff --git a/rbi/generated/prism/dsl.rbi b/rbi/generated/prism/dsl.rbi new file mode 100644 index 0000000000..40eaccc727 --- /dev/null +++ b/rbi/generated/prism/dsl.rbi @@ -0,0 +1,747 @@ +# typed: true + +module Prism + # The DSL module provides a set of methods that can be used to create prism + # nodes in a more concise manner. For example, instead of writing: + # + # source = Prism::Source.for("[1]") + # + # Prism::ArrayNode.new( + # source, + # 0, + # Prism::Location.new(source, 0, 3), + # 0, + # [ + # Prism::IntegerNode.new( + # source, + # 0, + # Prism::Location.new(source, 1, 1), + # Prism::IntegerBaseFlags::DECIMAL, + # 1 + # ) + # ], + # Prism::Location.new(source, 0, 1), + # Prism::Location.new(source, 2, 1) + # ) + # + # you could instead write: + # + # class Builder + # include Prism::DSL + # + # attr_reader :default_source + # + # def initialize + # @default_source = source("[1]") + # end + # + # def build + # array_node( + # location: location(start_offset: 0, length: 3), + # elements: [ + # integer_node( + # location: location(start_offset: 1, length: 1), + # flags: integer_base_flag(:decimal), + # value: 1 + # ) + # ], + # opening_loc: location(start_offset: 0, length: 1), + # closing_loc: location(start_offset: 2, length: 1) + # ) + # end + # end + # + # This is mostly helpful in the context of generating trees programmatically. + module DSL + # Create a new Source object. + sig { params(string: String).returns(Source) } + def source(string); end + + # Create a new Location object. + sig { params(source: Source, start_offset: Integer, length: Integer).returns(Location) } + def location(source: T.unsafe(nil), start_offset: T.unsafe(nil), length: T.unsafe(nil)); end + + # Create a new AliasGlobalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } + def alias_global_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new AliasMethodNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(SymbolNode, InterpolatedSymbolNode), old_name: T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } + def alias_method_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new AlternationPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AlternationPatternNode) } + def alternation_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new AndNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AndNode) } + def and_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new ArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).returns(ArgumentsNode) } + def arguments_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil)); end + + # Create a new ArrayNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayNode) } + def array_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new ArrayPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayPatternNode) } + def array_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), requireds: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new AssocNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: T.nilable(Location)).returns(AssocNode) } + def assoc_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), key: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new AssocSplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } + def assoc_splat_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new BackReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BackReferenceReadNode) } + def back_reference_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new BeginNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), rescue_clause: T.nilable(RescueNode), else_clause: T.nilable(ElseNode), ensure_clause: T.nilable(EnsureNode), end_keyword_loc: T.nilable(Location)).returns(BeginNode) } + def begin_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), begin_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), rescue_clause: T.unsafe(nil), else_clause: T.unsafe(nil), ensure_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new BlockArgumentNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } + def block_argument_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new BlockLocalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BlockLocalVariableNode) } + def block_local_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new BlockNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } + def block_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new BlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } + def block_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new BlockParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(BlockParametersNode) } + def block_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parameters: T.unsafe(nil), locals: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new BreakNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } + def break_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new CallAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } + def call_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new CallNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), name: Symbol, message_loc: T.nilable(Location), opening_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), closing_loc: T.nilable(Location), equal_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } + def call_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new CallOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } + def call_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new CallOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } + def call_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new CallTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).returns(CallTargetNode) } + def call_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil)); end + + # Create a new CapturePatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).returns(CapturePatternNode) } + def capture_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new CaseMatchNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[InNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } + def case_match_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new CaseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[WhenNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } + def case_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new ClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: T.nilable(Location), superclass: T.nilable(Node), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } + def class_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), inheritance_operator_loc: T.unsafe(nil), superclass: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ClassVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableAndWriteNode) } + def class_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ClassVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ClassVariableOperatorWriteNode) } + def class_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new ClassVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableOrWriteNode) } + def class_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ClassVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableReadNode) } + def class_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ClassVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableTargetNode) } + def class_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ClassVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ClassVariableWriteNode) } + def class_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new ConstantAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantAndWriteNode) } + def constant_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantOperatorWriteNode) } + def constant_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new ConstantOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantOrWriteNode) } + def constant_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantPathAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathAndWriteNode) } + def constant_path_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantPathNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } + def constant_path_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + # Create a new ConstantPathOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantPathOperatorWriteNode) } + def constant_path_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new ConstantPathOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathOrWriteNode) } + def constant_path_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantPathTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } + def constant_path_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + # Create a new ConstantPathWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathWriteNode) } + def constant_path_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ConstantReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantReadNode) } + def constant_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ConstantTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantTargetNode) } + def constant_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new ConstantWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ConstantWriteNode) } + def constant_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new DefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: T.nilable(Node), parameters: T.nilable(ParametersNode), body: T.nilable(T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: T.nilable(Location), lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), equal_loc: T.nilable(Location), end_keyword_loc: T.nilable(Location)).returns(DefNode) } + def def_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), receiver: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), locals: T.unsafe(nil), def_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new DefinedNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: T.nilable(Location), value: Node, rparen_loc: T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } + def defined_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lparen_loc: T.unsafe(nil), value: T.unsafe(nil), rparen_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new ElseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: T.nilable(Location)).returns(ElseNode) } + def else_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), else_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new EmbeddedStatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } + def embedded_statements_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), statements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new EmbeddedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } + def embedded_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), variable: T.unsafe(nil)); end + + # Create a new EnsureNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } + def ensure_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), ensure_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new FalseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(FalseNode) } + def false_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new FindPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: T.any(SplatNode, MissingNode), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(FindPatternNode) } + def find_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), left: T.unsafe(nil), requireds: T.unsafe(nil), right: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new FlipFlopNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } + def flip_flop_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new FloatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Float).returns(FloatNode) } + def float_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ForNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } + def for_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), index: T.unsafe(nil), collection: T.unsafe(nil), statements: T.unsafe(nil), for_keyword_loc: T.unsafe(nil), in_keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new ForwardingArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ForwardingArgumentsNode) } + def forwarding_arguments_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ForwardingParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ForwardingParameterNode) } + def forwarding_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ForwardingSuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: T.nilable(BlockNode)).returns(ForwardingSuperNode) } + def forwarding_super_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new GlobalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableAndWriteNode) } + def global_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new GlobalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(GlobalVariableOperatorWriteNode) } + def global_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new GlobalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableOrWriteNode) } + def global_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new GlobalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableReadNode) } + def global_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new GlobalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableTargetNode) } + def global_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new GlobalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(GlobalVariableWriteNode) } + def global_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new HashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } + def hash_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), elements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new HashPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(HashPatternNode) } + def hash_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), elements: T.unsafe(nil), rest: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new IfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: T.nilable(Location), predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(T.any(ElseNode, IfNode)), end_keyword_loc: T.nilable(Location)).returns(IfNode) } + def if_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), if_keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new ImaginaryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } + def imaginary_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numeric: T.unsafe(nil)); end + + # Create a new ImplicitNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } + def implicit_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new ImplicitRestNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ImplicitRestNode) } + def implicit_rest_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new InNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: T.nilable(StatementsNode), in_loc: Location, then_loc: T.nilable(Location)).returns(InNode) } + def in_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), pattern: T.unsafe(nil), statements: T.unsafe(nil), in_loc: T.unsafe(nil), then_loc: T.unsafe(nil)); end + + # Create a new IndexAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } + def index_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new IndexOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } + def index_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new IndexOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } + def index_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new IndexTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } + def index_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new InstanceVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableAndWriteNode) } + def instance_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new InstanceVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(InstanceVariableOperatorWriteNode) } + def instance_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + # Create a new InstanceVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableOrWriteNode) } + def instance_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new InstanceVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableReadNode) } + def instance_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new InstanceVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableTargetNode) } + def instance_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new InstanceVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(InstanceVariableWriteNode) } + def instance_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new IntegerNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Integer).returns(IntegerNode) } + def integer_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new InterpolatedMatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } + def interpolated_match_last_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedRegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } + def interpolated_regular_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: T.nilable(Location)).returns(InterpolatedStringNode) } + def interpolated_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedSymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: T.nilable(Location)).returns(InterpolatedSymbolNode) } + def interpolated_symbol_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new InterpolatedXStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } + def interpolated_x_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new ItLocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ItLocalVariableReadNode) } + def it_local_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ItParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(ItParametersNode) } + def it_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new KeywordHashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } + def keyword_hash_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil)); end + + # Create a new KeywordRestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } + def keyword_rest_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new LambdaNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode))).returns(LambdaNode) } + def lambda_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil)); end + + # Create a new LocalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableAndWriteNode) } + def local_variable_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).returns(LocalVariableOperatorWriteNode) } + def local_variable_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), binary_operator: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableOrWriteNode) } + def local_variable_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableReadNode) } + def local_variable_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableTargetNode) } + def local_variable_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + # Create a new LocalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).returns(LocalVariableWriteNode) } + def local_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new MatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(MatchLastLineNode) } + def match_last_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new MatchPredicateNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchPredicateNode) } + def match_predicate_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new MatchRequiredNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchRequiredNode) } + def match_required_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new MatchWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).returns(MatchWriteNode) } + def match_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), call: T.unsafe(nil), targets: T.unsafe(nil)); end + + # Create a new MissingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(MissingNode) } + def missing_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ModuleNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } + def module_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), module_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new MultiTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location)).returns(MultiTargetNode) } + def multi_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + # Create a new MultiWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } + def multi_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new NextNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } + def next_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new NilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(NilNode) } + def nil_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new NoBlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoBlockParameterNode) } + def no_block_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new NoKeywordsParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoKeywordsParameterNode) } + def no_keywords_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new NumberedParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, maximum: Integer).returns(NumberedParametersNode) } + def numbered_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), maximum: T.unsafe(nil)); end + + # Create a new NumberedReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, number: Integer).returns(NumberedReferenceReadNode) } + def numbered_reference_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), number: T.unsafe(nil)); end + + # Create a new OptionalKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).returns(OptionalKeywordParameterNode) } + def optional_keyword_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new OptionalParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(OptionalParameterNode) } + def optional_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + # Create a new OrNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(OrNode) } + def or_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new ParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: T.nilable(T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } + def parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), requireds: T.unsafe(nil), optionals: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), keywords: T.unsafe(nil), keyword_rest: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new ParenthesesNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } + def parentheses_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new PinnedExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).returns(PinnedExpressionNode) } + def pinned_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + # Create a new PinnedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } + def pinned_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), variable: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new PostExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } + def post_execution_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new PreExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } + def pre_execution_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + # Create a new ProgramNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).returns(ProgramNode) } + def program_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new RangeNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(RangeNode) } + def range_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new RationalNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).returns(RationalNode) } + def rational_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numerator: T.unsafe(nil), denominator: T.unsafe(nil)); end + + # Create a new RedoNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(RedoNode) } + def redo_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new RegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(RegularExpressionNode) } + def regular_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new RequiredKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).returns(RequiredKeywordParameterNode) } + def required_keyword_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + # Create a new RequiredParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(RequiredParameterNode) } + def required_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + # Create a new RescueModifierNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).returns(RescueModifierNode) } + def rescue_modifier_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), keyword_loc: T.unsafe(nil), rescue_expression: T.unsafe(nil)); end + + # Create a new RescueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: T.nilable(Location), reference: T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(RescueNode)).returns(RescueNode) } + def rescue_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), exceptions: T.unsafe(nil), operator_loc: T.unsafe(nil), reference: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil)); end + + # Create a new RestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } + def rest_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + # Create a new RetryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(RetryNode) } + def retry_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ReturnNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: T.nilable(ArgumentsNode)).returns(ReturnNode) } + def return_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), arguments: T.unsafe(nil)); end + + # Create a new SelfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(SelfNode) } + def self_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new ShareableConstantNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } + def shareable_constant_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), write: T.unsafe(nil)); end + + # Create a new SingletonClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } + def singleton_class_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new SourceEncodingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(SourceEncodingNode) } + def source_encoding_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new SourceFileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, filepath: String).returns(SourceFileNode) } + def source_file_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), filepath: T.unsafe(nil)); end + + # Create a new SourceLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(SourceLineNode) } + def source_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new SplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: T.nilable(Node)).returns(SplatNode) } + def splat_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil)); end + + # Create a new StatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).returns(StatementsNode) } + def statements_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil)); end + + # Create a new StringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), content_loc: Location, closing_loc: T.nilable(Location), unescaped: String).returns(StringNode) } + def string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new SuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } + def super_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + # Create a new SymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), value_loc: T.nilable(Location), closing_loc: T.nilable(Location), unescaped: String).returns(SymbolNode) } + def symbol_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), value_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new TrueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).returns(TrueNode) } + def true_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + # Create a new UndefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } + def undef_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), names: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + # Create a new UnlessNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), else_clause: T.nilable(ElseNode), end_keyword_loc: T.nilable(Location)).returns(UnlessNode) } + def unless_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), else_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + # Create a new UntilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(UntilNode) } + def until_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new WhenNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode)).returns(WhenNode) } + def when_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), conditions: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new WhileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(WhileNode) } + def while_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + # Create a new XStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(XStringNode) } + def x_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + # Create a new YieldNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location)).returns(YieldNode) } + def yield_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + # Retrieve the value of one of the ArgumentsNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def arguments_node_flag(name); end + + # Retrieve the value of one of the ArrayNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def array_node_flag(name); end + + # Retrieve the value of one of the CallNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def call_node_flag(name); end + + # Retrieve the value of one of the EncodingFlags flags. + sig { params(name: Symbol).returns(Integer) } + def encoding_flag(name); end + + # Retrieve the value of one of the IntegerBaseFlags flags. + sig { params(name: Symbol).returns(Integer) } + def integer_base_flag(name); end + + # Retrieve the value of one of the InterpolatedStringNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def interpolated_string_node_flag(name); end + + # Retrieve the value of one of the KeywordHashNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def keyword_hash_node_flag(name); end + + # Retrieve the value of one of the LoopFlags flags. + sig { params(name: Symbol).returns(Integer) } + def loop_flag(name); end + + # Retrieve the value of one of the ParameterFlags flags. + sig { params(name: Symbol).returns(Integer) } + def parameter_flag(name); end + + # Retrieve the value of one of the ParenthesesNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def parentheses_node_flag(name); end + + # Retrieve the value of one of the RangeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def range_flag(name); end + + # Retrieve the value of one of the RegularExpressionFlags flags. + sig { params(name: Symbol).returns(Integer) } + def regular_expression_flag(name); end + + # Retrieve the value of one of the ShareableConstantNodeFlags flags. + sig { params(name: Symbol).returns(Integer) } + def shareable_constant_node_flag(name); end + + # Retrieve the value of one of the StringFlags flags. + sig { params(name: Symbol).returns(Integer) } + def string_flag(name); end + + # Retrieve the value of one of the SymbolFlags flags. + sig { params(name: Symbol).returns(Integer) } + def symbol_flag(name); end + + # The default source object that gets attached to nodes and locations if no + # source is specified. + sig { returns(Source) } + private def default_source; end + + # The default location object that gets attached to nodes if no location is + # specified, which uses the given source. + sig { returns(Location) } + private def default_location; end + + # The default node that gets attached to nodes if no node is specified for a + # required node field. + sig { params(source: Source, location: Location).returns(Node) } + private def default_node(source, location); end + end +end diff --git a/rbi/generated/prism/inspect_visitor.rbi b/rbi/generated/prism/inspect_visitor.rbi new file mode 100644 index 0000000000..85442ef768 --- /dev/null +++ b/rbi/generated/prism/inspect_visitor.rbi @@ -0,0 +1,503 @@ +# typed: true + +module Prism + # This visitor is responsible for composing the strings that get returned by + # the various #inspect methods defined on each of the nodes. + class InspectVisitor < Visitor + # Most of the time, we can simply pass down the indent to the next node. + # However, when we are inside a list we want some extra special formatting + # when we hit an element in that list. In this case, we have a special + # command that replaces the subsequent indent with the given value. + class Replace + sig { returns(String) } + attr_reader :value + + sig { params(value: String).void } + def initialize(value); end + end + + # The current prefix string. + sig { returns(String) } + attr_reader :indent + + # The list of commands that we need to execute in order to compose the + # final string. + sig { returns(T::Array[[T.any(String, Node, Replace), String]]) } + attr_reader :commands + + sig { params(indent: String).void } + def initialize(indent = T.unsafe(nil)); end + + # Compose an inspect string for the given node. + sig { params(node: Node).returns(String) } + def self.compose(node); end + + # Compose the final string. + sig { returns(String) } + def compose; end + + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + sig { params(node: AndNode).void } + def visit_and_node(node); end + + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + sig { params(node: CallNode).void } + def visit_call_node(node); end + + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + sig { params(node: DefNode).void } + def visit_def_node(node); end + + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + sig { params(node: ForNode).void } + def visit_for_node(node); end + + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + sig { params(node: IfNode).void } + def visit_if_node(node); end + + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + sig { params(node: InNode).void } + def visit_in_node(node); end + + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + sig { params(node: NextNode).void } + def visit_next_node(node); end + + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + sig { params(node: OrNode).void } + def visit_or_node(node); end + + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + sig { params(node: StringNode).void } + def visit_string_node(node); end + + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + + # Compose a header for the given node. + sig { params(name: String, node: Node).returns(String) } + private def inspect_node(name, node); end + + # Compose a string representing the given inner location field. + sig { params(location: T.nilable(Location)).returns(String) } + private def inspect_location(location); end + end +end diff --git a/rbi/generated/prism/lex_compat.rbi b/rbi/generated/prism/lex_compat.rbi new file mode 100644 index 0000000000..df47383acf --- /dev/null +++ b/rbi/generated/prism/lex_compat.rbi @@ -0,0 +1,155 @@ +# typed: true + +module Prism + module Translation + class Ripper + EXPR_NONE = T.let(nil, Integer) + EXPR_BEG = T.let(nil, Integer) + EXPR_MID = T.let(nil, Integer) + EXPR_END = T.let(nil, Integer) + EXPR_CLASS = T.let(nil, Integer) + EXPR_VALUE = T.let(nil, Integer) + EXPR_ARG = T.let(nil, Integer) + EXPR_CMDARG = T.let(nil, Integer) + EXPR_ENDARG = T.let(nil, Integer) + EXPR_ENDFN = T.let(nil, Integer) + + class Lexer < Ripper + class State + sig { params(value: Integer).returns(State) } + def self.[](value); end + end + end + end + end + + # This class is responsible for lexing the source using prism and then + # converting those tokens to be compatible with Ripper. In the vast majority + # of cases, this is a one-to-one mapping of the token type. Everything else + # generally lines up. However, there are a few cases that require special + # handling. + class LexCompat + # A result class specialized for holding tokens produced by the lexer. + class Result < Prism::Result + # The list of tokens that were produced by the lexer. + sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + attr_reader :value + + # Create a new lex compat result object with the given values. + sig { params(value: T::Array[[[Integer, Integer], Symbol, String, T.untyped]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + + # Implement the hash pattern matching interface for Result. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + end + + # This is a mapping of prism token types to Ripper token types. This is a + # many-to-one mapping because we split up our token types, whereas Ripper + # tends to group them. + RIPPER = T.let(nil, T.untyped) + + # A heredoc in this case is a list of tokens that belong to the body of the + # heredoc that should be appended onto the list of tokens when the heredoc + # closes. + module Heredoc + # Heredocs that are no dash or tilde heredocs are just a list of tokens. + # We need to keep them around so that we can insert them in the correct + # order back into the token stream and set the state of the last token to + # the state that the heredoc was opened in. + class PlainHeredoc + sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + attr_reader :tokens + + sig { void } + def initialize; end + + sig { params(token: [[Integer, Integer], Symbol, String, T.untyped]).void } + def <<(token); end + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + def to_a; end + end + + # Dash heredocs are a little more complicated. They are a list of tokens + # that need to be split on "\\\n" to mimic Ripper's behavior. We also need + # to keep track of the state that the heredoc was opened in. + class DashHeredoc + sig { returns(T::Boolean) } + attr_reader :split + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + attr_reader :tokens + + sig { params(split: T::Boolean).void } + def initialize(split); end + + sig { params(token: [[Integer, Integer], Symbol, String, T.untyped]).void } + def <<(token); end + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + def to_a; end + end + + # Heredocs that are dedenting heredocs are a little more complicated. + # Ripper outputs on_ignored_sp tokens for the whitespace that is being + # removed from the output. prism only modifies the node itself and keeps + # the token the same. This simplifies prism, but makes comparing against + # Ripper much harder because there is a length mismatch. + # + # Fortunately, we already have to pull out the heredoc tokens in order to + # insert them into the stream in the correct order. As such, we can do + # some extra manipulation on the tokens to make them match Ripper's + # output by mirroring the dedent logic that Ripper uses. + class DedentingHeredoc + TAB_WIDTH = T.let(nil, Integer) + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + attr_reader :tokens + + sig { returns(T::Boolean) } + attr_reader :dedent_next + + sig { returns(T.nilable(Integer)) } + attr_reader :dedent + + sig { returns(Integer) } + attr_reader :embexpr_balance + + sig { void } + def initialize; end + + # As tokens are coming in, we track the minimum amount of common leading + # whitespace on plain string content tokens. This allows us to later + # remove that amount of whitespace from the beginning of each line. + # + sig { params(token: [[Integer, Integer], Symbol, String, T.untyped]).void } + def <<(token); end + + sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + def to_a; end + end + + # Here we will split between the two types of heredocs and return the + # object that will store their tokens. + sig { params(opening: [[Integer, Integer], Symbol, String, T.untyped]).returns(T.any(PlainHeredoc, DashHeredoc, DedentingHeredoc)) } + def self.build(opening); end + end + + # In previous versions of Ruby, Ripper wouldn't flush the bom before the + # first token, so we had to have a hack in place to account for that. + BOM_FLUSHED = T.let(nil, T.untyped) + + sig { returns(T::Hash[Symbol, T.untyped]) } + attr_reader :options + + sig { params(source: String, options: T.untyped).void } + def initialize(source, **options); end + + sig { returns(Result) } + def result; end + + sig { params(tokens: T::Array[[[Integer, Integer], Symbol, String, T.untyped]], source: Source, data_loc: T.nilable(Location), bom: T::Boolean, eof_token: T.nilable(Token)).returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + private def post_process_tokens(tokens, source, data_loc, bom, eof_token); end + end +end diff --git a/rbi/generated/prism/mutation_compiler.rbi b/rbi/generated/prism/mutation_compiler.rbi new file mode 100644 index 0000000000..f62613fa1b --- /dev/null +++ b/rbi/generated/prism/mutation_compiler.rbi @@ -0,0 +1,464 @@ +# typed: true + +module Prism + # This visitor walks through the tree and copies each node as it is being + # visited. This is useful for consumers that want to mutate the tree, as you + # can change subtrees in place without effecting the rest of the tree. + class MutationCompiler < Compiler + sig { params(arg0: AliasGlobalVariableNode).returns(T.nilable(Node)) } + def visit_alias_global_variable_node(arg0); end + + sig { params(arg0: AliasMethodNode).returns(T.nilable(Node)) } + def visit_alias_method_node(arg0); end + + sig { params(arg0: AlternationPatternNode).returns(T.nilable(Node)) } + def visit_alternation_pattern_node(arg0); end + + sig { params(arg0: AndNode).returns(T.nilable(Node)) } + def visit_and_node(arg0); end + + sig { params(arg0: ArgumentsNode).returns(T.nilable(Node)) } + def visit_arguments_node(arg0); end + + sig { params(arg0: ArrayNode).returns(T.nilable(Node)) } + def visit_array_node(arg0); end + + sig { params(arg0: ArrayPatternNode).returns(T.nilable(Node)) } + def visit_array_pattern_node(arg0); end + + sig { params(arg0: AssocNode).returns(T.nilable(Node)) } + def visit_assoc_node(arg0); end + + sig { params(arg0: AssocSplatNode).returns(T.nilable(Node)) } + def visit_assoc_splat_node(arg0); end + + sig { params(arg0: BackReferenceReadNode).returns(T.nilable(Node)) } + def visit_back_reference_read_node(arg0); end + + sig { params(arg0: BeginNode).returns(T.nilable(Node)) } + def visit_begin_node(arg0); end + + sig { params(arg0: BlockArgumentNode).returns(T.nilable(Node)) } + def visit_block_argument_node(arg0); end + + sig { params(arg0: BlockLocalVariableNode).returns(T.nilable(Node)) } + def visit_block_local_variable_node(arg0); end + + sig { params(arg0: BlockNode).returns(T.nilable(Node)) } + def visit_block_node(arg0); end + + sig { params(arg0: BlockParameterNode).returns(T.nilable(Node)) } + def visit_block_parameter_node(arg0); end + + sig { params(arg0: BlockParametersNode).returns(T.nilable(Node)) } + def visit_block_parameters_node(arg0); end + + sig { params(arg0: BreakNode).returns(T.nilable(Node)) } + def visit_break_node(arg0); end + + sig { params(arg0: CallAndWriteNode).returns(T.nilable(Node)) } + def visit_call_and_write_node(arg0); end + + sig { params(arg0: CallNode).returns(T.nilable(Node)) } + def visit_call_node(arg0); end + + sig { params(arg0: CallOperatorWriteNode).returns(T.nilable(Node)) } + def visit_call_operator_write_node(arg0); end + + sig { params(arg0: CallOrWriteNode).returns(T.nilable(Node)) } + def visit_call_or_write_node(arg0); end + + sig { params(arg0: CallTargetNode).returns(T.nilable(Node)) } + def visit_call_target_node(arg0); end + + sig { params(arg0: CapturePatternNode).returns(T.nilable(Node)) } + def visit_capture_pattern_node(arg0); end + + sig { params(arg0: CaseMatchNode).returns(T.nilable(Node)) } + def visit_case_match_node(arg0); end + + sig { params(arg0: CaseNode).returns(T.nilable(Node)) } + def visit_case_node(arg0); end + + sig { params(arg0: ClassNode).returns(T.nilable(Node)) } + def visit_class_node(arg0); end + + sig { params(arg0: ClassVariableAndWriteNode).returns(T.nilable(Node)) } + def visit_class_variable_and_write_node(arg0); end + + sig { params(arg0: ClassVariableOperatorWriteNode).returns(T.nilable(Node)) } + def visit_class_variable_operator_write_node(arg0); end + + sig { params(arg0: ClassVariableOrWriteNode).returns(T.nilable(Node)) } + def visit_class_variable_or_write_node(arg0); end + + sig { params(arg0: ClassVariableReadNode).returns(T.nilable(Node)) } + def visit_class_variable_read_node(arg0); end + + sig { params(arg0: ClassVariableTargetNode).returns(T.nilable(Node)) } + def visit_class_variable_target_node(arg0); end + + sig { params(arg0: ClassVariableWriteNode).returns(T.nilable(Node)) } + def visit_class_variable_write_node(arg0); end + + sig { params(arg0: ConstantAndWriteNode).returns(T.nilable(Node)) } + def visit_constant_and_write_node(arg0); end + + sig { params(arg0: ConstantOperatorWriteNode).returns(T.nilable(Node)) } + def visit_constant_operator_write_node(arg0); end + + sig { params(arg0: ConstantOrWriteNode).returns(T.nilable(Node)) } + def visit_constant_or_write_node(arg0); end + + sig { params(arg0: ConstantPathAndWriteNode).returns(T.nilable(Node)) } + def visit_constant_path_and_write_node(arg0); end + + sig { params(arg0: ConstantPathNode).returns(T.nilable(Node)) } + def visit_constant_path_node(arg0); end + + sig { params(arg0: ConstantPathOperatorWriteNode).returns(T.nilable(Node)) } + def visit_constant_path_operator_write_node(arg0); end + + sig { params(arg0: ConstantPathOrWriteNode).returns(T.nilable(Node)) } + def visit_constant_path_or_write_node(arg0); end + + sig { params(arg0: ConstantPathTargetNode).returns(T.nilable(Node)) } + def visit_constant_path_target_node(arg0); end + + sig { params(arg0: ConstantPathWriteNode).returns(T.nilable(Node)) } + def visit_constant_path_write_node(arg0); end + + sig { params(arg0: ConstantReadNode).returns(T.nilable(Node)) } + def visit_constant_read_node(arg0); end + + sig { params(arg0: ConstantTargetNode).returns(T.nilable(Node)) } + def visit_constant_target_node(arg0); end + + sig { params(arg0: ConstantWriteNode).returns(T.nilable(Node)) } + def visit_constant_write_node(arg0); end + + sig { params(arg0: DefNode).returns(T.nilable(Node)) } + def visit_def_node(arg0); end + + sig { params(arg0: DefinedNode).returns(T.nilable(Node)) } + def visit_defined_node(arg0); end + + sig { params(arg0: ElseNode).returns(T.nilable(Node)) } + def visit_else_node(arg0); end + + sig { params(arg0: EmbeddedStatementsNode).returns(T.nilable(Node)) } + def visit_embedded_statements_node(arg0); end + + sig { params(arg0: EmbeddedVariableNode).returns(T.nilable(Node)) } + def visit_embedded_variable_node(arg0); end + + sig { params(arg0: EnsureNode).returns(T.nilable(Node)) } + def visit_ensure_node(arg0); end + + sig { params(arg0: FalseNode).returns(T.nilable(Node)) } + def visit_false_node(arg0); end + + sig { params(arg0: FindPatternNode).returns(T.nilable(Node)) } + def visit_find_pattern_node(arg0); end + + sig { params(arg0: FlipFlopNode).returns(T.nilable(Node)) } + def visit_flip_flop_node(arg0); end + + sig { params(arg0: FloatNode).returns(T.nilable(Node)) } + def visit_float_node(arg0); end + + sig { params(arg0: ForNode).returns(T.nilable(Node)) } + def visit_for_node(arg0); end + + sig { params(arg0: ForwardingArgumentsNode).returns(T.nilable(Node)) } + def visit_forwarding_arguments_node(arg0); end + + sig { params(arg0: ForwardingParameterNode).returns(T.nilable(Node)) } + def visit_forwarding_parameter_node(arg0); end + + sig { params(arg0: ForwardingSuperNode).returns(T.nilable(Node)) } + def visit_forwarding_super_node(arg0); end + + sig { params(arg0: GlobalVariableAndWriteNode).returns(T.nilable(Node)) } + def visit_global_variable_and_write_node(arg0); end + + sig { params(arg0: GlobalVariableOperatorWriteNode).returns(T.nilable(Node)) } + def visit_global_variable_operator_write_node(arg0); end + + sig { params(arg0: GlobalVariableOrWriteNode).returns(T.nilable(Node)) } + def visit_global_variable_or_write_node(arg0); end + + sig { params(arg0: GlobalVariableReadNode).returns(T.nilable(Node)) } + def visit_global_variable_read_node(arg0); end + + sig { params(arg0: GlobalVariableTargetNode).returns(T.nilable(Node)) } + def visit_global_variable_target_node(arg0); end + + sig { params(arg0: GlobalVariableWriteNode).returns(T.nilable(Node)) } + def visit_global_variable_write_node(arg0); end + + sig { params(arg0: HashNode).returns(T.nilable(Node)) } + def visit_hash_node(arg0); end + + sig { params(arg0: HashPatternNode).returns(T.nilable(Node)) } + def visit_hash_pattern_node(arg0); end + + sig { params(arg0: IfNode).returns(T.nilable(Node)) } + def visit_if_node(arg0); end + + sig { params(arg0: ImaginaryNode).returns(T.nilable(Node)) } + def visit_imaginary_node(arg0); end + + sig { params(arg0: ImplicitNode).returns(T.nilable(Node)) } + def visit_implicit_node(arg0); end + + sig { params(arg0: ImplicitRestNode).returns(T.nilable(Node)) } + def visit_implicit_rest_node(arg0); end + + sig { params(arg0: InNode).returns(T.nilable(Node)) } + def visit_in_node(arg0); end + + sig { params(arg0: IndexAndWriteNode).returns(T.nilable(Node)) } + def visit_index_and_write_node(arg0); end + + sig { params(arg0: IndexOperatorWriteNode).returns(T.nilable(Node)) } + def visit_index_operator_write_node(arg0); end + + sig { params(arg0: IndexOrWriteNode).returns(T.nilable(Node)) } + def visit_index_or_write_node(arg0); end + + sig { params(arg0: IndexTargetNode).returns(T.nilable(Node)) } + def visit_index_target_node(arg0); end + + sig { params(arg0: InstanceVariableAndWriteNode).returns(T.nilable(Node)) } + def visit_instance_variable_and_write_node(arg0); end + + sig { params(arg0: InstanceVariableOperatorWriteNode).returns(T.nilable(Node)) } + def visit_instance_variable_operator_write_node(arg0); end + + sig { params(arg0: InstanceVariableOrWriteNode).returns(T.nilable(Node)) } + def visit_instance_variable_or_write_node(arg0); end + + sig { params(arg0: InstanceVariableReadNode).returns(T.nilable(Node)) } + def visit_instance_variable_read_node(arg0); end + + sig { params(arg0: InstanceVariableTargetNode).returns(T.nilable(Node)) } + def visit_instance_variable_target_node(arg0); end + + sig { params(arg0: InstanceVariableWriteNode).returns(T.nilable(Node)) } + def visit_instance_variable_write_node(arg0); end + + sig { params(arg0: IntegerNode).returns(T.nilable(Node)) } + def visit_integer_node(arg0); end + + sig { params(arg0: InterpolatedMatchLastLineNode).returns(T.nilable(Node)) } + def visit_interpolated_match_last_line_node(arg0); end + + sig { params(arg0: InterpolatedRegularExpressionNode).returns(T.nilable(Node)) } + def visit_interpolated_regular_expression_node(arg0); end + + sig { params(arg0: InterpolatedStringNode).returns(T.nilable(Node)) } + def visit_interpolated_string_node(arg0); end + + sig { params(arg0: InterpolatedSymbolNode).returns(T.nilable(Node)) } + def visit_interpolated_symbol_node(arg0); end + + sig { params(arg0: InterpolatedXStringNode).returns(T.nilable(Node)) } + def visit_interpolated_x_string_node(arg0); end + + sig { params(arg0: ItLocalVariableReadNode).returns(T.nilable(Node)) } + def visit_it_local_variable_read_node(arg0); end + + sig { params(arg0: ItParametersNode).returns(T.nilable(Node)) } + def visit_it_parameters_node(arg0); end + + sig { params(arg0: KeywordHashNode).returns(T.nilable(Node)) } + def visit_keyword_hash_node(arg0); end + + sig { params(arg0: KeywordRestParameterNode).returns(T.nilable(Node)) } + def visit_keyword_rest_parameter_node(arg0); end + + sig { params(arg0: LambdaNode).returns(T.nilable(Node)) } + def visit_lambda_node(arg0); end + + sig { params(arg0: LocalVariableAndWriteNode).returns(T.nilable(Node)) } + def visit_local_variable_and_write_node(arg0); end + + sig { params(arg0: LocalVariableOperatorWriteNode).returns(T.nilable(Node)) } + def visit_local_variable_operator_write_node(arg0); end + + sig { params(arg0: LocalVariableOrWriteNode).returns(T.nilable(Node)) } + def visit_local_variable_or_write_node(arg0); end + + sig { params(arg0: LocalVariableReadNode).returns(T.nilable(Node)) } + def visit_local_variable_read_node(arg0); end + + sig { params(arg0: LocalVariableTargetNode).returns(T.nilable(Node)) } + def visit_local_variable_target_node(arg0); end + + sig { params(arg0: LocalVariableWriteNode).returns(T.nilable(Node)) } + def visit_local_variable_write_node(arg0); end + + sig { params(arg0: MatchLastLineNode).returns(T.nilable(Node)) } + def visit_match_last_line_node(arg0); end + + sig { params(arg0: MatchPredicateNode).returns(T.nilable(Node)) } + def visit_match_predicate_node(arg0); end + + sig { params(arg0: MatchRequiredNode).returns(T.nilable(Node)) } + def visit_match_required_node(arg0); end + + sig { params(arg0: MatchWriteNode).returns(T.nilable(Node)) } + def visit_match_write_node(arg0); end + + sig { params(arg0: MissingNode).returns(T.nilable(Node)) } + def visit_missing_node(arg0); end + + sig { params(arg0: ModuleNode).returns(T.nilable(Node)) } + def visit_module_node(arg0); end + + sig { params(arg0: MultiTargetNode).returns(T.nilable(Node)) } + def visit_multi_target_node(arg0); end + + sig { params(arg0: MultiWriteNode).returns(T.nilable(Node)) } + def visit_multi_write_node(arg0); end + + sig { params(arg0: NextNode).returns(T.nilable(Node)) } + def visit_next_node(arg0); end + + sig { params(arg0: NilNode).returns(T.nilable(Node)) } + def visit_nil_node(arg0); end + + sig { params(arg0: NoBlockParameterNode).returns(T.nilable(Node)) } + def visit_no_block_parameter_node(arg0); end + + sig { params(arg0: NoKeywordsParameterNode).returns(T.nilable(Node)) } + def visit_no_keywords_parameter_node(arg0); end + + sig { params(arg0: NumberedParametersNode).returns(T.nilable(Node)) } + def visit_numbered_parameters_node(arg0); end + + sig { params(arg0: NumberedReferenceReadNode).returns(T.nilable(Node)) } + def visit_numbered_reference_read_node(arg0); end + + sig { params(arg0: OptionalKeywordParameterNode).returns(T.nilable(Node)) } + def visit_optional_keyword_parameter_node(arg0); end + + sig { params(arg0: OptionalParameterNode).returns(T.nilable(Node)) } + def visit_optional_parameter_node(arg0); end + + sig { params(arg0: OrNode).returns(T.nilable(Node)) } + def visit_or_node(arg0); end + + sig { params(arg0: ParametersNode).returns(T.nilable(Node)) } + def visit_parameters_node(arg0); end + + sig { params(arg0: ParenthesesNode).returns(T.nilable(Node)) } + def visit_parentheses_node(arg0); end + + sig { params(arg0: PinnedExpressionNode).returns(T.nilable(Node)) } + def visit_pinned_expression_node(arg0); end + + sig { params(arg0: PinnedVariableNode).returns(T.nilable(Node)) } + def visit_pinned_variable_node(arg0); end + + sig { params(arg0: PostExecutionNode).returns(T.nilable(Node)) } + def visit_post_execution_node(arg0); end + + sig { params(arg0: PreExecutionNode).returns(T.nilable(Node)) } + def visit_pre_execution_node(arg0); end + + sig { params(arg0: ProgramNode).returns(T.nilable(Node)) } + def visit_program_node(arg0); end + + sig { params(arg0: RangeNode).returns(T.nilable(Node)) } + def visit_range_node(arg0); end + + sig { params(arg0: RationalNode).returns(T.nilable(Node)) } + def visit_rational_node(arg0); end + + sig { params(arg0: RedoNode).returns(T.nilable(Node)) } + def visit_redo_node(arg0); end + + sig { params(arg0: RegularExpressionNode).returns(T.nilable(Node)) } + def visit_regular_expression_node(arg0); end + + sig { params(arg0: RequiredKeywordParameterNode).returns(T.nilable(Node)) } + def visit_required_keyword_parameter_node(arg0); end + + sig { params(arg0: RequiredParameterNode).returns(T.nilable(Node)) } + def visit_required_parameter_node(arg0); end + + sig { params(arg0: RescueModifierNode).returns(T.nilable(Node)) } + def visit_rescue_modifier_node(arg0); end + + sig { params(arg0: RescueNode).returns(T.nilable(Node)) } + def visit_rescue_node(arg0); end + + sig { params(arg0: RestParameterNode).returns(T.nilable(Node)) } + def visit_rest_parameter_node(arg0); end + + sig { params(arg0: RetryNode).returns(T.nilable(Node)) } + def visit_retry_node(arg0); end + + sig { params(arg0: ReturnNode).returns(T.nilable(Node)) } + def visit_return_node(arg0); end + + sig { params(arg0: SelfNode).returns(T.nilable(Node)) } + def visit_self_node(arg0); end + + sig { params(arg0: ShareableConstantNode).returns(T.nilable(Node)) } + def visit_shareable_constant_node(arg0); end + + sig { params(arg0: SingletonClassNode).returns(T.nilable(Node)) } + def visit_singleton_class_node(arg0); end + + sig { params(arg0: SourceEncodingNode).returns(T.nilable(Node)) } + def visit_source_encoding_node(arg0); end + + sig { params(arg0: SourceFileNode).returns(T.nilable(Node)) } + def visit_source_file_node(arg0); end + + sig { params(arg0: SourceLineNode).returns(T.nilable(Node)) } + def visit_source_line_node(arg0); end + + sig { params(arg0: SplatNode).returns(T.nilable(Node)) } + def visit_splat_node(arg0); end + + sig { params(arg0: StatementsNode).returns(T.nilable(Node)) } + def visit_statements_node(arg0); end + + sig { params(arg0: StringNode).returns(T.nilable(Node)) } + def visit_string_node(arg0); end + + sig { params(arg0: SuperNode).returns(T.nilable(Node)) } + def visit_super_node(arg0); end + + sig { params(arg0: SymbolNode).returns(T.nilable(Node)) } + def visit_symbol_node(arg0); end + + sig { params(arg0: TrueNode).returns(T.nilable(Node)) } + def visit_true_node(arg0); end + + sig { params(arg0: UndefNode).returns(T.nilable(Node)) } + def visit_undef_node(arg0); end + + sig { params(arg0: UnlessNode).returns(T.nilable(Node)) } + def visit_unless_node(arg0); end + + sig { params(arg0: UntilNode).returns(T.nilable(Node)) } + def visit_until_node(arg0); end + + sig { params(arg0: WhenNode).returns(T.nilable(Node)) } + def visit_when_node(arg0); end + + sig { params(arg0: WhileNode).returns(T.nilable(Node)) } + def visit_while_node(arg0); end + + sig { params(arg0: XStringNode).returns(T.nilable(Node)) } + def visit_x_string_node(arg0); end + + sig { params(arg0: YieldNode).returns(T.nilable(Node)) } + def visit_yield_node(arg0); end + end +end diff --git a/rbi/generated/prism/node.rbi b/rbi/generated/prism/node.rbi new file mode 100644 index 0000000000..f7486e9f66 --- /dev/null +++ b/rbi/generated/prism/node.rbi @@ -0,0 +1,13811 @@ +# typed: true + +module Prism + # This represents a node in the tree. It is the parent class of all of the + # various node types. + class Node + abstract! + + # A pointer to the source that this node was created from. + sig { returns(Source) } + attr_reader :source + + # A unique identifier for this node. This is used in a very specific + # use case where you want to keep around a reference to a node without + # having to keep around the syntax tree in memory. This unique identifier + # will be consistent across multiple parses of the same source code. + sig { returns(Integer) } + attr_reader :node_id + + # Save this node using a saved source so that it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save(repository); end + + # A Location instance that represents the location of this node in the + # source. + sig { returns(Location) } + def location; end + + # Save the location using a saved source so that it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_location(repository); end + + # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. + sig { returns(Integer) } + def start_line; end + + # Delegates to [`end_line`](rdoc-ref:Location#end_line) of the associated location object. + sig { returns(Integer) } + def end_line; end + + # Delegates to [`start_offset`](rdoc-ref:Location#start_offset) of the associated location object. + sig { returns(Integer) } + def start_offset; end + + # Delegates to [`end_offset`](rdoc-ref:Location#end_offset) of the associated location object. + sig { returns(Integer) } + def end_offset; end + + # Delegates to [`start_character_offset`](rdoc-ref:Location#start_character_offset) + # of the associated location object. + sig { returns(Integer) } + def start_character_offset; end + + # Delegates to [`end_character_offset`](rdoc-ref:Location#end_character_offset) + # of the associated location object. + sig { returns(Integer) } + def end_character_offset; end + + # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) + # of the associated location object. + sig { params(cache: T.untyped).returns(Integer) } + def cached_start_code_units_offset(cache); end + + # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) + # of the associated location object. + sig { params(cache: T.untyped).returns(Integer) } + def cached_end_code_units_offset(cache); end + + # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. + sig { returns(Integer) } + def start_column; end + + # Delegates to [`end_column`](rdoc-ref:Location#end_column) of the associated location object. + sig { returns(Integer) } + def end_column; end + + # Delegates to [`start_character_column`](rdoc-ref:Location#start_character_column) + # of the associated location object. + sig { returns(Integer) } + def start_character_column; end + + # Delegates to [`end_character_column`](rdoc-ref:Location#end_character_column) + # of the associated location object. + sig { returns(Integer) } + def end_character_column; end + + # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) + # of the associated location object. + sig { params(cache: T.untyped).returns(Integer) } + def cached_start_code_units_column(cache); end + + # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) + # of the associated location object. + sig { params(cache: T.untyped).returns(Integer) } + def cached_end_code_units_column(cache); end + + # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. + sig { returns(T::Array[Comment]) } + def leading_comments; end + + # Delegates to [`trailing_comments`](rdoc-ref:Location#trailing_comments) of the associated location object. + sig { returns(T::Array[Comment]) } + def trailing_comments; end + + # Delegates to [`comments`](rdoc-ref:Location#comments) of the associated location object. + sig { returns(T::Array[Comment]) } + def comments; end + + # Returns all of the lines of the source code associated with this node. + sig { returns(T::Array[String]) } + def source_lines; end + + # Slice the location of the node from the source. + sig { returns(String) } + def slice; end + + # Slice the location of the node from the source, starting at the beginning + # of the line that the location starts on, ending at the end of the line + # that the location ends on. + sig { returns(String) } + def slice_lines; end + + # An bitset of flags for this node. There are certain flags that are common + # for all nodes, and then some nodes have specific flags. + sig { returns(Integer) } + attr_reader :flags + + # Returns true if the node has the newline flag set. + sig { returns(T::Boolean) } + def newline?; end + + # Returns true if the node has the static literal flag set. + sig { returns(T::Boolean) } + def static_literal?; end + + # Similar to inspect, but respects the current level of indentation given by + # the pretty print object. + sig { params(q: PP).void } + def pretty_print(q); end + + # Convert this node into a graphviz dot graph string. + sig { returns(String) } + def to_dot; end + + # Returns a list of nodes that are descendants of this node that contain the + # given line and column. This is useful for locating a node that is selected + # based on the line and column of the source code. + # + # Important to note is that the column given to this method should be in + # bytes, as opposed to characters or code units. + sig { params(line: Integer, column: Integer).returns(T::Array[Node]) } + def tunnel(line, column); end + + # Returns the first node that matches the given block when visited in a + # breadth-first search. This is useful for finding a node that matches a + # particular condition. + # + # node.breadth_first_search { |node| node.node_id == node_id } + sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T.nilable(Node)) } + def breadth_first_search(&blk); end + + # Returns all of the nodes that match the given block when visited in a + # breadth-first search. This is useful for finding all nodes that match a + # particular condition. + # + # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } + sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } + def breadth_first_search_all(&blk); end + + # Returns a list of the fields that exist for this node class. Fields + # describe the structure of the node. This kind of reflection is useful for + # things like recursively visiting each node _and_ field in the tree. + sig { returns(T::Array[Reflection::Field]) } + def self.fields; end + + # Accepts a visitor and calls back into the specialized visit function. + sig { abstract.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # Returns an array of child nodes, including `nil`s in the place of optional + # nodes that were not present. + sig { abstract.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # With a block given, yields each child node. Without a block, returns + # an enumerator that contains each child node. Excludes any `nil`s in + # the place of optional nodes that were not present. + sig { abstract.returns(T::Enumerator[Node]) } + sig { abstract.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # Returns an array of child nodes, excluding any `nil`s in the place of + # optional nodes that were not present. + sig { abstract.returns(T::Array[Node]) } + def compact_child_nodes; end + + # Returns an array of child nodes and locations that could potentially have + # comments attached to them. + sig { abstract.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Returns a string representation of the node. + sig { abstract.returns(String) } + def inspect; end + + # Sometimes you want to check an instance of a node against a list of + # classes to see what kind of behavior to perform. Usually this is done by + # calling `[cls1, cls2].include?(node.class)` or putting the node into a + # case statement and doing `case node; when cls1; when cls2; end`. Both of + # these approaches are relatively slow because of the constant lookups, + # method calls, and/or array allocations. + # + # Instead, you can call #type, which will return to you a symbol that you + # can use for comparison. This is faster than the other approaches because + # it uses a single integer comparison, but also because if you're on CRuby + # you can take advantage of the fact that case statements with all symbol + # keys will use a jump table. + sig { abstract.returns(Symbol) } + def type; end + + # Similar to #type, this method returns a symbol that you can use for + # splitting on the type of the node without having to do a long === chain. + # Note that like #type, it will still be slower than using == for a single + # class, but should be faster in a case statement or an array comparison. + sig { abstract.returns(Symbol) } + def self.type; end + end + + # Represents the use of the `alias` keyword to alias a global variable. + # + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + class AliasGlobalVariableNode < Node + # Initialize a new AliasGlobalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, new_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the new name of the global variable that can be used after aliasing. + # + # alias $foo $bar + # ^^^^ + sig { returns(T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } + def new_name; end + + # Represents the old name of the global variable that can be used before aliasing. + # + # alias $foo $bar + # ^^^^ + sig { returns(T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode)) } + def old_name; end + + # The Location of the `alias` keyword. + # + # alias $foo $bar + # ^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `alias` keyword to alias a method. + # + # alias foo bar + # ^^^^^^^^^^^^^ + class AliasMethodNode < Node + # Initialize a new AliasMethodNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(SymbolNode, InterpolatedSymbolNode), old_name: T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, new_name: T.any(SymbolNode, InterpolatedSymbolNode), old_name: T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the new name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + sig { returns(T.any(SymbolNode, InterpolatedSymbolNode)) } + def new_name; end + + # Represents the old name of the method that will be aliased. + # + # alias foo bar + # ^^^ + # + # alias :foo :bar + # ^^^^ + # + # alias :"#{foo}" :"#{bar}" + # ^^^^^^^^^ + sig { returns(T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode)) } + def old_name; end + + # Represents the Location of the `alias` keyword. + # + # alias foo bar + # ^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an alternation pattern in pattern matching. + # + # foo => bar | baz + # ^^^^^^^^^ + class AlternationPatternNode < Node + # Initialize a new AlternationPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AlternationPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the left side of the expression. + # + # foo => bar | baz + # ^^^ + sig { returns(Node) } + def left; end + + # Represents the right side of the expression. + # + # foo => bar | baz + # ^^^ + sig { returns(Node) } + def right; end + + # Represents the alternation operator Location. + # + # foo => bar | baz + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&` operator or the `and` keyword. + # + # left and right + # ^^^^^^^^^^^^^^ + class AndNode < Node + # Initialize a new AndNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AndNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # left and right + # ^^^^ + # + # 1 && 2 + # ^ + sig { returns(Node) } + def left; end + + # Represents the right side of the expression. + # + # left && right + # ^^^^^ + # + # 1 and 2 + # ^ + sig { returns(Node) } + def right; end + + # The Location of the `and` keyword or the `&&` operator. + # + # left and right + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a set of arguments to a method or a keyword. + # + # return foo, bar, baz + # ^^^^^^^^^^^^^ + class ArgumentsNode < Node + # Initialize a new ArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).void } + def initialize(source, node_id, location, flags, arguments); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).returns(ArgumentsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # if the arguments contain forwarding + sig { returns(T::Boolean) } + def contains_forwarding?; end + + # if the arguments contain keywords + sig { returns(T::Boolean) } + def contains_keywords?; end + + # if the arguments contain a keyword splat + sig { returns(T::Boolean) } + def contains_keyword_splat?; end + + # if the arguments contain a splat + sig { returns(T::Boolean) } + def contains_splat?; end + + # if the arguments contain multiple splats + sig { returns(T::Boolean) } + def contains_multiple_splats?; end + + # The list of arguments, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar, baz) + # ^^^^^^^^ + sig { returns(T::Array[Node]) } + def arguments; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i. + # + # [1, 2, 3] + # ^^^^^^^^^ + class ArrayNode < Node + # Initialize a new ArrayNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, elements, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # if array contains splat nodes + sig { returns(T::Boolean) } + def contains_splat?; end + + # Represent the list of zero or more [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression) within the array. + sig { returns(T::Array[Node]) } + def elements; end + + # Represents the optional source Location for the opening token. + # + # [1,2,3] # "[" + # %w[foo bar baz] # "%w[" + # %I(apple orange banana) # "%I(" + # foo = 1, 2, 3 # nil + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the optional source Location for the closing token. + # + # [1,2,3] # "]" + # %w[foo bar baz] # "]" + # %I(apple orange banana) # ")" + # foo = 1, 2, 3 # nil + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an array pattern in pattern matching. + # + # foo in 1, 2 + # ^^^^^^^^^^^ + # + # foo in [1, 2] + # ^^^^^^^^^^^^^ + # + # foo in *bar + # ^^^^^^^^^^^ + # + # foo in Bar[] + # ^^^^^^^^^^^^ + # + # foo in Bar[1, 2, 3] + # ^^^^^^^^^^^^^^^^^^^ + class ArrayPatternNode < Node + # Initialize a new ArrayPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, constant, requireds, rest, posts, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), requireds: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the optional constant preceding the Array + # + # foo in Bar[] + # ^^^ + # + # foo in Bar[1, 2, 3] + # ^^^ + # + # foo in Bar::Baz[1, 2, 3] + # ^^^^^^^^ + sig { returns(T.nilable(T.any(ConstantPathNode, ConstantReadNode))) } + def constant; end + + # Represents the required elements of the array pattern. + # + # foo in [1, 2] + # ^ ^ + sig { returns(T::Array[Node]) } + def requireds; end + + # Represents the rest element of the array pattern. + # + # foo in *bar + # ^^^^ + sig { returns(T.nilable(Node)) } + def rest; end + + # Represents the elements after the rest element of the array pattern. + # + # foo in *bar, baz + # ^^^ + sig { returns(T::Array[Node]) } + def posts; end + + # Represents the opening Location of the array pattern. + # + # foo in [1, 2] + # ^ + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the closing Location of the array pattern. + # + # foo in [1, 2] + # ^ + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash key/value pair. + # + # { a => b } + # ^^^^^^ + class AssocNode < Node + # Initialize a new AssocNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, key, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: T.nilable(Location)).returns(AssocNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), key: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # { a: b } + # ^ + # + # { foo => bar } + # ^^^ + # + # { def a; end => 1 } + # ^^^^^^^^^^ + sig { returns(Node) } + def key; end + + # The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # { foo => bar } + # ^^^ + # + # { x: 1 } + # ^ + sig { returns(Node) } + def value; end + + # The Location of the `=>` operator, if present. + # + # { foo => bar } + # ^^ + sig { returns(T.nilable(Location)) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(T.nilable(String)) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a splat in a hash literal. + # + # { **foo } + # ^^^^^ + class AssocSplatNode < Node + # Initialize a new AssocSplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used. + # + # { **foo } + # ^^^ + sig { returns(T.nilable(Node)) } + def value; end + + # The Location of the `**` operator. + # + # { **x } + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading a reference to a field in the previous match. + # + # $' + # ^^ + class BackReferenceReadNode < Node + # Initialize a new BackReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BackReferenceReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the back-reference variable, including the leading `$`. + # + # $& # name `:$&` + # + # $+ # name `:$+` + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a begin statement. + # + # begin + # foo + # end + # ^^^^^ + class BeginNode < Node + # Initialize a new BeginNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), rescue_clause: T.nilable(RescueNode), else_clause: T.nilable(ElseNode), ensure_clause: T.nilable(EnsureNode), end_keyword_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), rescue_clause: T.nilable(RescueNode), else_clause: T.nilable(ElseNode), ensure_clause: T.nilable(EnsureNode), end_keyword_loc: T.nilable(Location)).returns(BeginNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), begin_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), rescue_clause: T.unsafe(nil), else_clause: T.unsafe(nil), ensure_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the Location of the `begin` keyword. + # + # begin x end + # ^^^^^ + sig { returns(T.nilable(Location)) } + def begin_keyword_loc; end + + # Save the begin_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_begin_keyword_loc(repository); end + + # Represents the statements within the begin block. + # + # begin x end + # ^ + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Represents the rescue clause within the begin block. + # + # begin x; rescue y; end + # ^^^^^^^^ + sig { returns(T.nilable(RescueNode)) } + def rescue_clause; end + + # Represents the else clause within the begin block. + # + # begin x; rescue y; else z; end + # ^^^^^^ + sig { returns(T.nilable(ElseNode)) } + def else_clause; end + + # Represents the ensure clause within the begin block. + # + # begin x; ensure y; end + # ^^^^^^^^ + sig { returns(T.nilable(EnsureNode)) } + def ensure_clause; end + + # Represents the Location of the `end` keyword. + # + # begin x end + # ^^^ + sig { returns(T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of begin_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def begin_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block argument using `&`. + # + # bar(&args) + # ^^^^^^^^^^ + class BlockArgumentNode < Node + # Initialize a new BlockArgumentNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, expression, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(&args) + # ^^^^^ + sig { returns(T.nilable(Node)) } + def expression; end + + # Represents the Location of the `&` operator. + # + # foo(&args) + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block local variable. + # + # a { |; b| } + # ^ + class BlockLocalVariableNode < Node + # Initialize a new BlockLocalVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BlockLocalVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # The name of the block local variable. + # + # a { |; b| } # name `:b` + # ^ + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block of ruby code. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^^^^^^^^^ + class BlockNode < Node + # Initialize a new BlockNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, locals, parameters, body, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The local variables declared in the block. + # + # [1, 2, 3].each { |i| puts x } # locals: [:i] + # ^ + sig { returns(T::Array[Symbol]) } + def locals; end + + # The parameters of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^ + # [1, 2, 3].each { puts _1 } + # ^^^^^^^^^^^ + # [1, 2, 3].each { puts it } + # ^^^^^^^^^^^ + sig { returns(T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } + def parameters; end + + # The body of the block. + # + # [1, 2, 3].each { |i| puts x } + # ^^^^^^ + sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + def body; end + + # Represents the Location of the opening `{` or `do`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Represents the Location of the closing `}` or `end`. + # + # [1, 2, 3].each { |i| puts x } + # ^ + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block parameter of a method, block, or lambda definition. + # + # def a(&b) + # ^^ + # end + class BlockParameterNode < Node + # Initialize a new BlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # The name of the block parameter. + # + # def a(&b) # name `:b` + # ^ + # end + sig { returns(T.nilable(Symbol)) } + def name; end + + # Represents the Location of the block parameter name. + # + # def a(&b) + # ^ + sig { returns(T.nilable(Location)) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_name_loc(repository); end + + # Represents the Location of the `&` operator. + # + # def a(&b) + # ^ + # end + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a block's parameters declaration. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^^^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^^^^^^^^^^ + # end + class BlockParametersNode < Node + # Initialize a new BlockParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, parameters, locals, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, parameters: T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(BlockParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parameters: T.unsafe(nil), locals: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the parameters of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^^^^ + # end + sig { returns(T.nilable(ParametersNode)) } + def parameters; end + + # Represents the local variables of the block. + # + # -> (a, b = 1; local) { } + # ^^^^^ + # + # foo do |a, b = 1; local| + # ^^^^^ + # end + sig { returns(T::Array[BlockLocalVariableNode]) } + def locals; end + + # Represents the opening Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the closing Location of the block parameters. + # + # -> (a, b = 1; local) { } + # ^ + # + # foo do |a, b = 1; local| + # ^ + # end + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `break` keyword. + # + # break foo + # ^^^^^^^^^ + class BreakNode < Node + # Initialize a new BreakNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, arguments, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The arguments to the break statement, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # break foo + # ^^^ + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # The Location of the `break` keyword. + # + # break foo + # ^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator on a call. + # + # foo.bar &&= value + # ^^^^^^^^^^^^^^^^^ + class CallAndWriteNode < Node + # Initialize a new CallAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar &&= value + # ^^^ + sig { returns(T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar &&= value + # ^ + sig { returns(T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the Location of the message. + # + # foo.bar &&= value + # ^^^ + sig { returns(T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar &&= value # read_name `:bar` + # ^^^ + sig { returns(Symbol) } + def read_name; end + + # Represents the name of the method being written to. + # + # foo.bar &&= value # write_name `:bar=` + # ^^^ + sig { returns(Symbol) } + def write_name; end + + # Represents the Location of the operator. + # + # foo.bar &&= value + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Represents the value being assigned. + # + # foo.bar &&= value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(T.nilable(String)) } + def message; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a method call, in all of the various forms that can take. + # + # foo + # ^^^ + # + # foo() + # ^^^^^ + # + # +foo + # ^^^^ + # + # foo + bar + # ^^^^^^^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo&.bar + # ^^^^^^^^ + class CallNode < Node + # Initialize a new CallNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), name: Symbol, message_loc: T.nilable(Location), opening_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), closing_loc: T.nilable(Location), equal_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc, opening_loc, arguments, closing_loc, equal_loc, block); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), name: Symbol, message_loc: T.nilable(Location), opening_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), closing_loc: T.nilable(Location), equal_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar + # ^^^ + # + # +foo + # ^^^ + # + # foo + bar + # ^^^ + sig { returns(T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar + # ^ + # + # foo&.bar + # ^^ + sig { returns(T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar # name `:foo` + # ^^^ + sig { returns(Symbol) } + def name; end + + # Represents the Location of the message. + # + # foo.bar + # ^^^ + sig { returns(T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the Location of the left parenthesis. + # + # foo(bar) + # ^ + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo(bar) + # ^^^ + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Represents the Location of the right parenthesis. + # + # foo(bar) + # ^ + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Represents the Location of the equal sign, in the case that this is an attribute write. + # + # foo.bar = value + # ^ + # + # foo[bar] = value + # ^ + sig { returns(T.nilable(Location)) } + def equal_loc; end + + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_equal_loc(repository); end + + # Represents the block that is being passed to the method. + # + # foo { |a| a } + # ^^^^^^^^^ + sig { returns(T.nilable(T.any(BlockNode, BlockArgumentNode))) } + def block; end + + # Slice the location of call_operator_loc from the source. + sig { returns(T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(T.nilable(String)) } + def message; end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + # Slice the location of equal_loc from the source. + sig { returns(T.nilable(String)) } + def equal; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of an assignment operator on a call. + # + # foo.bar += baz + # ^^^^^^^^^^^^^^ + class CallOperatorWriteNode < Node + # Initialize a new CallOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, binary_operator, binary_operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar += value + # ^^^ + sig { returns(T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar += value + # ^ + sig { returns(T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the Location of the message. + # + # foo.bar += value + # ^^^ + sig { returns(T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar += value # read_name `:bar` + # ^^^ + sig { returns(Symbol) } + def read_name; end + + # Represents the name of the method being written to. + # + # foo.bar += value # write_name `:bar=` + # ^^^ + sig { returns(Symbol) } + def write_name; end + + # Represents the binary operator being used. + # + # foo.bar += value # binary_operator `:+` + # ^ + sig { returns(Symbol) } + def binary_operator; end + + # Represents the Location of the binary operator. + # + # foo.bar += value + # ^^ + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Represents the value being assigned. + # + # foo.bar += value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(T.nilable(String)) } + def message; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator on a call. + # + # foo.bar ||= value + # ^^^^^^^^^^^^^^^^^ + class CallOrWriteNode < Node + # Initialize a new CallOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar ||= value + # ^^^ + sig { returns(T.nilable(Node)) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar ||= value + # ^ + sig { returns(T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Represents the Location of the message. + # + # foo.bar ||= value + # ^^^ + sig { returns(T.nilable(Location)) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_message_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar ||= value # read_name `:bar` + # ^^^ + sig { returns(Symbol) } + def read_name; end + + # Represents the name of the method being written to. + # + # foo.bar ||= value # write_name `:bar=` + # ^^^ + sig { returns(Symbol) } + def write_name; end + + # Represents the Location of the operator. + # + # foo.bar ||= value + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Represents the value being assigned. + # + # foo.bar ||= value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(T.nilable(String)) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(T.nilable(String)) } + def message; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a method call. + # + # foo.bar, = 1 + # ^^^^^^^ + # + # begin + # rescue => foo.bar + # ^^^^^^^ + # end + # + # for foo.bar in baz do end + # ^^^^^^^ + class CallTargetNode < Node + # Initialize a new CallTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).returns(CallTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # The object that the method is being called on. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo.bar = 1 + # ^^^ + sig { returns(Node) } + def receiver; end + + # Represents the Location of the call operator. + # + # foo.bar = 1 + # ^ + sig { returns(Location) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_call_operator_loc(repository); end + + # Represents the name of the method being called. + # + # foo.bar = 1 # name `:foo` + # ^^^ + sig { returns(Symbol) } + def name; end + + # Represents the Location of the message. + # + # foo.bar = 1 + # ^^^ + sig { returns(Location) } + def message_loc; end + + # Save the message_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_message_loc(repository); end + + # Slice the location of call_operator_loc from the source. + sig { returns(String) } + def call_operator; end + + # Slice the location of message_loc from the source. + sig { returns(String) } + def message; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a local variable in pattern matching. + # + # foo => [bar => baz] + # ^^^^^^^^^^^^ + class CapturePatternNode < Node + # Initialize a new CapturePatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, target, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).returns(CapturePatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the value to capture. + # + # foo => bar + # ^^^ + sig { returns(Node) } + def value; end + + # Represents the target of the capture. + # + # foo => bar + # ^^^ + sig { returns(LocalVariableTargetNode) } + def target; end + + # Represents the Location of the `=>` operator. + # + # foo => bar + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of a case statement for pattern matching. + # + # case true + # in false + # end + # ^^^^^^^^^ + class CaseMatchNode < Node + # Initialize a new CaseMatchNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[InNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[InNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; in false; end + # ^^^^ + sig { returns(T.nilable(Node)) } + def predicate; end + + # Represents the conditions of the case match. + # + # case true; in false; end + # ^^^^^^^^ + sig { returns(T::Array[InNode]) } + def conditions; end + + # Represents the else clause of the case match. + # + # case true; in false; else; end + # ^^^^ + sig { returns(T.nilable(ElseNode)) } + def else_clause; end + + # Represents the Location of the `case` keyword. + # + # case true; in false; end + # ^^^^ + sig { returns(Location) } + def case_keyword_loc; end + + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_case_keyword_loc(repository); end + + # Represents the Location of the `end` keyword. + # + # case true; in false; end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of case_keyword_loc from the source. + sig { returns(String) } + def case_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of a case statement. + # + # case true + # when false + # end + # ^^^^^^^^^^ + class CaseNode < Node + # Initialize a new CaseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[WhenNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[WhenNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # case true; when false; end + # ^^^^ + sig { returns(T.nilable(Node)) } + def predicate; end + + # Represents the conditions of the case statement. + # + # case true; when false; end + # ^^^^^^^^^^ + sig { returns(T::Array[WhenNode]) } + def conditions; end + + # Represents the else clause of the case statement. + # + # case true; when false; else; end + # ^^^^ + sig { returns(T.nilable(ElseNode)) } + def else_clause; end + + # Represents the Location of the `case` keyword. + # + # case true; when false; end + # ^^^^ + sig { returns(Location) } + def case_keyword_loc; end + + # Save the case_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_case_keyword_loc(repository); end + + # Represents the Location of the `end` keyword. + # + # case true; when false; end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of case_keyword_loc from the source. + sig { returns(String) } + def case_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a class declaration involving the `class` keyword. + # + # class Foo end + # ^^^^^^^^^^^^^ + class ClassNode < Node + # Initialize a new ClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: T.nilable(Location), superclass: T.nilable(Node), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } + def initialize(source, node_id, location, flags, locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, body, end_keyword_loc, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: T.nilable(Location), superclass: T.nilable(Node), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), inheritance_operator_loc: T.unsafe(nil), superclass: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Represents the Location of the `class` keyword. + # + # class Foo end + # ^^^^^ + sig { returns(Location) } + def class_keyword_loc; end + + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_class_keyword_loc(repository); end + + # Returns the `constant_path` attribute. + sig { returns(T.any(ConstantReadNode, ConstantPathNode, CallNode)) } + def constant_path; end + + # Represents the Location of the `<` operator. + # + # class Foo < Bar + # ^ + sig { returns(T.nilable(Location)) } + def inheritance_operator_loc; end + + # Save the inheritance_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_inheritance_operator_loc(repository); end + + # Represents the superclass of the class. + # + # class Foo < Bar + # ^^^ + sig { returns(T.nilable(Node)) } + def superclass; end + + # Represents the body of the class. + # + # class Foo + # foo + # ^^^ + sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + def body; end + + # Represents the Location of the `end` keyword. + # + # class Foo end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # The name of the class. + # + # class Foo end # name `:Foo` + sig { returns(Symbol) } + def name; end + + # Slice the location of class_keyword_loc from the source. + sig { returns(String) } + def class_keyword; end + + # Slice the location of inheritance_operator_loc from the source. + sig { returns(T.nilable(String)) } + def inheritance_operator; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a class variable. + # + # @@target &&= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableAndWriteNode < Node + # Initialize a new ClassVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@target &&= value # name `:@@target` + # ^^^^^^^^ + sig { returns(Symbol) } + def name; end + + # Represents the Location of the variable name. + # + # @@target &&= value + # ^^^^^^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Represents the Location of the `&&=` operator. + # + # @@target &&= value + # ^^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @@target &&= value + # ^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a class variable using an operator that isn't `=`. + # + # @@target += value + # ^^^^^^^^^^^^^^^^^ + class ClassVariableOperatorWriteNode < Node + # Initialize a new ClassVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ClassVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a class variable. + # + # @@target ||= value + # ^^^^^^^^^^^^^^^^^^ + class ClassVariableOrWriteNode < Node + # Initialize a new ClassVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing a class variable. + # + # @@foo + # ^^^^^ + class ClassVariableReadNode < Node + # Initialize a new ClassVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc # name `:@@abc` + # + # @@_test # name `:@@_test` + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a class variable in a context that doesn't have an explicit value. + # + # @@foo, @@bar = baz + # ^^^^^ ^^^^^ + class ClassVariableTargetNode < Node + # Initialize a new ClassVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a class variable. + # + # @@foo = 1 + # ^^^^^^^^^ + class ClassVariableWriteNode < Node + # Initialize a new ClassVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ClassVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @@abc = 123 # name `@@abc` + # + # @@_test = :test # name `@@_test` + sig { returns(Symbol) } + def name; end + + # The Location of the variable name. + # + # @@foo = :bar + # ^^^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # The value to write to the class variable. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @@foo = :bar + # ^^^^ + # + # @@_xyz = 123 + # ^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # @@foo = :bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a constant. + # + # Target &&= value + # ^^^^^^^^^^^^^^^^ + class ConstantAndWriteNode < Node + # Initialize a new ConstantAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a constant using an operator that isn't `=`. + # + # Target += value + # ^^^^^^^^^^^^^^^ + class ConstantOperatorWriteNode < Node + # Initialize a new ConstantOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a constant. + # + # Target ||= value + # ^^^^^^^^^^^^^^^^ + class ConstantOrWriteNode < Node + # Initialize a new ConstantOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a constant path. + # + # Parent::Child &&= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathAndWriteNode < Node + # Initialize a new ConstantPathAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, target, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `target` attribute. + sig { returns(ConstantPathNode) } + def target; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents accessing a constant through a path of `::` operators. + # + # Foo::Bar + # ^^^^^^^^ + class ConstantPathNode < Node + # Initialize a new ConstantPathNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } + def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The left-hand node of the path, if present. It can be `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It will be `nil` when the constant lookup is at the root of the module tree. + # + # Foo::Bar + # ^^^ + # + # self::Test + # ^^^^ + # + # a.b::C + # ^^^ + sig { returns(T.nilable(Node)) } + def parent; end + + # The name of the constant being accessed. This could be `nil` in the event of a syntax error. + sig { returns(T.nilable(Symbol)) } + def name; end + + # The Location of the `::` delimiter. + # + # ::Foo + # ^^ + # + # One::Two + # ^^ + sig { returns(Location) } + def delimiter_loc; end + + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_delimiter_loc(repository); end + + # The Location of the name of the constant. + # + # ::Foo + # ^^^ + # + # One::Two + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Slice the location of delimiter_loc from the source. + sig { returns(String) } + def delimiter; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a constant path using an operator that isn't `=`. + # + # Parent::Child += value + # ^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOperatorWriteNode < Node + # Initialize a new ConstantPathOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, target, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantPathOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `target` attribute. + sig { returns(ConstantPathNode) } + def target; end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a constant path. + # + # Parent::Child ||= value + # ^^^^^^^^^^^^^^^^^^^^^^^ + class ConstantPathOrWriteNode < Node + # Initialize a new ConstantPathOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, target, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `target` attribute. + sig { returns(ConstantPathNode) } + def target; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant path in a context that doesn't have an explicit value. + # + # Foo::Foo, Bar::Bar = baz + # ^^^^^^^^ ^^^^^^^^ + class ConstantPathTargetNode < Node + # Initialize a new ConstantPathTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } + def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `parent` attribute. + sig { returns(T.nilable(Node)) } + def parent; end + + # Returns the `name` attribute. + sig { returns(T.nilable(Symbol)) } + def name; end + + # Returns the Location represented by `delimiter_loc`. + sig { returns(Location) } + def delimiter_loc; end + + # Save the delimiter_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_delimiter_loc(repository); end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Slice the location of delimiter_loc from the source. + sig { returns(String) } + def delimiter; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant path. + # + # ::Foo = 1 + # ^^^^^^^^^ + # + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # ::Foo::Bar = 1 + # ^^^^^^^^^^^^^^ + class ConstantPathWriteNode < Node + # Initialize a new ConstantPathWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, target, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # A node representing the constant path being written to. + # + # Foo::Bar = 1 + # ^^^^^^^^ + # + # ::Foo = :abc + # ^^^^^ + sig { returns(ConstantPathNode) } + def target; end + + # The Location of the `=` operator. + # + # ::ABC = 123 + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # The value to write to the constant path. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # FOO::BAR = :abc + # ^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing a constant. + # + # Foo + # ^^^ + class ConstantReadNode < Node + # Initialize a new ConstantReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # X # name `:X` + # + # SOME_CONSTANT # name `:SOME_CONSTANT` + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant in a context that doesn't have an explicit value. + # + # Foo, Bar = baz + # ^^^ ^^^ + class ConstantTargetNode < Node + # Initialize a new ConstantTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a constant. + # + # Foo = 1 + # ^^^^^^^ + class ConstantWriteNode < Node + # Initialize a new ConstantWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ConstantWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). + # + # Foo = :bar # name `:Foo` + # + # XYZ = 1 # name `:XYZ` + sig { returns(Symbol) } + def name; end + + # The Location of the constant name. + # + # FOO = 1 + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # The value to write to the constant. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # FOO = :bar + # ^^^^ + # + # MyClass = Class.new + # ^^^^^^^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # FOO = :bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a method definition. + # + # def method + # end + # ^^^^^^^^^^ + class DefNode < Node + # Initialize a new DefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: T.nilable(Node), parameters: T.nilable(ParametersNode), body: T.nilable(T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: T.nilable(Location), lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), equal_loc: T.nilable(Location), end_keyword_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, name, name_loc, receiver, parameters, body, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: T.nilable(Node), parameters: T.nilable(ParametersNode), body: T.nilable(T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: T.nilable(Location), lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), equal_loc: T.nilable(Location), end_keyword_loc: T.nilable(Location)).returns(DefNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), receiver: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), locals: T.unsafe(nil), def_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the `receiver` attribute. + sig { returns(T.nilable(Node)) } + def receiver; end + + # Returns the `parameters` attribute. + sig { returns(T.nilable(ParametersNode)) } + def parameters; end + + # Returns the `body` attribute. + sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + def body; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `def_keyword_loc`. + sig { returns(Location) } + def def_keyword_loc; end + + # Save the def_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_def_keyword_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(T.nilable(Location)) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_operator_loc(repository); end + + # Returns the Location represented by `lparen_loc`. + sig { returns(T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Returns the Location represented by `rparen_loc`. + sig { returns(T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Returns the Location represented by `equal_loc`. + sig { returns(T.nilable(Location)) } + def equal_loc; end + + # Save the equal_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_equal_loc(repository); end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of def_keyword_loc from the source. + sig { returns(String) } + def def_keyword; end + + # Slice the location of operator_loc from the source. + sig { returns(T.nilable(String)) } + def operator; end + + # Slice the location of lparen_loc from the source. + sig { returns(T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(T.nilable(String)) } + def rparen; end + + # Slice the location of equal_loc from the source. + sig { returns(T.nilable(String)) } + def equal; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `defined?` keyword. + # + # defined?(a) + # ^^^^^^^^^^^ + class DefinedNode < Node + # Initialize a new DefinedNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: T.nilable(Location), value: Node, rparen_loc: T.nilable(Location), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, lparen_loc, value, rparen_loc, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, lparen_loc: T.nilable(Location), value: Node, rparen_loc: T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lparen_loc: T.unsafe(nil), value: T.unsafe(nil), rparen_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `lparen_loc`. + sig { returns(T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the Location represented by `rparen_loc`. + sig { returns(T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of lparen_loc from the source. + sig { returns(T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(T.nilable(String)) } + def rparen; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an `else` clause in a `case`, `if`, or `unless` statement. + # + # if a then b else c end + # ^^^^^^^^^^ + class ElseNode < Node + # Initialize a new ElseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, else_keyword_loc, statements, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: T.nilable(Location)).returns(ElseNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), else_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `else_keyword_loc`. + sig { returns(Location) } + def else_keyword_loc; end + + # Save the else_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_else_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of else_keyword_loc from the source. + sig { returns(String) } + def else_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an interpolated set of statements. + # + # "foo #{bar}" + # ^^^^^^ + class EmbeddedStatementsNode < Node + # Initialize a new EmbeddedStatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: T.nilable(StatementsNode), closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, statements, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), statements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an interpolated variable. + # + # "foo #@bar" + # ^^^^^ + class EmbeddedVariableNode < Node + # Initialize a new EmbeddedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).void } + def initialize(source, node_id, location, flags, operator_loc, variable); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), variable: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `variable` attribute. + sig { returns(T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } + def variable; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an `ensure` clause in a `begin` statement. + # + # begin + # foo + # ensure + # ^^^^^^ + # bar + # end + class EnsureNode < Node + # Initialize a new EnsureNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, ensure_keyword_loc, statements, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), ensure_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `ensure_keyword_loc`. + sig { returns(Location) } + def ensure_keyword_loc; end + + # Save the ensure_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_ensure_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of ensure_keyword_loc from the source. + sig { returns(String) } + def ensure_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the literal `false` keyword. + # + # false + # ^^^^^ + class FalseNode < Node + # Initialize a new FalseNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(FalseNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a find pattern in pattern matching. + # + # foo in *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + # + # foo in [*bar, baz, *qux] + # ^^^^^^^^^^^^^^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^^^^^^^^^^^^^^^^^ + # + # foo => *bar, baz, *qux + # ^^^^^^^^^^^^^^^ + class FindPatternNode < Node + # Initialize a new FindPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: T.any(SplatNode, MissingNode), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, constant, left, requireds, right, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: T.any(SplatNode, MissingNode), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(FindPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), left: T.unsafe(nil), requireds: T.unsafe(nil), right: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the optional constant preceding the pattern + # + # foo in Foo(*bar, baz, *qux) + # ^^^ + sig { returns(T.nilable(T.any(ConstantPathNode, ConstantReadNode))) } + def constant; end + + # Represents the first wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + sig { returns(SplatNode) } + def left; end + + # Represents the nodes in between the wildcards. + # + # foo in *bar, baz, *qux + # ^^^ + # + # foo in Foo(*bar, baz, 1, *qux) + # ^^^^^^ + sig { returns(T::Array[Node]) } + def requireds; end + + # Represents the second wildcard node in the pattern. + # + # foo in *bar, baz, *qux + # ^^^^ + # + # foo in Foo(*bar, baz, *qux) + # ^^^^ + sig { returns(T.any(SplatNode, MissingNode)) } + def right; end + + # The Location of the opening brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # The Location of the closing brace. + # + # foo in [*bar, baz, *qux] + # ^ + # + # foo in Foo(*bar, baz, *qux) + # ^ + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `..` or `...` operators to create flip flops. + # + # baz if foo .. bar + # ^^^^^^^^^^ + class FlipFlopNode < Node + # Initialize a new FlipFlopNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # ... operator + sig { returns(T::Boolean) } + def exclude_end?; end + + # Returns the `left` attribute. + sig { returns(T.nilable(Node)) } + def left; end + + # Returns the `right` attribute. + sig { returns(T.nilable(Node)) } + def right; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a floating point number literal. + # + # 1.0 + # ^^^ + class FloatNode < Node + # Initialize a new FloatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Float).void } + def initialize(source, node_id, location, flags, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Float).returns(FloatNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The value of the floating point number as a Float. + sig { returns(Float) } + def value; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `for` keyword. + # + # for i in a end + # ^^^^^^^^^^^^^^ + class ForNode < Node + # Initialize a new ForNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: T.nilable(Location), end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, index: T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), index: T.unsafe(nil), collection: T.unsafe(nil), statements: T.unsafe(nil), for_keyword_loc: T.unsafe(nil), in_keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The index expression for `for` loops. + # + # for i in a end + # ^ + sig { returns(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)) } + def index; end + + # The collection to iterate over. + # + # for i in a end + # ^ + sig { returns(Node) } + def collection; end + + # Represents the body of statements to execute for each iteration of the loop. + # + # for i in a + # foo(i) + # ^^^^^^ + # end + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # The Location of the `for` keyword. + # + # for i in a end + # ^^^ + sig { returns(Location) } + def for_keyword_loc; end + + # Save the for_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_for_keyword_loc(repository); end + + # The Location of the `in` keyword. + # + # for i in a end + # ^^ + sig { returns(Location) } + def in_keyword_loc; end + + # Save the in_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_in_keyword_loc(repository); end + + # The Location of the `do` keyword, if present. + # + # for i in a do end + # ^^ + sig { returns(T.nilable(Location)) } + def do_keyword_loc; end + + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_do_keyword_loc(repository); end + + # The Location of the `end` keyword. + # + # for i in a end + # ^^^ + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of for_keyword_loc from the source. + sig { returns(String) } + def for_keyword; end + + # Slice the location of in_keyword_loc from the source. + sig { returns(String) } + def in_keyword; end + + # Slice the location of do_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def do_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents forwarding all arguments to this method to another method. + # + # def foo(...) + # bar(...) + # ^^^ + # end + class ForwardingArgumentsNode < Node + # Initialize a new ForwardingArgumentsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingArgumentsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the forwarding parameter in a method, block, or lambda declaration. + # + # def foo(...) + # ^^^ + # end + class ForwardingParameterNode < Node + # Initialize a new ForwardingParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `super` keyword without parentheses or arguments, but which might have a block. + # + # super + # ^^^^^ + # + # super { 123 } + # ^^^^^^^^^^^^^ + # + # If it has any other arguments, it would be a `SuperNode` instead. + class ForwardingSuperNode < Node + # Initialize a new ForwardingSuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: T.nilable(BlockNode)).void } + def initialize(source, node_id, location, flags, block); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, block: T.nilable(BlockNode)).returns(ForwardingSuperNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # All other arguments are forwarded as normal, except the original block is replaced with the new block. + sig { returns(T.nilable(BlockNode)) } + def block; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a global variable. + # + # $target &&= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableAndWriteNode < Node + # Initialize a new GlobalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a global variable using an operator that isn't `=`. + # + # $target += value + # ^^^^^^^^^^^^^^^^ + class GlobalVariableOperatorWriteNode < Node + # Initialize a new GlobalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(GlobalVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a global variable. + # + # $target ||= value + # ^^^^^^^^^^^^^^^^^ + class GlobalVariableOrWriteNode < Node + # Initialize a new GlobalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing a global variable. + # + # $foo + # ^^^^ + class GlobalVariableReadNode < Node + # Initialize a new GlobalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo # name `:$foo` + # + # $_Test # name `:$_Test` + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a global variable in a context that doesn't have an explicit value. + # + # $foo, $bar = baz + # ^^^^ ^^^^ + class GlobalVariableTargetNode < Node + # Initialize a new GlobalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a global variable. + # + # $foo = 1 + # ^^^^^^^^ + class GlobalVariableWriteNode < Node + # Initialize a new GlobalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(GlobalVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. + # + # $foo = :bar # name `:$foo` + # + # $_Test = 123 # name `:$_Test` + sig { returns(Symbol) } + def name; end + + # The Location of the global variable's name. + # + # $foo = :bar + # ^^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # The value to write to the global variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # $foo = :bar + # ^^^^ + # + # $-xyz = 123 + # ^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # $foo = :bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash literal. + # + # { a => b } + # ^^^^^^^^^^ + class HashNode < Node + # Initialize a new HashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[T.any(AssocNode, AssocSplatNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, elements, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), elements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The Location of the opening brace. + # + # { a => b } + # ^ + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s. + # + # { a: b } + # ^^^^ + # + # { **foo } + # ^^^^^ + sig { returns(T::Array[T.any(AssocNode, AssocSplatNode)]) } + def elements; end + + # The Location of the closing brace. + # + # { a => b } + # ^ + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash pattern in pattern matching. + # + # foo => { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + # + # foo => { a: 1, b: 2, **c } + # ^^^^^^^^^^^^^^^^^^^ + # + # foo => Bar[a: 1, b: 2] + # ^^^^^^^^^^^^^^^ + # + # foo in { a: 1, b: 2 } + # ^^^^^^^^^^^^^^ + class HashPatternNode < Node + # Initialize a new HashPatternNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, constant, elements, rest, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(HashPatternNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), elements: T.unsafe(nil), rest: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the optional constant preceding the Hash. + # + # foo => Bar[a: 1, b: 2] + # ^^^ + # + # foo => Bar::Baz[a: 1, b: 2] + # ^^^^^^^^ + sig { returns(T.nilable(T.any(ConstantPathNode, ConstantReadNode))) } + def constant; end + + # Represents the explicit named hash keys and values. + # + # foo => { a: 1, b:, ** } + # ^^^^^^^^ + sig { returns(T::Array[AssocNode]) } + def elements; end + + # Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`. + # + # foo => { a: 1, b:, **c } + # ^^^ + # + # foo => { a: 1, b:, ** } + # ^^ + # + # foo => { a: 1, b:, **nil } + # ^^^^^ + sig { returns(T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode))) } + def rest; end + + # The Location of the opening brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # The Location of the closing brace. + # + # foo => { a: 1 } + # ^ + # + # foo => Bar[a: 1] + # ^ + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `if` keyword, either in the block form or the modifier form, or a ternary expression. + # + # bar if foo + # ^^^^^^^^^^ + # + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + class IfNode < Node + # Initialize a new IfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: T.nilable(Location), predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(T.any(ElseNode, IfNode)), end_keyword_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, if_keyword_loc, predicate, then_keyword_loc, statements, subsequent, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, if_keyword_loc: T.nilable(Location), predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(T.any(ElseNode, IfNode)), end_keyword_loc: T.nilable(Location)).returns(IfNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), if_keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The Location of the `if` keyword if present. + # + # bar if foo + # ^^ + # + # The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression. + sig { returns(T.nilable(Location)) } + def if_keyword_loc; end + + # Save the if_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_if_keyword_loc(repository); end + + # The node for the condition the `IfNode` is testing. + # + # if foo + # ^^^ + # bar + # end + # + # bar if foo + # ^^^ + # + # foo ? bar : baz + # ^^^ + sig { returns(Node) } + def predicate; end + + # The Location of the `then` keyword (if present) or the `?` in a ternary expression, `nil` otherwise. + # + # if foo then bar end + # ^^^^ + # + # a ? b : c + # ^ + sig { returns(T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # Represents the body of statements that will be executed when the predicate is evaluated as truthy. Will be `nil` when no body is provided. + # + # if foo + # bar + # ^^^ + # baz + # ^^^ + # end + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement. + # + # if foo + # bar + # elsif baz + # ^^^^^^^^^ + # qux + # ^^^ + # end + # ^^^ + # + # if foo then bar else baz end + # ^^^^^^^^^^^^ + sig { returns(T.nilable(T.any(ElseNode, IfNode))) } + def subsequent; end + + # The Location of the `end` keyword if present, `nil` otherwise. + # + # if foo + # bar + # end + # ^^^ + sig { returns(T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of if_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def if_keyword; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def then_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an imaginary number literal. + # + # 1.0i + # ^^^^ + class ImaginaryNode < Node + # Initialize a new ImaginaryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: T.any(FloatNode, IntegerNode, RationalNode)).void } + def initialize(source, node_id, location, flags, numeric); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, numeric: T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numeric: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `numeric` attribute. + sig { returns(T.any(FloatNode, IntegerNode, RationalNode)) } + def numeric; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source. + # + # { foo: } + # ^^^^ + # + # { Foo: } + # ^^^^ + # + # foo in { bar: } + # ^^^^ + class ImplicitNode < Node + # Initialize a new ImplicitNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).void } + def initialize(source, node_id, location, flags, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `value` attribute. + sig { returns(T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)) } + def value; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents using a trailing comma to indicate an implicit rest parameter. + # + # foo { |bar,| } + # ^ + # + # foo in [bar,] + # ^ + # + # for foo, in bar do end + # ^ + # + # foo, = bar + # ^ + class ImplicitRestNode < Node + # Initialize a new ImplicitRestNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ImplicitRestNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `in` keyword in a case statement. + # + # case a; in b then c end + # ^^^^^^^^^^^ + class InNode < Node + # Initialize a new InNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: T.nilable(StatementsNode), in_loc: Location, then_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, pattern, statements, in_loc, then_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: T.nilable(StatementsNode), in_loc: Location, then_loc: T.nilable(Location)).returns(InNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), pattern: T.unsafe(nil), statements: T.unsafe(nil), in_loc: T.unsafe(nil), then_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `pattern` attribute. + sig { returns(Node) } + def pattern; end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `in_loc`. + sig { returns(Location) } + def in_loc; end + + # Save the in_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_in_loc(repository); end + + # Returns the Location represented by `then_loc`. + sig { returns(T.nilable(Location)) } + def then_loc; end + + # Save the then_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_then_loc(repository); end + + # Slice the location of in_loc from the source. + sig { returns(String) } + def in; end + + # Slice the location of then_loc from the source. + sig { returns(T.nilable(String)) } + def then; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator on a call to the `[]` method. + # + # foo.bar[baz] &&= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexAndWriteNode < Node + # Initialize a new IndexAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(T.nilable(Node)) } + def receiver; end + + # Returns the Location represented by `call_operator_loc`. + sig { returns(T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(T.nilable(BlockArgumentNode)) } + def block; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(T.nilable(String)) } + def call_operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of an assignment operator on a call to `[]`. + # + # foo.bar[baz] += value + # ^^^^^^^^^^^^^^^^^^^^^ + class IndexOperatorWriteNode < Node + # Initialize a new IndexOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, binary_operator, binary_operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(T.nilable(Node)) } + def receiver; end + + # Returns the Location represented by `call_operator_loc`. + sig { returns(T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(T.nilable(BlockArgumentNode)) } + def block; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(T.nilable(String)) } + def call_operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator on a call to `[]`. + # + # foo.bar[baz] ||= value + # ^^^^^^^^^^^^^^^^^^^^^^ + class IndexOrWriteNode < Node + # Initialize a new IndexOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(T.nilable(Node)) } + def receiver; end + + # Returns the Location represented by `call_operator_loc`. + sig { returns(T.nilable(Location)) } + def call_operator_loc; end + + # Save the call_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_call_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(T.nilable(BlockArgumentNode)) } + def block; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of call_operator_loc from the source. + sig { returns(T.nilable(String)) } + def call_operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to an index. + # + # foo[bar], = 1 + # ^^^^^^^^ + # + # begin + # rescue => foo[bar] + # ^^^^^^^^ + # end + # + # for foo[bar] in baz do end + # ^^^^^^^^ + class IndexTargetNode < Node + # Initialize a new IndexTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode)).void } + def initialize(source, node_id, location, flags, receiver, opening_loc, arguments, closing_loc, block); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # &. operator + sig { returns(T::Boolean) } + def safe_navigation?; end + + # a call that could have been a local variable + sig { returns(T::Boolean) } + def variable_call?; end + + # a call that is an attribute write, so the value being written should be returned + sig { returns(T::Boolean) } + def attribute_write?; end + + # a call that ignores method visibility + sig { returns(T::Boolean) } + def ignore_visibility?; end + + # Returns the `receiver` attribute. + sig { returns(Node) } + def receiver; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `block` attribute. + sig { returns(T.nilable(BlockArgumentNode)) } + def block; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to an instance variable. + # + # @target &&= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableAndWriteNode < Node + # Initialize a new InstanceVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to an instance variable using an operator that isn't `=`. + # + # @target += value + # ^^^^^^^^^^^^^^^^ + class InstanceVariableOperatorWriteNode < Node + # Initialize a new InstanceVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).void } + def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(InstanceVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to an instance variable. + # + # @target ||= value + # ^^^^^^^^^^^^^^^^^ + class InstanceVariableOrWriteNode < Node + # Initialize a new InstanceVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents referencing an instance variable. + # + # @foo + # ^^^^ + class InstanceVariableReadNode < Node + # Initialize a new InstanceVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x # name `:@x` + # + # @_test # name `:@_test` + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to an instance variable in a context that doesn't have an explicit value. + # + # @foo, @bar = baz + # ^^^^ ^^^^ + class InstanceVariableTargetNode < Node + # Initialize a new InstanceVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to an instance variable. + # + # @foo = 1 + # ^^^^^^^^ + class InstanceVariableWriteNode < Node + # Initialize a new InstanceVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(InstanceVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # @x = :y # name `:@x` + # + # @_foo = "bar" # name `@_foo` + sig { returns(Symbol) } + def name; end + + # The Location of the variable name. + # + # @_x = 1 + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # The value to write to the instance variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # @foo = :bar + # ^^^^ + # + # @_x = 1234 + # ^^^^ + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # @x = y + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an integer number literal. + # + # 1 + # ^ + class IntegerNode < Node + # Initialize a new IntegerNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Integer).void } + def initialize(source, node_id, location, flags, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Integer).returns(IntegerNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 0b prefix + sig { returns(T::Boolean) } + def binary?; end + + # 0d or no prefix + sig { returns(T::Boolean) } + def decimal?; end + + # 0o or 0 prefix + sig { returns(T::Boolean) } + def octal?; end + + # 0x prefix + sig { returns(T::Boolean) } + def hexadecimal?; end + + # The value of the integer literal as a number. + sig { returns(Integer) } + def value; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo #{bar} baz/ then end + # ^^^^^^^^^^^^^^^^ + class InterpolatedMatchLastLineNode < Node + # Initialize a new InterpolatedMatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal that contains interpolation. + # + # /foo #{bar} baz/ + # ^^^^^^^^^^^^^^^^ + class InterpolatedRegularExpressionNode < Node + # Initialize a new InterpolatedRegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a string literal that contains interpolation. + # + # "foo #{bar} baz" + # ^^^^^^^^^^^^^^^^ + class InterpolatedStringNode < Node + # Initialize a new InterpolatedStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: T.nilable(Location)).returns(InterpolatedStringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + sig { returns(T::Boolean) } + def frozen?; end + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + sig { returns(T::Boolean) } + def mutable?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a symbol literal that contains interpolation. + # + # :"foo #{bar} baz" + # ^^^^^^^^^^^^^^^^^ + class InterpolatedSymbolNode < Node + # Initialize a new InterpolatedSymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: T.nilable(Location)).returns(InterpolatedSymbolNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `opening_loc`. + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an xstring literal that contains interpolation. + # + # `foo #{bar} baz` + # ^^^^^^^^^^^^^^^^ + class InterpolatedXStringNode < Node + # Initialize a new InterpolatedXStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the `parts` attribute. + sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + def parts; end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading from the implicit `it` local variable. + # + # -> { it } + # ^^ + class ItLocalVariableReadNode < Node + # Initialize a new ItLocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItLocalVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda. + # + # -> { it + it } + # ^^^^^^^^^^^^^^ + class ItParametersNode < Node + # Initialize a new ItParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a hash literal without opening and closing braces. + # + # foo(a: b) + # ^^^^ + class KeywordHashNode < Node + # Initialize a new KeywordHashNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[T.any(AssocNode, AssocSplatNode)]).void } + def initialize(source, node_id, location, flags, elements); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + sig { returns(T::Boolean) } + def symbol_keys?; end + + # Returns the `elements` attribute. + sig { returns(T::Array[T.any(AssocNode, AssocSplatNode)]) } + def elements; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a keyword rest parameter to a method, block, or lambda definition. + # + # def a(**b) + # ^^^ + # end + class KeywordRestParameterNode < Node + # Initialize a new KeywordRestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(T.nilable(Symbol)) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(T.nilable(Location)) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents using a lambda literal (not the lambda method call). + # + # ->(value) { value * 2 } + # ^^^^^^^^^^^^^^^^^^^^^^^ + class LambdaNode < Node + # Initialize a new LambdaNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode))).void } + def initialize(source, node_id, location, flags, locals, operator_loc, opening_loc, closing_loc, parameters, body); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode))).returns(LambdaNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `parameters` attribute. + sig { returns(T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } + def parameters; end + + # Returns the `body` attribute. + sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + def body; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `&&=` operator for assignment to a local variable. + # + # target &&= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableAndWriteNode < Node + # Initialize a new LocalVariableAndWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableAndWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents assigning to a local variable using an operator that isn't `=`. + # + # target += value + # ^^^^^^^^^^^^^^^ + class LocalVariableOperatorWriteNode < Node + # Initialize a new LocalVariableOperatorWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name_loc, binary_operator_loc, value, name, binary_operator, depth); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).returns(LocalVariableOperatorWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), binary_operator: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `binary_operator_loc`. + sig { returns(Location) } + def binary_operator_loc; end + + # Save the binary_operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_binary_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `binary_operator` attribute. + sig { returns(Symbol) } + def binary_operator; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||=` operator for assignment to a local variable. + # + # target ||= value + # ^^^^^^^^^^^^^^^^ + class LocalVariableOrWriteNode < Node + # Initialize a new LocalVariableOrWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableOrWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call. + # + # foo + # ^^^ + class LocalVariableReadNode < Node + # Initialize a new LocalVariableReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name, depth); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # x # name `:x` + # + # _Test # name `:_Test` + # + # Note that this can also be an underscore followed by a number for the default block parameters. + # + # _1 # name `:_1` + sig { returns(Symbol) } + def name; end + + # The number of visible scopes that should be searched to find the origin of this local variable. + # + # foo = 1; foo # depth 0 + # + # bar = 2; tap { bar } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + sig { returns(Integer) } + def depth; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a local variable in a context that doesn't have an explicit value. + # + # foo, bar = baz + # ^^^ ^^^ + # + # foo => baz + # ^^^ + class LocalVariableTargetNode < Node + # Initialize a new LocalVariableTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).void } + def initialize(source, node_id, location, flags, name, depth); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the `depth` attribute. + sig { returns(Integer) } + def depth; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing to a local variable. + # + # foo = 1 + # ^^^^^^^ + class LocalVariableWriteNode < Node + # Initialize a new LocalVariableWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, depth, name_loc, value, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).returns(LocalVariableWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + # + # foo = :bar # name `:foo` + # + # abc = 123 # name `:abc` + sig { returns(Symbol) } + def name; end + + # The number of semantic scopes we have to traverse to find the declaration of this variable. + # + # foo = 1 # depth 0 + # + # tap { foo = 1 } # depth 1 + # + # The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + sig { returns(Integer) } + def depth; end + + # The Location of the variable name. + # + # foo = :bar + # ^^^ + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # The value to write to the local variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # foo = :bar + # ^^^^ + # + # abc = 1234 + # ^^^^ + # + # Note that since the name of a local variable is known before the value is parsed, it is valid for a local variable to appear within the value of its own write. + # + # foo = foo + sig { returns(Node) } + def value; end + + # The Location of the `=` operator. + # + # x = :y + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object. + # + # if /foo/i then end + # ^^^^^^ + class MatchLastLineNode < Node + # Initialize a new MatchLastLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(MatchLastLineNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the modifier `in` operator. + # + # foo in bar + # ^^^^^^^^^^ + class MatchPredicateNode < Node + # Initialize a new MatchPredicateNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, pattern, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchPredicateNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Returns the `pattern` attribute. + sig { returns(Node) } + def pattern; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `=>` operator. + # + # foo => bar + # ^^^^^^^^^^ + class MatchRequiredNode < Node + # Initialize a new MatchRequiredNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, value, pattern, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchRequiredNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the left-hand side of the operator. + # + # foo => bar + # ^^^ + sig { returns(Node) } + def value; end + + # Represents the right-hand side of the operator. The type of the node depends on the expression. + # + # Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`. + # + # foo => a # This is equivalent to writing `a = foo` + # ^ + # + # Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant. + # + # foo => [a] + # ^^^ + # + # foo => a, b + # ^^^^ + # + # foo => Bar[a, b] + # ^^^^^^^^^ + # + # If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead. + # + # foo => *, 1, *a + # ^^^^^ + # + # Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`. + # + # foo => { a: 1, b: } + # + # foo => Bar[a: 1, b:] + # + # foo => Bar[**] + # + # To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode` + # + # foo => ^a + # ^^ + # + # Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`. + # + # foo => ^(a + 1) + # + # Anything else will result in the regular node for that expression, for example a `ConstantReadNode`. + # + # foo => CONST + sig { returns(Node) } + def pattern; end + + # The Location of the operator. + # + # foo => bar + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents writing local variables using a regular expression match with named capture groups. + # + # /(?bar)/ =~ baz + # ^^^^^^^^^^^^^^^^^^^^ + class MatchWriteNode < Node + # Initialize a new MatchWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).void } + def initialize(source, node_id, location, flags, call, targets); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).returns(MatchWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), call: T.unsafe(nil), targets: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `call` attribute. + sig { returns(CallNode) } + def call; end + + # Returns the `targets` attribute. + sig { returns(T::Array[LocalVariableTargetNode]) } + def targets; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a node that is missing from the source and results in a syntax error. + class MissingNode < Node + # Initialize a new MissingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(MissingNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a module declaration involving the `module` keyword. + # + # module Foo end + # ^^^^^^^^^^^^^^ + class ModuleNode < Node + # Initialize a new ModuleNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } + def initialize(source, node_id, location, flags, locals, module_keyword_loc, constant_path, body, end_keyword_loc, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), module_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `module_keyword_loc`. + sig { returns(Location) } + def module_keyword_loc; end + + # Save the module_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_module_keyword_loc(repository); end + + # Returns the `constant_path` attribute. + sig { returns(T.any(ConstantReadNode, ConstantPathNode, MissingNode)) } + def constant_path; end + + # Returns the `body` attribute. + sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + def body; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Slice the location of module_keyword_loc from the source. + sig { returns(String) } + def module_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a multi-target expression. + # + # a, (b, c) = 1, 2, 3 + # ^^^^^^ + # + # This can be a part of `MultiWriteNode` as above, or the target of a `for` loop + # + # for a, b in [[1, 2], [3, 4]] + # ^^^^ + class MultiTargetNode < Node + # Initialize a new MultiTargetNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location)).returns(MultiTargetNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the targets expressions before a splat node. + # + # a, (b, c, *) = 1, 2, 3, 4, 5 + # ^^^^ + # + # The splat node can be absent, in that case all target expressions are in the left field. + # + # a, (b, c) = 1, 2, 3, 4, 5 + # ^^^^ + sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def lefts; end + + # Represents a splat node in the target expression. + # + # a, (b, *c) = 1, 2, 3, 4 + # ^^ + # + # The variable can be empty, this results in a `SplatNode` with a `nil` expression field. + # + # a, (b, *) = 1, 2, 3, 4 + # ^ + # + # If the `*` is omitted, this field will contain an `ImplicitRestNode` + # + # a, (b,) = 1, 2, 3, 4 + # ^ + sig { returns(T.nilable(T.any(ImplicitRestNode, SplatNode))) } + def rest; end + + # Represents the targets expressions after a splat node. + # + # a, (*, b, c) = 1, 2, 3, 4, 5 + # ^^^^ + sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def rights; end + + # The Location of the opening parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + sig { returns(T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # The Location of the closing parenthesis. + # + # a, (b, c) = 1, 2, 3 + # ^ + sig { returns(T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Slice the location of lparen_loc from the source. + sig { returns(T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(T.nilable(String)) } + def rparen; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a write to a multi-target expression. + # + # a, b, c = 1, 2, 3 + # ^^^^^^^^^^^^^^^^^ + class MultiWriteNode < Node + # Initialize a new MultiWriteNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the targets expressions before a splat node. + # + # a, b, * = 1, 2, 3, 4, 5 + # ^^^^ + # + # The splat node can be absent, in that case all target expressions are in the left field. + # + # a, b, c = 1, 2, 3, 4, 5 + # ^^^^^^^ + sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def lefts; end + + # Represents a splat node in the target expression. + # + # a, b, *c = 1, 2, 3, 4 + # ^^ + # + # The variable can be empty, this results in a `SplatNode` with a `nil` expression field. + # + # a, b, * = 1, 2, 3, 4 + # ^ + # + # If the `*` is omitted, this field will contain an `ImplicitRestNode` + # + # a, b, = 1, 2, 3, 4 + # ^ + sig { returns(T.nilable(T.any(ImplicitRestNode, SplatNode))) } + def rest; end + + # Represents the targets expressions after a splat node. + # + # a, *, b, c = 1, 2, 3, 4, 5 + # ^^^^ + sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + def rights; end + + # The Location of the opening parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + sig { returns(T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # The Location of the closing parenthesis. + # + # (a, b, c) = 1, 2, 3 + # ^ + sig { returns(T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # The Location of the operator. + # + # a, b, c = 1, 2, 3 + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # The value to write to the targets. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # a, b, c = 1, 2, 3 + # ^^^^^^^ + sig { returns(Node) } + def value; end + + # Slice the location of lparen_loc from the source. + sig { returns(T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(T.nilable(String)) } + def rparen; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `next` keyword. + # + # next 1 + # ^^^^^^ + class NextNode < Node + # Initialize a new NextNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).void } + def initialize(source, node_id, location, flags, arguments, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `arguments` attribute. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `nil` keyword. + # + # nil + # ^^^ + class NilNode < Node + # Initialize a new NilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(NilNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of `&nil` inside method arguments. + # + # def a(&nil) + # ^^^^ + # end + class NoBlockParameterNode < Node + # Initialize a new NoBlockParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).void } + def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoBlockParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of `**nil` inside method arguments. + # + # def a(**nil) + # ^^^^^ + # end + class NoKeywordsParameterNode < Node + # Initialize a new NoKeywordsParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).void } + def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoKeywordsParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an implicit set of parameters through the use of numbered parameters within a block or lambda. + # + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + class NumberedParametersNode < Node + # Initialize a new NumberedParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, maximum: Integer).void } + def initialize(source, node_id, location, flags, maximum); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, maximum: Integer).returns(NumberedParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), maximum: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `maximum` attribute. + sig { returns(Integer) } + def maximum; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents reading a numbered reference to a capture in the previous match. + # + # $1 + # ^^ + class NumberedReferenceReadNode < Node + # Initialize a new NumberedReferenceReadNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, number: Integer).void } + def initialize(source, node_id, location, flags, number); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, number: Integer).returns(NumberedReferenceReadNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), number: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The (1-indexed, from the left) number of the capture group. Numbered references that are too large result in this value being `0`. + # + # $1 # number `1` + # + # $5432 # number `5432` + # + # $4294967296 # number `0` + sig { returns(Integer) } + def number; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an optional keyword parameter to a method, block, or lambda definition. + # + # def a(b: 1) + # ^^^^ + # end + class OptionalKeywordParameterNode < Node + # Initialize a new OptionalKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).returns(OptionalKeywordParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an optional parameter to a method, block, or lambda definition. + # + # def a(b = 1) + # ^^^^^ + # end + class OptionalParameterNode < Node + # Initialize a new OptionalParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(OptionalParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `value` attribute. + sig { returns(Node) } + def value; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `||` operator or the `or` keyword. + # + # left or right + # ^^^^^^^^^^^^^ + class OrNode < Node + # Initialize a new OrNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(OrNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # left or right + # ^^^^ + # + # 1 || 2 + # ^ + sig { returns(Node) } + def left; end + + # Represents the right side of the expression. + # + # left || right + # ^^^^^ + # + # 1 or 2 + # ^ + sig { returns(Node) } + def right; end + + # The Location of the `or` keyword or the `||` operator. + # + # left or right + # ^^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the list of parameters on a method, block, or lambda definition. + # + # def a(b, c, d) + # ^^^^^^^ + # end + class ParametersNode < Node + # Initialize a new ParametersNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: T.nilable(T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))).void } + def initialize(source, node_id, location, flags, requireds, optionals, rest, posts, keywords, keyword_rest, block); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, requireds: T::Array[T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: T.nilable(T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), requireds: T.unsafe(nil), optionals: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), keywords: T.unsafe(nil), keyword_rest: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `requireds` attribute. + sig { returns(T::Array[T.any(RequiredParameterNode, MultiTargetNode)]) } + def requireds; end + + # Returns the `optionals` attribute. + sig { returns(T::Array[OptionalParameterNode]) } + def optionals; end + + # Returns the `rest` attribute. + sig { returns(T.nilable(T.any(RestParameterNode, ImplicitRestNode))) } + def rest; end + + # Returns the `posts` attribute. + sig { returns(T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)]) } + def posts; end + + # Returns the `keywords` attribute. + sig { returns(T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)]) } + def keywords; end + + # Returns the `keyword_rest` attribute. + sig { returns(T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode))) } + def keyword_rest; end + + # Returns the `block` attribute. + sig { returns(T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))) } + def block; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a parenthesized expression + # + # (10 + 34) + # ^^^^^^^^^ + class ParenthesesNode < Node + # Initialize a new ParenthesesNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T.nilable(Node), opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, body, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, body: T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # parentheses that contain multiple potentially void statements + sig { returns(T::Boolean) } + def multiple_statements?; end + + # Returns the `body` attribute. + sig { returns(T.nilable(Node)) } + def body; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `^` operator for pinning an expression in a pattern matching expression. + # + # foo in ^(bar) + # ^^^^^^ + class PinnedExpressionNode < Node + # Initialize a new PinnedExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).void } + def initialize(source, node_id, location, flags, expression, operator_loc, lparen_loc, rparen_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).returns(PinnedExpressionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The expression used in the pinned expression + # + # foo in ^(bar) + # ^^^ + sig { returns(Node) } + def expression; end + + # The Location of the `^` operator + # + # foo in ^(bar) + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # The Location of the opening parenthesis. + # + # foo in ^(bar) + # ^ + sig { returns(Location) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_lparen_loc(repository); end + + # The Location of the closing parenthesis. + # + # foo in ^(bar) + # ^ + sig { returns(Location) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_rparen_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of lparen_loc from the source. + sig { returns(String) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(String) } + def rparen; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `^` operator for pinning a variable in a pattern matching expression. + # + # foo in ^bar + # ^^^^ + class PinnedVariableNode < Node + # Initialize a new PinnedVariableNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).void } + def initialize(source, node_id, location, flags, variable, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, variable: T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), variable: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The variable used in the pinned expression + # + # foo in ^bar + # ^^^ + sig { returns(T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode)) } + def variable; end + + # The Location of the `^` operator + # + # foo in ^bar + # ^ + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `END` keyword. + # + # END { foo } + # ^^^^^^^^^^^ + class PostExecutionNode < Node + # Initialize a new PostExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `BEGIN` keyword. + # + # BEGIN { foo } + # ^^^^^^^^^^^^^ + class PreExecutionNode < Node + # Initialize a new PreExecutionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } + def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # The top level node of any parse tree. + class ProgramNode < Node + # Initialize a new ProgramNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).void } + def initialize(source, node_id, location, flags, locals, statements); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).returns(ProgramNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the `statements` attribute. + sig { returns(StatementsNode) } + def statements; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `..` or `...` operators. + # + # 1..2 + # ^^^^ + # + # c if a =~ /left/ ... b =~ /right/ + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + class RangeNode < Node + # Initialize a new RangeNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).void } + def initialize(source, node_id, location, flags, left, right, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(RangeNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # ... operator + sig { returns(T::Boolean) } + def exclude_end?; end + + # The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # 1... + # ^ + # + # hello...goodbye + # ^^^^^ + sig { returns(T.nilable(Node)) } + def left; end + + # The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # ..5 + # ^ + # + # 1...foo + # ^^^ + # If neither right-hand or left-hand side was included, this will be a MissingNode. + sig { returns(T.nilable(Node)) } + def right; end + + # The Location of the `..` or `...` operator. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a rational number literal. + # + # 1.0r + # ^^^^ + class RationalNode < Node + # Initialize a new RationalNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).void } + def initialize(source, node_id, location, flags, numerator, denominator); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).returns(RationalNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numerator: T.unsafe(nil), denominator: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # 0b prefix + sig { returns(T::Boolean) } + def binary?; end + + # 0d or no prefix + sig { returns(T::Boolean) } + def decimal?; end + + # 0o or 0 prefix + sig { returns(T::Boolean) } + def octal?; end + + # 0x prefix + sig { returns(T::Boolean) } + def hexadecimal?; end + + # The numerator of the rational number. + # + # 1.5r # numerator 3 + sig { returns(Integer) } + def numerator; end + + # The denominator of the rational number. + # + # 1.5r # denominator 2 + sig { returns(Integer) } + def denominator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `redo` keyword. + # + # redo + # ^^^^ + class RedoNode < Node + # Initialize a new RedoNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(RedoNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a regular expression literal with no interpolation. + # + # /foo/i + # ^^^^^^ + class RegularExpressionNode < Node + # Initialize a new RegularExpressionNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(RegularExpressionNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # i - ignores the case of characters when matching + sig { returns(T::Boolean) } + def ignore_case?; end + + # x - ignores whitespace and allows comments in regular expressions + sig { returns(T::Boolean) } + def extended?; end + + # m - allows $ to match the end of lines within strings + sig { returns(T::Boolean) } + def multi_line?; end + + # o - only interpolates values into the regular expression once + sig { returns(T::Boolean) } + def once?; end + + # e - forces the EUC-JP encoding + sig { returns(T::Boolean) } + def euc_jp?; end + + # n - forces the ASCII-8BIT encoding + sig { returns(T::Boolean) } + def ascii_8bit?; end + + # s - forces the Windows-31J encoding + sig { returns(T::Boolean) } + def windows_31j?; end + + # u - forces the UTF-8 encoding + sig { returns(T::Boolean) } + def utf_8?; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a required keyword parameter to a method, block, or lambda definition. + # + # def a(b: ) + # ^^ + # end + class RequiredKeywordParameterNode < Node + # Initialize a new RequiredKeywordParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).returns(RequiredKeywordParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(Location) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_name_loc(repository); end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a required parameter to a method, block, or lambda definition. + # + # def a(b) + # ^ + # end + class RequiredParameterNode < Node + # Initialize a new RequiredParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol).void } + def initialize(source, node_id, location, flags, name); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(RequiredParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(Symbol) } + def name; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an expression modified with a rescue. + # + # foo rescue nil + # ^^^^^^^^^^^^^^ + class RescueModifierNode < Node + # Initialize a new RescueModifierNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).void } + def initialize(source, node_id, location, flags, expression, keyword_loc, rescue_expression); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).returns(RescueModifierNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), keyword_loc: T.unsafe(nil), rescue_expression: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `expression` attribute. + sig { returns(Node) } + def expression; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `rescue_expression` attribute. + sig { returns(Node) } + def rescue_expression; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a rescue statement. + # + # begin + # rescue Foo, *splat, Bar => ex + # foo + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + # end + # + # `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field. + class RescueNode < Node + # Initialize a new RescueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: T.nilable(Location), reference: T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(RescueNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, then_keyword_loc, statements, subsequent); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: T.nilable(Location), reference: T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(RescueNode)).returns(RescueNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), exceptions: T.unsafe(nil), operator_loc: T.unsafe(nil), reference: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `exceptions` attribute. + sig { returns(T::Array[Node]) } + def exceptions; end + + # Returns the Location represented by `operator_loc`. + sig { returns(T.nilable(Location)) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_operator_loc(repository); end + + # Returns the `reference` attribute. + sig { returns(T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode))) } + def reference; end + + # Returns the Location represented by `then_keyword_loc`. + sig { returns(T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Returns the `subsequent` attribute. + sig { returns(T.nilable(RescueNode)) } + def subsequent; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of operator_loc from the source. + sig { returns(T.nilable(String)) } + def operator; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def then_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a rest parameter to a method, block, or lambda definition. + # + # def a(*b) + # ^^ + # end + class RestParameterNode < Node + # Initialize a new RestParameterNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).void } + def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a parameter name that has been repeated in the method signature + sig { returns(T::Boolean) } + def repeated_parameter?; end + + # Returns the `name` attribute. + sig { returns(T.nilable(Symbol)) } + def name; end + + # Returns the Location represented by `name_loc`. + sig { returns(T.nilable(Location)) } + def name_loc; end + + # Save the name_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_name_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `retry` keyword. + # + # retry + # ^^^^^ + class RetryNode < Node + # Initialize a new RetryNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(RetryNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `return` keyword. + # + # return 1 + # ^^^^^^^^ + class ReturnNode < Node + # Initialize a new ReturnNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: T.nilable(ArgumentsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, arguments); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: T.nilable(ArgumentsNode)).returns(ReturnNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), arguments: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the `self` keyword. + # + # self + # ^^^^ + class SelfNode < Node + # Initialize a new SelfNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(SelfNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # This node wraps a constant write to indicate that when the value is written, it should have its shareability state modified. + # + # # shareable_constant_value: literal + # C = { a: 1 } + # ^^^^^^^^^^^^ + class ShareableConstantNode < Node + # Initialize a new ShareableConstantNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).void } + def initialize(source, node_id, location, flags, write); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, write: T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), write: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # constant writes that should be modified with shareable constant value literal + sig { returns(T::Boolean) } + def literal?; end + + # constant writes that should be modified with shareable constant value experimental everything + sig { returns(T::Boolean) } + def experimental_everything?; end + + # constant writes that should be modified with shareable constant value experimental copy + sig { returns(T::Boolean) } + def experimental_copy?; end + + # The constant write that should be modified with the shareability state. + sig { returns(T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)) } + def write; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a singleton class declaration involving the `class` keyword. + # + # class << self end + # ^^^^^^^^^^^^^^^^^ + class SingletonClassNode < Node + # Initialize a new SingletonClassNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).void } + def initialize(source, node_id, location, flags, locals, class_keyword_loc, operator_loc, expression, body, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `locals` attribute. + sig { returns(T::Array[Symbol]) } + def locals; end + + # Returns the Location represented by `class_keyword_loc`. + sig { returns(Location) } + def class_keyword_loc; end + + # Save the class_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_class_keyword_loc(repository); end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `expression` attribute. + sig { returns(Node) } + def expression; end + + # Returns the `body` attribute. + sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + def body; end + + # Returns the Location represented by `end_keyword_loc`. + sig { returns(Location) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_end_keyword_loc(repository); end + + # Slice the location of class_keyword_loc from the source. + sig { returns(String) } + def class_keyword; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(String) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `__ENCODING__` keyword. + # + # __ENCODING__ + # ^^^^^^^^^^^^ + class SourceEncodingNode < Node + # Initialize a new SourceEncodingNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceEncodingNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `__FILE__` keyword. + # + # __FILE__ + # ^^^^^^^^ + class SourceFileNode < Node + # Initialize a new SourceFileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, filepath: String).void } + def initialize(source, node_id, location, flags, filepath); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, filepath: String).returns(SourceFileNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), filepath: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + sig { returns(T::Boolean) } + def frozen?; end + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + sig { returns(T::Boolean) } + def mutable?; end + + # Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism.parse*` APIs. + sig { returns(String) } + def filepath; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `__LINE__` keyword. + # + # __LINE__ + # ^^^^^^^^ + class SourceLineNode < Node + # Initialize a new SourceLineNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceLineNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the splat operator. + # + # [*a] + # ^^ + class SplatNode < Node + # Initialize a new SplatNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: T.nilable(Node)).void } + def initialize(source, node_id, location, flags, operator_loc, expression); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: T.nilable(Node)).returns(SplatNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `operator_loc`. + sig { returns(Location) } + def operator_loc; end + + # Save the operator_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_operator_loc(repository); end + + # Returns the `expression` attribute. + sig { returns(T.nilable(Node)) } + def expression; end + + # Slice the location of operator_loc from the source. + sig { returns(String) } + def operator; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a set of statements contained within some scope. + # + # foo; bar; baz + # ^^^^^^^^^^^^^ + class StatementsNode < Node + # Initialize a new StatementsNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).void } + def initialize(source, node_id, location, flags, body); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).returns(StatementsNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `body` attribute. + sig { returns(T::Array[Node]) } + def body; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string. + # + # "foo" + # ^^^^^ + # + # %w[foo] + # ^^^ + # + # "foo #{bar} baz" + # ^^^^ ^^^^ + class StringNode < Node + # Initialize a new StringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), content_loc: Location, closing_loc: T.nilable(Location), unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), content_loc: Location, closing_loc: T.nilable(Location), unescaped: String).returns(StringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + sig { returns(T::Boolean) } + def frozen?; end + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + sig { returns(T::Boolean) } + def mutable?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `super` keyword with parentheses or arguments. + # + # super() + # ^^^^^^^ + # + # super foo, bar + # ^^^^^^^^^^^^^^ + # + # If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead. + class SuperNode < Node + # Initialize a new SuperNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).void } + def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc, block); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil), block: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `lparen_loc`. + sig { returns(T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Can be only `nil` when there are empty parentheses, like `super()`. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `rparen_loc`. + sig { returns(T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Returns the `block` attribute. + sig { returns(T.nilable(T.any(BlockNode, BlockArgumentNode))) } + def block; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of lparen_loc from the source. + sig { returns(T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(T.nilable(String)) } + def rparen; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents a symbol literal or a symbol contained within a `%i` list. + # + # :foo + # ^^^^ + # + # %i[foo] + # ^^^ + class SymbolNode < Node + # Initialize a new SymbolNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), value_loc: T.nilable(Location), closing_loc: T.nilable(Location), unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, value_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), value_loc: T.nilable(Location), closing_loc: T.nilable(Location), unescaped: String).returns(SymbolNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), value_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # internal bytes forced the encoding to US-ASCII + sig { returns(T::Boolean) } + def forced_us_ascii_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(T.nilable(Location)) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_opening_loc(repository); end + + # Returns the Location represented by `value_loc`. + sig { returns(T.nilable(Location)) } + def value_loc; end + + # Save the value_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_value_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(T.nilable(String)) } + def opening; end + + # Slice the location of value_loc from the source. + sig { returns(T.nilable(String)) } + def value; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the literal `true` keyword. + # + # true + # ^^^^ + class TrueNode < Node + # Initialize a new TrueNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer).void } + def initialize(source, node_id, location, flags); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer).returns(TrueNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `undef` keyword. + # + # undef :foo, :bar, :baz + # ^^^^^^^^^^^^^^^^^^^^^^ + class UndefNode < Node + # Initialize a new UndefNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).void } + def initialize(source, node_id, location, flags, names, keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, names: T::Array[T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), names: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the `names` attribute. + sig { returns(T::Array[T.any(SymbolNode, InterpolatedSymbolNode)]) } + def names; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `unless` keyword, either in the block form or the modifier form. + # + # bar unless foo + # ^^^^^^^^^^^^^^ + # + # unless foo then bar end + # ^^^^^^^^^^^^^^^^^^^^^^^ + class UnlessNode < Node + # Initialize a new UnlessNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), else_clause: T.nilable(ElseNode), end_keyword_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, keyword_loc, predicate, then_keyword_loc, statements, else_clause, end_keyword_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), else_clause: T.nilable(ElseNode), end_keyword_loc: T.nilable(Location)).returns(UnlessNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), else_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # The Location of the `unless` keyword. + # + # unless cond then bar end + # ^^^^^^ + # + # bar unless cond + # ^^^^^^ + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # The condition to be evaluated for the unless expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). + # + # unless cond then bar end + # ^^^^ + # + # bar unless cond + # ^^^^ + sig { returns(Node) } + def predicate; end + + # The Location of the `then` keyword, if present. + # + # unless cond then bar end + # ^^^^ + sig { returns(T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # The body of statements that will executed if the unless condition is + # falsey. Will be `nil` if no body is provided. + # + # unless cond then bar end + # ^^^ + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # The else clause of the unless expression, if present. + # + # unless cond then bar else baz end + # ^^^^^^^^ + sig { returns(T.nilable(ElseNode)) } + def else_clause; end + + # The Location of the `end` keyword, if present. + # + # unless cond then bar end + # ^^^ + sig { returns(T.nilable(Location)) } + def end_keyword_loc; end + + # Save the end_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_end_keyword_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def then_keyword; end + + # Slice the location of end_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def end_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `until` keyword, either in the block form or the modifier form. + # + # bar until foo + # ^^^^^^^^^^^^^ + # + # until foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class UntilNode < Node + # Initialize a new UntilNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(UntilNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a loop after a begin statement, so the body is executed first before the condition + sig { returns(T::Boolean) } + def begin_modifier?; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `do_keyword_loc`. + sig { returns(T.nilable(Location)) } + def do_keyword_loc; end + + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_do_keyword_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `predicate` attribute. + sig { returns(Node) } + def predicate; end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of do_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def do_keyword; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `when` keyword within a case statement. + # + # case true + # when true + # ^^^^^^^^^ + # end + class WhenNode < Node + # Initialize a new WhenNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, conditions, then_keyword_loc, statements); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode)).returns(WhenNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), conditions: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the `conditions` attribute. + sig { returns(T::Array[Node]) } + def conditions; end + + # Returns the Location represented by `then_keyword_loc`. + sig { returns(T.nilable(Location)) } + def then_keyword_loc; end + + # Save the then_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_then_keyword_loc(repository); end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of then_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def then_keyword; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `while` keyword, either in the block form or the modifier form. + # + # bar while foo + # ^^^^^^^^^^^^^ + # + # while foo do bar end + # ^^^^^^^^^^^^^^^^^^^^ + class WhileNode < Node + # Initialize a new WhileNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).void } + def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(WhileNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # a loop after a begin statement, so the body is executed first before the condition + sig { returns(T::Boolean) } + def begin_modifier?; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `do_keyword_loc`. + sig { returns(T.nilable(Location)) } + def do_keyword_loc; end + + # Save the do_keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_do_keyword_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(T.nilable(Location)) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_closing_loc(repository); end + + # Returns the `predicate` attribute. + sig { returns(Node) } + def predicate; end + + # Returns the `statements` attribute. + sig { returns(T.nilable(StatementsNode)) } + def statements; end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of do_keyword_loc from the source. + sig { returns(T.nilable(String)) } + def do_keyword; end + + # Slice the location of closing_loc from the source. + sig { returns(T.nilable(String)) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents an xstring literal with no interpolation. + # + # `foo` + # ^^^^^ + class XStringNode < Node + # Initialize a new XStringNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).void } + def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(XStringNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # internal bytes forced the encoding to UTF-8 + sig { returns(T::Boolean) } + def forced_utf8_encoding?; end + + # internal bytes forced the encoding to binary + sig { returns(T::Boolean) } + def forced_binary_encoding?; end + + # Returns the Location represented by `opening_loc`. + sig { returns(Location) } + def opening_loc; end + + # Save the opening_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_opening_loc(repository); end + + # Returns the Location represented by `content_loc`. + sig { returns(Location) } + def content_loc; end + + # Save the content_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_content_loc(repository); end + + # Returns the Location represented by `closing_loc`. + sig { returns(Location) } + def closing_loc; end + + # Save the closing_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_closing_loc(repository); end + + # Returns the `unescaped` attribute. + sig { returns(String) } + def unescaped; end + + # Slice the location of opening_loc from the source. + sig { returns(String) } + def opening; end + + # Slice the location of content_loc from the source. + sig { returns(String) } + def content; end + + # Slice the location of closing_loc from the source. + sig { returns(String) } + def closing; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Represents the use of the `yield` keyword. + # + # yield 1 + # ^^^^^^^ + class YieldNode < Node + # Initialize a new YieldNode node. + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location)).void } + def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc); end + + # See Node.accept. + sig { override.params(visitor: T.untyped).returns(T.untyped) } + def accept(visitor); end + + # See Node.child_nodes. + sig { override.returns(T::Array[T.nilable(Node)]) } + def child_nodes; end + + # See Node.each_child_node. + sig { override.returns(T::Enumerator[Node]) } + sig { override.params(blk: T.proc.params(arg0: Node).void).void } + def each_child_node(&blk); end + + # See Node.compact_child_nodes. + sig { override.returns(T::Array[Node]) } + def compact_child_nodes; end + + # See Node.comment_targets. + sig { override.returns(T::Array[T.any(Node, Location)]) } + def comment_targets; end + + # Creates a copy of self with the given fields, using self as the template. + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location)).returns(YieldNode) } + def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # See `Node#type`. + sig { override.returns(Symbol) } + def type; end + + # See `Node.type`. + sig { override.returns(Symbol) } + def self.type; end + + sig { override.returns(String) } + def inspect; end + + # Returns the Location represented by `keyword_loc`. + sig { returns(Location) } + def keyword_loc; end + + # Save the keyword_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(Relocation::Entry) } + def save_keyword_loc(repository); end + + # Returns the Location represented by `lparen_loc`. + sig { returns(T.nilable(Location)) } + def lparen_loc; end + + # Save the lparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_lparen_loc(repository); end + + # Returns the `arguments` attribute. + sig { returns(T.nilable(ArgumentsNode)) } + def arguments; end + + # Returns the Location represented by `rparen_loc`. + sig { returns(T.nilable(Location)) } + def rparen_loc; end + + # Save the rparen_loc location using the given saved source so that + # it can be retrieved later. + sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + def save_rparen_loc(repository); end + + # Slice the location of keyword_loc from the source. + sig { returns(String) } + def keyword; end + + # Slice the location of lparen_loc from the source. + sig { returns(T.nilable(String)) } + def lparen; end + + # Slice the location of rparen_loc from the source. + sig { returns(T.nilable(String)) } + def rparen; end + + sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + def ===(other); end + end + + # Flags for arguments nodes. + module ArgumentsNodeFlags + # if the arguments contain forwarding + CONTAINS_FORWARDING = T.let(nil, T.untyped) + + # if the arguments contain keywords + CONTAINS_KEYWORDS = T.let(nil, T.untyped) + + # if the arguments contain a keyword splat + CONTAINS_KEYWORD_SPLAT = T.let(nil, T.untyped) + + # if the arguments contain a splat + CONTAINS_SPLAT = T.let(nil, T.untyped) + + # if the arguments contain multiple splats + CONTAINS_MULTIPLE_SPLATS = T.let(nil, T.untyped) + end + + # Flags for array nodes. + module ArrayNodeFlags + # if array contains splat nodes + CONTAINS_SPLAT = T.let(nil, T.untyped) + end + + # Flags for call nodes. + module CallNodeFlags + # &. operator + SAFE_NAVIGATION = T.let(nil, T.untyped) + + # a call that could have been a local variable + VARIABLE_CALL = T.let(nil, T.untyped) + + # a call that is an attribute write, so the value being written should be returned + ATTRIBUTE_WRITE = T.let(nil, T.untyped) + + # a call that ignores method visibility + IGNORE_VISIBILITY = T.let(nil, T.untyped) + end + + # Flags for nodes that have unescaped content. + module EncodingFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + end + + # Flags for integer nodes that correspond to the base of the integer. + module IntegerBaseFlags + # 0b prefix + BINARY = T.let(nil, T.untyped) + + # 0d or no prefix + DECIMAL = T.let(nil, T.untyped) + + # 0o or 0 prefix + OCTAL = T.let(nil, T.untyped) + + # 0x prefix + HEXADECIMAL = T.let(nil, T.untyped) + end + + # Flags for interpolated string nodes that indicated mutability if they are also marked as literals. + module InterpolatedStringNodeFlags + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + FROZEN = T.let(nil, T.untyped) + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + MUTABLE = T.let(nil, T.untyped) + end + + # Flags for keyword hash nodes. + module KeywordHashNodeFlags + # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + SYMBOL_KEYS = T.let(nil, T.untyped) + end + + # Flags for while and until loop nodes. + module LoopFlags + # a loop after a begin statement, so the body is executed first before the condition + BEGIN_MODIFIER = T.let(nil, T.untyped) + end + + # Flags for parameter nodes. + module ParameterFlags + # a parameter name that has been repeated in the method signature + REPEATED_PARAMETER = T.let(nil, T.untyped) + end + + # Flags for parentheses nodes. + module ParenthesesNodeFlags + # parentheses that contain multiple potentially void statements + MULTIPLE_STATEMENTS = T.let(nil, T.untyped) + end + + # Flags for range and flip-flop nodes. + module RangeFlags + # ... operator + EXCLUDE_END = T.let(nil, T.untyped) + end + + # Flags for regular expression and match last line nodes. + module RegularExpressionFlags + # i - ignores the case of characters when matching + IGNORE_CASE = T.let(nil, T.untyped) + + # x - ignores whitespace and allows comments in regular expressions + EXTENDED = T.let(nil, T.untyped) + + # m - allows $ to match the end of lines within strings + MULTI_LINE = T.let(nil, T.untyped) + + # o - only interpolates values into the regular expression once + ONCE = T.let(nil, T.untyped) + + # e - forces the EUC-JP encoding + EUC_JP = T.let(nil, T.untyped) + + # n - forces the ASCII-8BIT encoding + ASCII_8BIT = T.let(nil, T.untyped) + + # s - forces the Windows-31J encoding + WINDOWS_31J = T.let(nil, T.untyped) + + # u - forces the UTF-8 encoding + UTF_8 = T.let(nil, T.untyped) + + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING = T.let(nil, T.untyped) + end + + # Flags for shareable constant nodes. + module ShareableConstantNodeFlags + # constant writes that should be modified with shareable constant value literal + LITERAL = T.let(nil, T.untyped) + + # constant writes that should be modified with shareable constant value experimental everything + EXPERIMENTAL_EVERYTHING = T.let(nil, T.untyped) + + # constant writes that should be modified with shareable constant value experimental copy + EXPERIMENTAL_COPY = T.let(nil, T.untyped) + end + + # Flags for string nodes. + module StringFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + + # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + FROZEN = T.let(nil, T.untyped) + + # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + MUTABLE = T.let(nil, T.untyped) + end + + # Flags for symbol nodes. + module SymbolFlags + # internal bytes forced the encoding to UTF-8 + FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + + # internal bytes forced the encoding to binary + FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + + # internal bytes forced the encoding to US-ASCII + FORCED_US_ASCII_ENCODING = T.let(nil, T.untyped) + end + + # The flags that are common to all nodes. + module NodeFlags + # A flag to indicate that the node is a candidate to emit a :line event + # through tracepoint when compiled. + NEWLINE = T.let(nil, Integer) + + # A flag to indicate that the value that the node represents is a value that + # can be determined at parse-time. + STATIC_LITERAL = T.let(nil, Integer) + end +end diff --git a/rbi/generated/prism/node_ext.rbi b/rbi/generated/prism/node_ext.rbi new file mode 100644 index 0000000000..925fd8dd7a --- /dev/null +++ b/rbi/generated/prism/node_ext.rbi @@ -0,0 +1,333 @@ +# typed: true + +module Prism + class Node + abstract! + + sig { params(replacements: String).void } + def deprecated(*replacements); end + end + + module RegularExpressionOptions + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { params(flags: Integer).returns(Integer) } + def self.options(flags); end + end + + class InterpolatedMatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + class InterpolatedRegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + class MatchLastLineNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + class RegularExpressionNode < Node + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + sig { returns(Integer) } + def options; end + end + + module HeredocQuery + # Returns true if this node was represented as a heredoc in the source code. + sig { params(opening: T.nilable(String)).returns(T.nilable(T::Boolean)) } + def self.heredoc?(opening); end + end + + class InterpolatedStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(T.nilable(T::Boolean)) } + def heredoc?; end + end + + class InterpolatedXStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(T.nilable(T::Boolean)) } + def heredoc?; end + end + + class StringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(T.nilable(T::Boolean)) } + def heredoc?; end + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + sig { returns(InterpolatedStringNode) } + def to_interpolated; end + end + + class XStringNode < Node + # Returns true if this node was represented as a heredoc in the source code. + sig { returns(T.nilable(T::Boolean)) } + def heredoc?; end + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + sig { returns(InterpolatedXStringNode) } + def to_interpolated; end + end + + class ImaginaryNode < Node + # Returns the value of the node as a Ruby Complex. + sig { returns(Complex) } + def value; end + end + + class RationalNode < Node + # Returns the value of the node as a Ruby Rational. + sig { returns(Rational) } + def value; end + + # Returns the value of the node as an IntegerNode or a FloatNode. This + # method is deprecated in favor of #value or #numerator/#denominator. + sig { returns(T.any(IntegerNode, FloatNode)) } + def numeric; end + end + + class ConstantReadNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant. For example: "Foo" + sig { returns(String) } + def full_name; end + end + + class ConstantWriteNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant. For example: "Foo" + sig { returns(String) } + def full_name; end + end + + class ConstantPathNode < Node + # An error class raised when dynamic parts are found while computing a + # constant path's full name. For example: + # Foo::Bar::Baz -> does not raise because all parts of the constant path are + # simple constants + # var::Bar::Baz -> raises because the first part of the constant path is a + # local variable + class DynamicPartsInConstantPathError < StandardError; end + + # An error class raised when missing nodes are found while computing a + # constant path's full name. For example: + # Foo:: -> raises because the constant path is missing the last part + class MissingNodesInConstantPathError < StandardError; end + + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant path. For example: "Foo::Bar" + sig { returns(String) } + def full_name; end + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + sig { returns(T.any(ConstantReadNode, MissingNode)) } + def child; end + end + + class ConstantPathTargetNode < Node + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant path. For example: "Foo::Bar" + sig { returns(String) } + def full_name; end + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + sig { returns(T.any(ConstantReadNode, MissingNode)) } + def child; end + end + + class ConstantTargetNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + sig { returns(T::Array[Symbol]) } + def full_name_parts; end + + # Returns the full name of this constant. For example: "Foo" + sig { returns(String) } + def full_name; end + end + + class ParametersNode < Node + # Mirrors the Method#parameters method. + sig { returns(T::Array[T.any([Symbol, Symbol], [Symbol])]) } + def signature; end + end + + class CallNode < Node + # When a call node has the attribute_write flag set, it means that the call + # is using the attribute write syntax. This is either a method call to []= + # or a method call to a method that ends with =. Either way, the = sign is + # present in the source. + # + # Prism returns the message_loc _without_ the = sign attached, because there + # can be any amount of space between the message and the = sign. However, + # sometimes you want the location of the full message including the inner + # space and the = sign. This method provides that. + sig { returns(T.nilable(Location)) } + def full_message_loc; end + end + + class CallOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class ClassVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class ConstantOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class ConstantPathOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class GlobalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class IndexOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class InstanceVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class LocalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + sig { returns(Symbol) } + def operator; end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + sig { returns(Location) } + def operator_loc; end + end + + class CaseMatchNode < Node + # Returns the else clause of the case match node. This method is deprecated + # in favor of #else_clause. + sig { returns(T.nilable(ElseNode)) } + def consequent; end + end + + class CaseNode < Node + # Returns the else clause of the case node. This method is deprecated in + # favor of #else_clause. + sig { returns(T.nilable(ElseNode)) } + def consequent; end + end + + class IfNode < Node + # Returns the subsequent if/elsif/else clause of the if node. This method is + # deprecated in favor of #subsequent. + sig { returns(T.nilable(T.any(IfNode, ElseNode))) } + def consequent; end + end + + class RescueNode < Node + # Returns the subsequent rescue clause of the rescue node. This method is + # deprecated in favor of #subsequent. + sig { returns(T.nilable(RescueNode)) } + def consequent; end + end + + class UnlessNode < Node + # Returns the else clause of the unless node. This method is deprecated in + # favor of #else_clause. + sig { returns(T.nilable(ElseNode)) } + def consequent; end + end +end diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi new file mode 100644 index 0000000000..6501e3cfaf --- /dev/null +++ b/rbi/generated/prism/parse_result.rbi @@ -0,0 +1,707 @@ +# typed: true + +module Prism + # This represents a source of Ruby code that has been parsed. It is used in + # conjunction with locations to allow them to resolve line numbers and source + # ranges. + class Source + # Create a new source object with the given source code. This method should + # be used instead of `new` and it will return either a `Source` or a + # specialized and more performant `ASCIISource` if no multibyte characters + # are present in the source code. + sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).returns(Source) } + def self.for(source, start_line = T.unsafe(nil), offsets = T.unsafe(nil)); end + + # The source code that this source object represents. + sig { returns(String) } + attr_reader :source + + # The line number where this source starts. + sig { returns(Integer) } + attr_reader :start_line + + # The list of newline byte offsets in the source code. + sig { returns(T::Array[Integer]) } + attr_reader :offsets + + # Create a new source object with the given source code. + sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).void } + def initialize(source, start_line = T.unsafe(nil), offsets = T.unsafe(nil)); end + + # Replace the value of start_line with the given value. + sig { params(start_line: Integer).void } + def replace_start_line(start_line); end + + # Replace the value of offsets with the given value. + sig { params(offsets: T::Array[Integer]).void } + def replace_offsets(offsets); end + + # Returns the encoding of the source code, which is set by parameters to the + # parser or by the encoding magic comment. + sig { returns(Encoding) } + def encoding; end + + # Returns the lines of the source code as an array of strings. + sig { returns(T::Array[String]) } + def lines; end + + # Perform a byteslice on the source code using the given byte offset and + # byte length. + sig { params(byte_offset: Integer, length: Integer).returns(String) } + def slice(byte_offset, length); end + + # Converts the line number and column in bytes to a byte offset. + sig { params(line: Integer, column: Integer).returns(Integer) } + def byte_offset(line, column); end + + # Binary search through the offsets to find the line number for the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def line(byte_offset); end + + # Return the byte offset of the start of the line corresponding to the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def line_start(byte_offset); end + + # Returns the byte offset of the end of the line corresponding to the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def line_end(byte_offset); end + + # Return the column in bytes for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def column(byte_offset); end + + # Return the character offset for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def character_offset(byte_offset); end + + # Return the column in characters for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def character_column(byte_offset); end + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the + # concept of code units that differs from the number of characters in other + # encodings, it is not captured here. + # + # We purposefully replace invalid and undefined characters with replacement + # characters in this conversion. This happens for two reasons. First, it's + # possible that the given byte offset will not occur on a character + # boundary. Second, it's possible that the source code will contain a + # character that has no equivalent in the given encoding. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_offset(byte_offset, encoding); end + + # Generate a cache that targets a specific encoding for calculating code + # unit offsets. + sig { params(encoding: Encoding).returns(CodeUnitsCache) } + def code_units_cache(encoding); end + + # Returns the column in code units for the given encoding for the + # given byte offset. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_column(byte_offset, encoding); end + + # Freeze this object and the objects it contains. + sig { void } + def deep_freeze; end + + # Binary search through the offsets to find the line number for the given + # byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + private def find_line(byte_offset); end + end + + # A cache that can be used to quickly compute code unit offsets from byte + # offsets. It purposefully provides only a single #[] method to access the + # cache in order to minimize surface area. + # + # Note that there are some known issues here that may or may not be addressed + # in the future: + # + # * The first is that there are issues when the cache computes values that are + # not on character boundaries. This can result in subsequent computations + # being off by one or more code units. + # * The second is that this cache is currently unbounded. In theory we could + # introduce some kind of LRU cache to limit the number of entries, but this + # has not yet been implemented. + class CodeUnitsCache + class UTF16Counter + sig { params(source: String, encoding: Encoding).void } + def initialize(source, encoding); end + + sig { params(byte_offset: Integer, byte_length: Integer).returns(Integer) } + def count(byte_offset, byte_length); end + end + + class LengthCounter + sig { params(source: String, encoding: Encoding).void } + def initialize(source, encoding); end + + sig { params(byte_offset: Integer, byte_length: Integer).returns(Integer) } + def count(byte_offset, byte_length); end + end + + # Initialize a new cache with the given source and encoding. + sig { params(source: String, encoding: Encoding).void } + def initialize(source, encoding); end + + # Retrieve the code units offset from the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def [](byte_offset); end + end + + # Specialized version of Prism::Source for source code that includes ASCII + # characters only. This class is used to apply performance optimizations that + # cannot be applied to sources that include multibyte characters. + # + # In the extremely rare case that a source includes multi-byte characters but + # is marked as binary because of a magic encoding comment and it cannot be + # eagerly converted to UTF-8, this class will be used as well. This is because + # at that point we will treat everything as single-byte characters. + class ASCIISource < Source + # Return the character offset for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def character_offset(byte_offset); end + + # Return the column in characters for the given byte offset. + sig { params(byte_offset: Integer).returns(Integer) } + def character_column(byte_offset); end + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the + # concept of code units that differs from the number of characters in other + # encodings, it is not captured here. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_offset(byte_offset, encoding); end + + # Returns a cache that is the identity function in order to maintain the + # same interface. We can do this because code units are always equivalent to + # byte offsets for ASCII-only sources. + sig { params(encoding: Encoding).returns(T.untyped) } + def code_units_cache(encoding); end + + # Specialized version of `code_units_column` that does not depend on + # `code_units_offset`, which is a more expensive operation. This is + # essentially the same as `Prism::Source#column`. + sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } + def code_units_column(byte_offset, encoding); end + end + + # This represents a location in the source. + class Location + # A Source object that is used to determine more information from the given + # offset and length. + sig { returns(Source) } + attr_reader :source + + # The byte offset from the beginning of the source where this location + # starts. + sig { returns(Integer) } + attr_reader :start_offset + + # The length of this location in bytes. + sig { returns(Integer) } + attr_reader :length + + # Create a new location object with the given source, start byte offset, and + # byte length. + sig { params(source: Source, start_offset: Integer, length: Integer).void } + def initialize(source, start_offset, length); end + + # These are the comments that are associated with this location that exist + # before the start of this location. + sig { returns(T::Array[Comment]) } + def leading_comments; end + + # Attach a comment to the leading comments of this location. + sig { params(comment: Comment).void } + def leading_comment(comment); end + + # These are the comments that are associated with this location that exist + # after the end of this location. + sig { returns(T::Array[Comment]) } + def trailing_comments; end + + # Attach a comment to the trailing comments of this location. + sig { params(comment: Comment).void } + def trailing_comment(comment); end + + # Returns all comments that are associated with this location (both leading + # and trailing comments). + sig { returns(T::Array[Comment]) } + def comments; end + + # Create a new location object with the given options. + sig { params(source: Source, start_offset: Integer, length: Integer).returns(Location) } + def copy(source: T.unsafe(nil), start_offset: T.unsafe(nil), length: T.unsafe(nil)); end + + # Returns a new location that is the result of chopping off the last byte. + sig { returns(Location) } + def chop; end + + # Returns a string representation of this location. + sig { returns(String) } + def inspect; end + + # Returns all of the lines of the source code associated with this location. + sig { returns(T::Array[String]) } + def source_lines; end + + # The source code that this location represents. + sig { returns(String) } + def slice; end + + # The source code that this location represents starting from the beginning + # of the line that this location starts on to the end of the line that this + # location ends on. + sig { returns(String) } + def slice_lines; end + + # The character offset from the beginning of the source where this location + # starts. + sig { returns(Integer) } + def start_character_offset; end + + # The offset from the start of the file in code units of the given encoding. + sig { params(encoding: Encoding).returns(Integer) } + def start_code_units_offset(encoding); end + + # The start offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + sig { params(cache: T.untyped).returns(Integer) } + def cached_start_code_units_offset(cache); end + + # The byte offset from the beginning of the source where this location ends. + sig { returns(Integer) } + def end_offset; end + + # The character offset from the beginning of the source where this location + # ends. + sig { returns(Integer) } + def end_character_offset; end + + # The offset from the start of the file in code units of the given encoding. + sig { params(encoding: Encoding).returns(Integer) } + def end_code_units_offset(encoding); end + + # The end offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + sig { params(cache: T.untyped).returns(Integer) } + def cached_end_code_units_offset(cache); end + + # The line number where this location starts. + sig { returns(Integer) } + def start_line; end + + # The content of the line where this location starts before this location. + sig { returns(String) } + def start_line_slice; end + + # The line number where this location ends. + sig { returns(Integer) } + def end_line; end + + # The column in bytes where this location starts from the start of + # the line. + sig { returns(Integer) } + def start_column; end + + # The column in characters where this location ends from the start of + # the line. + sig { returns(Integer) } + def start_character_column; end + + # The column in code units of the given encoding where this location + # starts from the start of the line. + sig { params(encoding: Encoding).returns(Integer) } + def start_code_units_column(encoding = T.unsafe(nil)); end + + # The start column in code units using the given cache to fetch or calculate + # the value. + sig { params(cache: T.untyped).returns(Integer) } + def cached_start_code_units_column(cache); end + + # The column in bytes where this location ends from the start of the + # line. + sig { returns(Integer) } + def end_column; end + + # The column in characters where this location ends from the start of + # the line. + sig { returns(Integer) } + def end_character_column; end + + # The column in code units of the given encoding where this location + # ends from the start of the line. + sig { params(encoding: Encoding).returns(Integer) } + def end_code_units_column(encoding = T.unsafe(nil)); end + + # The end column in code units using the given cache to fetch or calculate + # the value. + sig { params(cache: T.untyped).returns(Integer) } + def cached_end_code_units_column(cache); end + + # Implement the hash pattern matching interface for Location. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # Implement the pretty print interface for Location. + sig { params(q: PP).void } + def pretty_print(q); end + + # Returns true if the given other location is equal to this location. + sig { params(other: T.untyped).returns(T::Boolean) } + def ==(other); end + + # Returns a new location that stretches from this location to the given + # other location. Raises an error if this location is not before the other + # location or if they don't share the same source. + sig { params(other: Location).returns(Location) } + def join(other); end + + # Join this location with the first occurrence of the string in the source + # that occurs after this location on the same line, and return the new + # location. This will raise an error if the string does not exist. + sig { params(string: String).returns(Location) } + def adjoin(string); end + end + + # This represents a comment that was encountered during parsing. It is the + # base class for all comment types. + class Comment + # The Location of this comment in the source. + sig { returns(Location) } + attr_reader :location + + # Create a new comment object with the given location. + sig { params(location: Location).void } + def initialize(location); end + + # Implement the hash pattern matching interface for Comment. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # Returns the content of the comment by slicing it from the source code. + sig { returns(String) } + def slice; end + + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. This can only be true for inline + # comments and should be false for block comments. + sig { returns(T::Boolean) } + def trailing?; end + end + + # InlineComment objects are the most common. They correspond to comments in + # the source file like this one that start with #. + class InlineComment < Comment + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. + sig { returns(T::Boolean) } + def trailing?; end + + # Returns a string representation of this comment. + sig { returns(String) } + def inspect; end + end + + # EmbDocComment objects correspond to comments that are surrounded by =begin + # and =end. + class EmbDocComment < Comment + # Returns false. This can only be true for inline comments. + sig { returns(T::Boolean) } + def trailing?; end + + # Returns a string representation of this comment. + sig { returns(String) } + def inspect; end + end + + # This represents a magic comment that was encountered during parsing. + class MagicComment + # A Location object representing the location of the key in the source. + sig { returns(Location) } + attr_reader :key_loc + + # A Location object representing the location of the value in the source. + sig { returns(Location) } + attr_reader :value_loc + + # Create a new magic comment object with the given key and value locations. + sig { params(key_loc: Location, value_loc: Location).void } + def initialize(key_loc, value_loc); end + + # Returns the key of the magic comment by slicing it from the source code. + sig { returns(String) } + def key; end + + # Returns the value of the magic comment by slicing it from the source code. + sig { returns(String) } + def value; end + + # Implement the hash pattern matching interface for MagicComment. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # Returns a string representation of this magic comment. + sig { returns(String) } + def inspect; end + end + + # This represents an error that was encountered during parsing. + class ParseError + # The type of error. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + sig { returns(Symbol) } + attr_reader :type + + # The message associated with this error. + sig { returns(String) } + attr_reader :message + + # A Location object representing the location of this error in the source. + sig { returns(Location) } + attr_reader :location + + # The level of this error. + sig { returns(Symbol) } + attr_reader :level + + # Create a new error object with the given message and location. + sig { params(type: Symbol, message: String, location: Location, level: Symbol).void } + def initialize(type, message, location, level); end + + # Implement the hash pattern matching interface for ParseError. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # Returns a string representation of this error. + sig { returns(String) } + def inspect; end + end + + # This represents a warning that was encountered during parsing. + class ParseWarning + # The type of warning. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + sig { returns(Symbol) } + attr_reader :type + + # The message associated with this warning. + sig { returns(String) } + attr_reader :message + + # A Location object representing the location of this warning in the source. + sig { returns(Location) } + attr_reader :location + + # The level of this warning. + sig { returns(Symbol) } + attr_reader :level + + # Create a new warning object with the given message and location. + sig { params(type: Symbol, message: String, location: Location, level: Symbol).void } + def initialize(type, message, location, level); end + + # Implement the hash pattern matching interface for ParseWarning. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # Returns a string representation of this warning. + sig { returns(String) } + def inspect; end + end + + # This represents the result of a call to Prism.parse or Prism.parse_file. + # It contains the requested structure, any comments that were encounters, + # and any errors that were encountered. + class Result + # The list of comments that were encountered during parsing. + sig { returns(T::Array[Comment]) } + attr_reader :comments + + # The list of magic comments that were encountered during parsing. + sig { returns(T::Array[MagicComment]) } + attr_reader :magic_comments + + # An optional location that represents the location of the __END__ marker + # and the rest of the content of the file. This content is loaded into the + # DATA constant when the file being parsed is the main file being executed. + sig { returns(T.nilable(Location)) } + attr_reader :data_loc + + # The list of errors that were generated during parsing. + sig { returns(T::Array[ParseError]) } + attr_reader :errors + + # The list of warnings that were generated during parsing. + sig { returns(T::Array[ParseWarning]) } + attr_reader :warnings + + # A Source instance that represents the source code that was parsed. + sig { returns(Source) } + attr_reader :source + + # Create a new result object with the given values. + sig { params(comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + def initialize(comments, magic_comments, data_loc, errors, warnings, source); end + + # Implement the hash pattern matching interface for Result. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # Returns the encoding of the source code that was parsed. + sig { returns(Encoding) } + def encoding; end + + # Returns true if there were no errors during parsing and false if there + # were. + sig { returns(T::Boolean) } + def success?; end + + # Returns true if there were errors during parsing and false if there were + # not. + sig { returns(T::Boolean) } + def failure?; end + + # Create a code units cache for the given encoding. + sig { params(encoding: Encoding).returns(T.untyped) } + def code_units_cache(encoding); end + end + + # This is a result specific to the `parse` and `parse_file` methods. + class ParseResult < Result + # The syntax tree that was parsed from the source code. + sig { returns(ProgramNode) } + attr_reader :value + + # Create a new parse result object with the given values. + sig { params(value: ProgramNode, comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + + # Implement the hash pattern matching interface for ParseResult. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # Attach the list of comments to their respective locations in the tree. + sig { void } + def attach_comments!; end + + # Walk the tree and mark nodes that are on a new line, loosely emulating + # the behavior of CRuby's `:line` tracepoint event. + sig { void } + def mark_newlines!; end + + # Returns a string representation of the syntax tree with the errors + # displayed inline. + sig { returns(String) } + def errors_format; end + end + + # This is a result specific to the `lex` and `lex_file` methods. + class LexResult < Result + # The list of tokens that were parsed from the source code. + sig { returns(T::Array[[Token, Integer]]) } + attr_reader :value + + # Create a new lex result object with the given values. + sig { params(value: T::Array[[Token, Integer]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + + # Implement the hash pattern matching interface for LexResult. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + end + + # This is a result specific to the `parse_lex` and `parse_lex_file` methods. + class ParseLexResult < Result + # A tuple of the syntax tree and the list of tokens that were parsed from + # the source code. + sig { returns([ProgramNode, T::Array[[Token, Integer]]]) } + attr_reader :value + + # Create a new parse lex result object with the given values. + sig { params(value: [ProgramNode, T::Array[[Token, Integer]]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + + # Implement the hash pattern matching interface for ParseLexResult. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + end + + # This represents a token from the Ruby source. + class Token + # The Source object that represents the source this token came from. + sig { returns(Source) } + attr_reader :source + + # The type of token that this token is. + sig { returns(Symbol) } + attr_reader :type + + # A byteslice of the source that this token represents. + sig { returns(String) } + attr_reader :value + + # Create a new token object with the given type, value, and location. + sig { params(source: Source, type: Symbol, value: String, location: T.any(Location, Integer)).void } + def initialize(source, type, value, location); end + + # Implement the hash pattern matching interface for Token. + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + def deconstruct_keys(keys); end + + # A Location object representing the location of this token in the source. + sig { returns(Location) } + def location; end + + # Implement the pretty print interface for Token. + sig { params(q: PP).void } + def pretty_print(q); end + + # Returns true if the given other token is equal to this token. + sig { params(other: T.untyped).returns(T::Boolean) } + def ==(other); end + + # Returns a string representation of this token. + sig { returns(String) } + def inspect; end + + # Freeze this object and the objects it contains. + sig { void } + def deep_freeze; end + end + + # This object is passed to the various Prism.* methods that accept the + # `scopes` option as an element of the list. It defines both the local + # variables visible at that scope as well as the forwarding parameters + # available at that scope. + class Scope + # The list of local variables that are defined in this scope. This should be + # defined as an array of symbols. + sig { returns(T::Array[Symbol]) } + attr_reader :locals + + # The list of local variables that are forwarded to the next scope. This + # should by defined as an array of symbols containing the specific values of + sig { returns(T::Array[Symbol]) } + attr_reader :forwarding + + # Create a new scope object with the given locals and forwarding. + sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).void } + def initialize(locals, forwarding); end + end + + # Create a new scope with the given locals and forwarding options that is + # suitable for passing into one of the Prism.* methods that accepts the + # `scopes` option. + sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).returns(Scope) } + def self.scope(locals: T.unsafe(nil), forwarding: T.unsafe(nil)); end +end diff --git a/rbi/generated/prism/parse_result/comments.rbi b/rbi/generated/prism/parse_result/comments.rbi new file mode 100644 index 0000000000..4220d23d9d --- /dev/null +++ b/rbi/generated/prism/parse_result/comments.rbi @@ -0,0 +1,90 @@ +# typed: true + +module Prism + class ParseResult < Result + # When we've parsed the source, we have both the syntax tree and the list of + # comments that we found in the source. This class is responsible for + # walking the tree and finding the nearest location to attach each comment. + # + # It does this by first finding the nearest locations to each comment. + # Locations can either come from nodes directly or from location fields on + # nodes. For example, a `ClassNode` has an overall location encompassing the + # entire class, but it also has a location for the `class` keyword. + # + # Once the nearest locations are found, it determines which one to attach + # to. If it's a trailing comment (a comment on the same line as other source + # code), it will favor attaching to the nearest location that occurs before + # the comment. Otherwise it will favor attaching to the nearest location + # that is after the comment. + class Comments + # A target for attaching comments that is based on a specific node's + # location. + class NodeTarget + sig { returns(Node) } + attr_reader :node + + sig { params(node: Node).void } + def initialize(node); end + + sig { returns(Integer) } + def start_offset; end + + sig { returns(Integer) } + def end_offset; end + + sig { params(comment: Comment).returns(T::Boolean) } + def encloses?(comment); end + + sig { params(comment: Comment).void } + def leading_comment(comment); end + + sig { params(comment: Comment).void } + def trailing_comment(comment); end + end + + # A target for attaching comments that is based on a location field on a + # node. For example, the `end` token of a ClassNode. + class LocationTarget + sig { returns(Location) } + attr_reader :location + + sig { params(location: Location).void } + def initialize(location); end + + sig { returns(Integer) } + def start_offset; end + + sig { returns(Integer) } + def end_offset; end + + sig { params(comment: Comment).returns(T::Boolean) } + def encloses?(comment); end + + sig { params(comment: Comment).void } + def leading_comment(comment); end + + sig { params(comment: Comment).void } + def trailing_comment(comment); end + end + + # The parse result that we are attaching comments to. + sig { returns(ParseResult) } + attr_reader :parse_result + + # Create a new Comments object that will attach comments to the given + # parse result. + sig { params(parse_result: ParseResult).void } + def initialize(parse_result); end + + # Attach the comments to their respective locations in the tree by + # mutating the parse result. + sig { void } + def attach!; end + + # Responsible for finding the nearest targets to the given comment within + # the context of the given encapsulating node. + sig { params(node: Node, comment: Comment).returns([T.untyped, T.untyped, T.untyped]) } + private def nearest_targets(node, comment); end + end + end +end diff --git a/rbi/generated/prism/parse_result/errors.rbi b/rbi/generated/prism/parse_result/errors.rbi new file mode 100644 index 0000000000..f864a3f8c2 --- /dev/null +++ b/rbi/generated/prism/parse_result/errors.rbi @@ -0,0 +1,21 @@ +# typed: true + +module Prism + class ParseResult < Result + # An object to represent the set of errors on a parse result. This object + # can be used to format the errors in a human-readable way. + class Errors + # The parse result that contains the errors. + sig { returns(ParseResult) } + attr_reader :parse_result + + # Initialize a new set of errors from the given parse result. + sig { params(parse_result: ParseResult).void } + def initialize(parse_result); end + + # Formats the errors in a human-readable way and return them as a string. + sig { returns(String) } + def format; end + end + end +end diff --git a/rbi/generated/prism/parse_result/newlines.rbi b/rbi/generated/prism/parse_result/newlines.rbi new file mode 100644 index 0000000000..f77dee3bbf --- /dev/null +++ b/rbi/generated/prism/parse_result/newlines.rbi @@ -0,0 +1,121 @@ +# typed: true + +module Prism + class ParseResult < Result + # The :line tracepoint event gets fired whenever the Ruby VM encounters an + # expression on a new line. The types of expressions that can trigger this + # event are: + # + # * if statements + # * unless statements + # * nodes that are children of statements lists + # + # In order to keep track of the newlines, we have a list of offsets that + # come back from the parser. We assign these offsets to the first nodes that + # we find in the tree that are on those lines. + # + # Note that the logic in this file should be kept in sync with the Java + # MarkNewlinesVisitor, since that visitor is responsible for marking the + # newlines for JRuby/TruffleRuby. + # + # This file is autoloaded only when `mark_newlines!` is called, so the + # re-opening of the various nodes in this file will only be performed in + # that case. We do that to avoid storing the extra `@newline` instance + # variable on every node if we don't need it. + class Newlines < Visitor + # Create a new Newlines visitor with the given newline offsets. + sig { params(lines: Integer).void } + def initialize(lines); end + + # Permit block nodes to mark newlines within themselves. + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + # Permit lambda nodes to mark newlines within themselves. + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + # Mark if nodes as newlines. + sig { params(node: IfNode).void } + def visit_if_node(node); end + + # Mark unless nodes as newlines. + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + # Permit statements lists to mark newlines within themselves. + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + end + end + + class Node + abstract! + + sig { returns(T::Boolean) } + def newline_flag?; end + + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class BeginNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class ParenthesesNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class IfNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class UnlessNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class UntilNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class WhileNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class RescueModifierNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedMatchLastLineNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedRegularExpressionNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedStringNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedSymbolNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end + + class InterpolatedXStringNode < Node + sig { params(lines: T::Array[T::Boolean]).void } + def newline_flag!(lines); end + end +end diff --git a/rbi/generated/prism/pattern.rbi b/rbi/generated/prism/pattern.rbi new file mode 100644 index 0000000000..cc74c54d5e --- /dev/null +++ b/rbi/generated/prism/pattern.rbi @@ -0,0 +1,134 @@ +# typed: true + +module Prism + # A pattern is an object that wraps a Ruby pattern matching expression. The + # expression would normally be passed to an `in` clause within a `case` + # expression or a rightward assignment expression. For example, in the + # following snippet: + # + # case node + # in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]] + # end + # + # the pattern is the ConstantPathNode[...] expression. + # + # The pattern gets compiled into an object that responds to #call by running + # the #compile method. This method itself will run back through Prism to + # parse the expression into a tree, then walk the tree to generate the + # necessary callable objects. For example, if you wanted to compile the + # expression above into a callable, you would: + # + # callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile + # callable.call(node) + # + # The callable object returned by #compile is guaranteed to respond to #call + # with a single argument, which is the node to match against. It also is + # guaranteed to respond to #===, which means it itself can be used in a `case` + # expression, as in: + # + # case node + # when callable + # end + # + # If the query given to the initializer cannot be compiled into a valid + # matcher (either because of a syntax error or because it is using syntax we + # do not yet support) then a Prism::Pattern::CompilationError will be + # raised. + class Pattern + # Raised when the query given to a pattern is either invalid Ruby syntax or + # is using syntax that we don't yet support. + class CompilationError < StandardError + # Create a new CompilationError with the given representation of the node + # that caused the error. + sig { params(repr: String).void } + def initialize(repr); end + end + + # The query that this pattern was initialized with. + sig { returns(String) } + attr_reader :query + + # Create a new pattern with the given query. The query should be a string + # containing a Ruby pattern matching expression. + sig { params(query: String).void } + def initialize(query); end + + # Compile the query into a callable object that can be used to match against + # nodes. + sig { returns(Proc) } + def compile; end + + # Scan the given node and all of its children for nodes that match the + # pattern. If a block is given, it will be called with each node that + # matches the pattern. If no block is given, an enumerator will be returned + # that will yield each node that matches the pattern. + sig { params(root: Node).returns(T::Enumerator[Node]) } + sig { params(root: Node, blk: T.proc.params(arg0: Node).void).void } + def scan(root, &blk); end + + # Shortcut for combining two procs into one that returns true if both return + # true. + sig { params(left: Proc, right: Proc).returns(Proc) } + private def combine_and(left, right); end + + # Shortcut for combining two procs into one that returns true if either + # returns true. + sig { params(left: Proc, right: Proc).returns(Proc) } + private def combine_or(left, right); end + + # Raise an error because the given node is not supported. Note purposefully + # not typing this method since it is a no return method that Steep does not + # understand. + sig { params(node: Node).returns(T.noreturn) } + private def compile_error(node); end + + # in [foo, bar, baz] + sig { params(node: ArrayPatternNode).returns(Proc) } + private def compile_array_pattern_node(node); end + + # in foo | bar + sig { params(node: AlternationPatternNode).returns(Proc) } + private def compile_alternation_pattern_node(node); end + + # in Prism::ConstantReadNode + sig { params(node: ConstantPathNode).returns(Proc) } + private def compile_constant_path_node(node); end + + # in ConstantReadNode + # in String + sig { params(node: ConstantReadNode).returns(Proc) } + private def compile_constant_read_node(node); end + + # Compile a name associated with a constant. + sig { params(node: T.any(ConstantPathNode, ConstantReadNode), name: Symbol).returns(Proc) } + private def compile_constant_name(node, name); end + + # in InstanceVariableReadNode[name: Symbol] + # in { name: Symbol } + sig { params(node: HashPatternNode).returns(Proc) } + private def compile_hash_pattern_node(node); end + + # in nil + sig { params(node: NilNode).returns(Proc) } + private def compile_nil_node(node); end + + # in /foo/ + sig { params(node: RegularExpressionNode).returns(Proc) } + private def compile_regular_expression_node(node); end + + # in "" + # in "foo" + sig { params(node: StringNode).returns(Proc) } + private def compile_string_node(node); end + + # in :+ + # in :foo + sig { params(node: SymbolNode).returns(Proc) } + private def compile_symbol_node(node); end + + # Compile any kind of node. Dispatch out to the individual compilation + # methods based on the type of node. + sig { params(node: Node).returns(Proc) } + private def compile_node(node); end + end +end diff --git a/rbi/generated/prism/reflection.rbi b/rbi/generated/prism/reflection.rbi new file mode 100644 index 0000000000..7a4cd1bb43 --- /dev/null +++ b/rbi/generated/prism/reflection.rbi @@ -0,0 +1,89 @@ +# typed: true + +module Prism + # The Reflection module provides the ability to reflect on the structure of + # the syntax tree itself, as opposed to looking at a single syntax tree. This + # is useful in metaprogramming contexts. + module Reflection + # A field represents a single piece of data on a node. It is the base class + # for all other field types. + class Field + # The name of the field. + sig { returns(Symbol) } + attr_reader :name + + # Initializes the field with the given name. + sig { params(name: Symbol).void } + def initialize(name); end + end + + # A node field represents a single child node in the syntax tree. It + # resolves to a Prism::Node in Ruby. + class NodeField < Field; end + + # An optional node field represents a single child node in the syntax tree + # that may or may not be present. It resolves to either a Prism::Node or nil + # in Ruby. + class OptionalNodeField < Field; end + + # A node list field represents a list of child nodes in the syntax tree. It + # resolves to an array of Prism::Node instances in Ruby. + class NodeListField < Field; end + + # A constant field represents a constant value on a node. Effectively, it + # represents an identifier found within the source. It resolves to a symbol + # in Ruby. + class ConstantField < Field; end + + # An optional constant field represents a constant value on a node that may + # or may not be present. It resolves to either a symbol or nil in Ruby. + class OptionalConstantField < Field; end + + # A constant list field represents a list of constant values on a node. It + # resolves to an array of symbols in Ruby. + class ConstantListField < Field; end + + # A string field represents a string value on a node. It almost always + # represents the unescaped value of a string-like literal. It resolves to a + # string in Ruby. + class StringField < Field; end + + # A location field represents the location of some part of the node in the + # source code. For example, the location of a keyword or an operator. It + # resolves to a Prism::Location in Ruby. + class LocationField < Field; end + + # An optional location field represents the location of some part of the + # node in the source code that may or may not be present. It resolves to + # either a Prism::Location or nil in Ruby. + class OptionalLocationField < Field; end + + # An integer field represents an integer value. It is used to represent the + # value of an integer literal, the depth of local variables, and the number + # of a numbered reference. It resolves to an Integer in Ruby. + class IntegerField < Field; end + + # A float field represents a double-precision floating point value. It is + # used exclusively to represent the value of a floating point literal. It + # resolves to a Float in Ruby. + class FloatField < Field; end + + # A flags field represents a bitset of flags on a node. It resolves to an + # integer in Ruby. Note that the flags cannot be accessed directly on the + # node because the integer is kept private. Instead, the various flags in + # the bitset should be accessed through their query methods. + class FlagsField < Field + # The names of the flags in the bitset. + sig { returns(T::Array[Symbol]) } + attr_reader :flags + + # Initializes the flags field with the given name and flags. + sig { params(name: Symbol, flags: T::Array[Symbol]).void } + def initialize(name, flags); end + end + + # Returns the fields for the given node. + sig { params(node: T.class_of(Node)).returns(T::Array[Field]) } + def self.fields_for(node); end + end +end diff --git a/rbi/generated/prism/relocation.rbi b/rbi/generated/prism/relocation.rbi new file mode 100644 index 0000000000..e1c0a5bd40 --- /dev/null +++ b/rbi/generated/prism/relocation.rbi @@ -0,0 +1,389 @@ +# typed: true + +module Prism + # Prism parses deterministically for the same input. This provides a nice + # property that is exposed through the #node_id API on nodes. Effectively this + # means that for the same input, these values will remain consistent every + # time the source is parsed. This means we can reparse the source same with a + # #node_id value and find the exact same node again. + # + # The Relocation module provides an API around this property. It allows you to + # "save" nodes and locations using a minimal amount of memory (just the + # node_id and a field identifier) and then reify them later. + module Relocation + # An entry in a repository that will lazily reify its values when they are + # first accessed. + class Entry + # Raised if a value that could potentially be on an entry is missing + # because it was either not configured on the repository or it has not yet + # been fetched. + class MissingValueError < StandardError; end + + # Initialize a new entry with the given repository. + sig { params(repository: Repository).void } + def initialize(repository); end + + # Fetch the filepath of the value. + sig { returns(String) } + def filepath; end + + # Fetch the start line of the value. + sig { returns(Integer) } + def start_line; end + + # Fetch the end line of the value. + sig { returns(Integer) } + def end_line; end + + # Fetch the start byte offset of the value. + sig { returns(Integer) } + def start_offset; end + + # Fetch the end byte offset of the value. + sig { returns(Integer) } + def end_offset; end + + # Fetch the start character offset of the value. + sig { returns(Integer) } + def start_character_offset; end + + # Fetch the end character offset of the value. + sig { returns(Integer) } + def end_character_offset; end + + # Fetch the start code units offset of the value, for the encoding that + # was configured on the repository. + sig { returns(Integer) } + def start_code_units_offset; end + + # Fetch the end code units offset of the value, for the encoding that was + # configured on the repository. + sig { returns(Integer) } + def end_code_units_offset; end + + # Fetch the start byte column of the value. + sig { returns(Integer) } + def start_column; end + + # Fetch the end byte column of the value. + sig { returns(Integer) } + def end_column; end + + # Fetch the start character column of the value. + sig { returns(Integer) } + def start_character_column; end + + # Fetch the end character column of the value. + sig { returns(Integer) } + def end_character_column; end + + # Fetch the start code units column of the value, for the encoding that + # was configured on the repository. + sig { returns(Integer) } + def start_code_units_column; end + + # Fetch the end code units column of the value, for the encoding that was + # configured on the repository. + sig { returns(Integer) } + def end_code_units_column; end + + # Fetch the leading comments of the value. + sig { returns(T::Array[CommentsField::Comment]) } + def leading_comments; end + + # Fetch the trailing comments of the value. + sig { returns(T::Array[CommentsField::Comment]) } + def trailing_comments; end + + # Fetch the leading and trailing comments of the value. + sig { returns(T::Array[CommentsField::Comment]) } + def comments; end + + # Reify the values on this entry with the given values. This is an + # internal-only API that is called from the repository when it is time to + # reify the values. + sig { params(values: T::Hash[Symbol, T.untyped]).void } + def reify!(values); end + + # Fetch a value from the entry, raising an error if it is missing. + sig { params(name: Symbol).returns(T.untyped) } + private def fetch_value(name); end + + # Return the values from the repository, reifying them if necessary. + sig { returns(T::Hash[Symbol, T.untyped]) } + private def values; end + end + + # Represents the source of a repository that will be reparsed. + class Source + # The value that will need to be reparsed. + sig { returns(T.untyped) } + attr_reader :value + + # Initialize the source with the given value. + sig { params(value: T.untyped).void } + def initialize(value); end + + # Reparse the value and return the parse result. + sig { returns(ParseResult) } + def result; end + + # Create a code units cache for the given encoding. + sig { params(encoding: Encoding).returns(T.untyped) } + def code_units_cache(encoding); end + end + + # A source that is represented by a file path. + class SourceFilepath < Source + # Reparse the file and return the parse result. + sig { returns(ParseResult) } + def result; end + end + + # A source that is represented by a string. + class SourceString < Source + # Reparse the string and return the parse result. + sig { returns(ParseResult) } + def result; end + end + + # A field that represents the file path. + class FilepathField + # The file path that this field represents. + sig { returns(String) } + attr_reader :value + + # Initialize a new field with the given file path. + sig { params(value: String).void } + def initialize(value); end + + # Fetch the file path. + sig { params(_value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(_value); end + end + + # A field representing the start and end lines. + class LinesField + # Fetches the start and end line of a value. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + end + + # A field representing the start and end byte offsets. + class OffsetsField + # Fetches the start and end byte offset of a value. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + end + + # A field representing the start and end character offsets. + class CharacterOffsetsField + # Fetches the start and end character offset of a value. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + end + + # A field representing the start and end code unit offsets. + class CodeUnitOffsetsField + # A pointer to the repository object that is used for lazily creating a + # code units cache. + sig { returns(Repository) } + attr_reader :repository + + # The associated encoding for the code units. + sig { returns(Encoding) } + attr_reader :encoding + + # Initialize a new field with the associated repository and encoding. + sig { params(repository: Repository, encoding: Encoding).void } + def initialize(repository, encoding); end + + # Fetches the start and end code units offset of a value for a particular + # encoding. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + + # Lazily create a code units cache for the associated encoding. + sig { returns(T.untyped) } + private def cache; end + end + + # A field representing the start and end byte columns. + class ColumnsField + # Fetches the start and end byte column of a value. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + end + + # A field representing the start and end character columns. + class CharacterColumnsField + # Fetches the start and end character column of a value. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + end + + # A field representing the start and end code unit columns for a specific + # encoding. + class CodeUnitColumnsField + # The repository object that is used for lazily creating a code units + # cache. + sig { returns(Repository) } + attr_reader :repository + + # The associated encoding for the code units. + sig { returns(Encoding) } + attr_reader :encoding + + # Initialize a new field with the associated repository and encoding. + sig { params(repository: Repository, encoding: Encoding).void } + def initialize(repository, encoding); end + + # Fetches the start and end code units column of a value for a particular + # encoding. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + + # Lazily create a code units cache for the associated encoding. + sig { returns(T.untyped) } + private def cache; end + end + + # An abstract field used as the parent class of the two comments fields. + class CommentsField + # An object that represents a slice of a comment. + class Comment + # The slice of the comment. + sig { returns(String) } + attr_reader :slice + + # Initialize a new comment with the given slice. + # + sig { params(slice: String).void } + def initialize(slice); end + end + + # Create comment objects from the given values. + sig { params(values: T.untyped).returns(T::Array[Comment]) } + private def comments(values); end + end + + # A field representing the leading comments. + class LeadingCommentsField < CommentsField + # Fetches the leading comments of a value. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + end + + # A field representing the trailing comments. + class TrailingCommentsField < CommentsField + # Fetches the trailing comments of a value. + sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + def fields(value); end + end + + # A repository is a configured collection of fields and a set of entries + # that knows how to reparse a source and reify the values. + class Repository + # Raised when multiple fields of the same type are configured on the same + # repository. + class ConfigurationError < StandardError; end + + # The source associated with this repository. This will be either a + # SourceFilepath (the most common use case) or a SourceString. + sig { returns(Source) } + attr_reader :source + + # The fields that have been configured on this repository. + sig { returns(T::Hash[Symbol, T.untyped]) } + attr_reader :fields + + # The entries that have been saved on this repository. + sig { returns(T::Hash[Integer, T::Hash[Symbol, Entry]]) } + attr_reader :entries + + # Initialize a new repository with the given source. + sig { params(source: Source).void } + def initialize(source); end + + # Create a code units cache for the given encoding from the source. + sig { params(encoding: Encoding).returns(T.untyped) } + def code_units_cache(encoding); end + + # Configure the filepath field for this repository and return self. + sig { returns(T.self_type) } + def filepath; end + + # Configure the lines field for this repository and return self. + sig { returns(T.self_type) } + def lines; end + + # Configure the offsets field for this repository and return self. + sig { returns(T.self_type) } + def offsets; end + + # Configure the character offsets field for this repository and return + # self. + sig { returns(T.self_type) } + def character_offsets; end + + # Configure the code unit offsets field for this repository for a specific + # encoding and return self. + sig { params(encoding: Encoding).returns(T.self_type) } + def code_unit_offsets(encoding); end + + # Configure the columns field for this repository and return self. + sig { returns(T.self_type) } + def columns; end + + # Configure the character columns field for this repository and return + # self. + sig { returns(T.self_type) } + def character_columns; end + + # Configure the code unit columns field for this repository for a specific + # encoding and return self. + sig { params(encoding: Encoding).returns(T.self_type) } + def code_unit_columns(encoding); end + + # Configure the leading comments field for this repository and return + # self. + sig { returns(T.self_type) } + def leading_comments; end + + # Configure the trailing comments field for this repository and return + # self. + sig { returns(T.self_type) } + def trailing_comments; end + + # Configure both the leading and trailing comment fields for this + # repository and return self. + sig { returns(T.self_type) } + def comments; end + + # This method is called from nodes and locations when they want to enter + # themselves into the repository. It it internal-only and meant to be + # called from the #save* APIs. + sig { params(node_id: Integer, field_name: Symbol).returns(Entry) } + def enter(node_id, field_name); end + + # This method is called from the entries in the repository when they need + # to reify their values. It is internal-only and meant to be called from + # the various value APIs. + sig { void } + def reify!; end + + # Append the given field to the repository and return the repository so + # that these calls can be chained. + sig { params(name: Symbol, arg0: T.untyped).returns(T.self_type) } + private def field(name, arg0); end + end + + # Create a new repository for the given filepath. + sig { params(value: String).returns(Repository) } + def self.filepath(value); end + + # Create a new repository for the given string. + sig { params(value: String).returns(Repository) } + def self.string(value); end + end +end diff --git a/rbi/generated/prism/serialize.rbi b/rbi/generated/prism/serialize.rbi new file mode 100644 index 0000000000..9957fc9858 --- /dev/null +++ b/rbi/generated/prism/serialize.rbi @@ -0,0 +1,172 @@ +# typed: true + +module Prism + # A module responsible for deserializing parse results. + module Serialize + # The major version of prism that we are expecting to find in the serialized + # strings. + MAJOR_VERSION = T.let(nil, Integer) + + # The minor version of prism that we are expecting to find in the serialized + # strings. + MINOR_VERSION = T.let(nil, Integer) + + # The patch version of prism that we are expecting to find in the serialized + # strings. + PATCH_VERSION = T.let(nil, Integer) + + # Deserialize the dumped output from a request to parse or parse_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(ParseResult) } + def self.load_parse(input, serialized, freeze); end + + # Deserialize the dumped output from a request to lex or lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(LexResult) } + def self.load_lex(input, serialized, freeze); end + + # Deserialize the dumped output from a request to parse_comments or + # parse_file_comments. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(T::Array[Comment]) } + def self.load_parse_comments(input, serialized, freeze); end + + # Deserialize the dumped output from a request to parse_lex or + # parse_lex_file. + # + # The formatting of the source of this method is purposeful to illustrate + # the structure of the serialized data. + sig { params(input: String, serialized: String, freeze: T::Boolean).returns(ParseLexResult) } + def self.load_parse_lex(input, serialized, freeze); end + + class ConstantPool + sig { returns(Integer) } + attr_reader :size + + sig { params(input: String, serialized: String, base: Integer, size: Integer).void } + def initialize(input, serialized, base, size); end + + sig { params(index: Integer, encoding: Encoding).returns(Symbol) } + def get(index, encoding); end + end + + FastStringIO = T.let(nil, T.untyped) + + class Loader + sig { returns(String) } + attr_reader :input + + sig { returns(StringIO) } + attr_reader :io + + sig { returns(Source) } + attr_reader :source + + sig { params(source: Source, serialized: String).void } + def initialize(source, serialized); end + + sig { returns(T::Boolean) } + def eof?; end + + sig { params(constant_pool: ConstantPool).void } + def load_constant_pool(constant_pool); end + + sig { void } + def load_header; end + + sig { returns(Encoding) } + def load_encoding; end + + sig { params(freeze: T::Boolean).returns(T::Array[Integer]) } + def load_line_offsets(freeze); end + + sig { params(freeze: T::Boolean).returns(T::Array[Comment]) } + def load_comments(freeze); end + + sig { params(freeze: T::Boolean).returns(T::Array[MagicComment]) } + def load_magic_comments(freeze); end + + DIAGNOSTIC_TYPES = T.let(nil, T::Array[Symbol]) + + sig { returns(Symbol) } + def load_error_level; end + + sig { params(encoding: Encoding, freeze: T::Boolean).returns(T::Array[ParseError]) } + def load_errors(encoding, freeze); end + + sig { returns(Symbol) } + def load_warning_level; end + + sig { params(encoding: Encoding, freeze: T::Boolean).returns(T::Array[ParseWarning]) } + def load_warnings(encoding, freeze); end + + sig { returns(T::Array[[Token, Integer]]) } + def load_tokens; end + + # variable-length integer using https://en.wikipedia.org/wiki/LEB128 + # This is also what protobuf uses: https://protobuf.dev/programming-guides/encoding/#varints + sig { returns(Integer) } + def load_varuint; end + + sig { returns(Integer) } + def load_varsint; end + + sig { returns(Integer) } + def load_integer; end + + sig { returns(Float) } + def load_double; end + + sig { returns(Integer) } + def load_uint32; end + + sig { params(constant_pool: ConstantPool, encoding: Encoding, freeze: T::Boolean).returns(T.nilable(Node)) } + def load_optional_node(constant_pool, encoding, freeze); end + + sig { params(encoding: Encoding).returns(String) } + def load_embedded_string(encoding); end + + sig { params(encoding: Encoding).returns(String) } + def load_string(encoding); end + + sig { params(freeze: T::Boolean).returns(Location) } + def load_location_object(freeze); end + + # Load a location object from the serialized data. Note that we are lying + # about the signature a bit here, because we sometimes load it as a packed + # integer instead of an object. + sig { params(freeze: T::Boolean).returns(Location) } + def load_location(freeze); end + + # Load an optional location object from the serialized data if it is + # present. Note that we are lying about the signature a bit here, because + # we sometimes load it as a packed integer instead of an object. + sig { params(freeze: T::Boolean).returns(T.nilable(Location)) } + def load_optional_location(freeze); end + + sig { params(freeze: T::Boolean).returns(T.nilable(Location)) } + def load_optional_location_object(freeze); end + + sig { params(constant_pool: ConstantPool, encoding: Encoding).returns(Symbol) } + def load_constant(constant_pool, encoding); end + + sig { params(constant_pool: ConstantPool, encoding: Encoding).returns(T.nilable(Symbol)) } + def load_optional_constant(constant_pool, encoding); end + + sig { params(constant_pool: ConstantPool, encoding: Encoding, freeze: T::Boolean).returns(Node) } + def load_node(constant_pool, encoding, freeze); end + + sig { void } + def define_load_node_lambdas; end + end + + # The token types that can be indexed by their enum values. + TOKEN_TYPES = T.let(nil, T::Array[T.nilable(Symbol)]) + end +end diff --git a/rbi/generated/prism/string_query.rbi b/rbi/generated/prism/string_query.rbi new file mode 100644 index 0000000000..688ea4f08b --- /dev/null +++ b/rbi/generated/prism/string_query.rbi @@ -0,0 +1,36 @@ +# typed: true + +module Prism + # Query methods that allow categorizing strings based on their context for + # where they could be valid in a Ruby syntax tree. + class StringQuery + sig { params(string: String).returns(T::Boolean) } + def self.local?(string); end + + sig { params(string: String).returns(T::Boolean) } + def self.constant?(string); end + + sig { params(string: String).returns(T::Boolean) } + def self.method_name?(string); end + + # The string that this query is wrapping. + sig { returns(String) } + attr_reader :string + + # Initialize a new query with the given string. + sig { params(string: String).void } + def initialize(string); end + + # Whether or not this string is a valid local variable name. + sig { returns(T::Boolean) } + def local?; end + + # Whether or not this string is a valid constant name. + sig { returns(T::Boolean) } + def constant?; end + + # Whether or not this string is a valid method name. + sig { returns(T::Boolean) } + def method_name?; end + end +end diff --git a/rbi/generated/prism/translation.rbi b/rbi/generated/prism/translation.rbi new file mode 100644 index 0000000000..007625b541 --- /dev/null +++ b/rbi/generated/prism/translation.rbi @@ -0,0 +1,7 @@ +# typed: true + +module Prism + # This module is responsible for converting the prism syntax tree into other + # syntax trees. + module Translation; end +end diff --git a/rbi/generated/prism/visitor.rbi b/rbi/generated/prism/visitor.rbi new file mode 100644 index 0000000000..5025dd4c10 --- /dev/null +++ b/rbi/generated/prism/visitor.rbi @@ -0,0 +1,650 @@ +# typed: true + +module Prism + # A class that knows how to walk down the tree. None of the individual visit + # methods are implemented on this visitor, so it forces the consumer to + # implement each one that they need. For a default implementation that + # continues walking the tree, see the Visitor class. + class BasicVisitor + # Calls `accept` on the given node if it is not `nil`, which in turn should + # call back into this visitor by calling the appropriate `visit_*` method. + sig { params(node: T.nilable(Node)).void } + def visit(node); end + + # Visits each node in `nodes` by calling `accept` on each one. + sig { params(nodes: T::Array[T.nilable(Node)]).void } + def visit_all(nodes); end + + # Visits the child nodes of `node` by calling `accept` on each one. + sig { params(node: Node).void } + def visit_child_nodes(node); end + end + + # A visitor is a class that provides a default implementation for every accept + # method defined on the nodes. This means it can walk a tree without the + # caller needing to define any special handling. This allows you to handle a + # subset of the tree, while still walking the whole tree. + # + # For example, to find all of the method calls that call the `foo` method, you + # could write: + # + # class FooCalls < Prism::Visitor + # def visit_call_node(node) + # if node.name == :foo + # # Do something with the node + # end + # + # # Call super so that the visitor continues walking the tree + # super + # end + # end + class Visitor < BasicVisitor + # Visit a AliasGlobalVariableNode node + sig { params(node: AliasGlobalVariableNode).void } + def visit_alias_global_variable_node(node); end + + # Visit a AliasMethodNode node + sig { params(node: AliasMethodNode).void } + def visit_alias_method_node(node); end + + # Visit a AlternationPatternNode node + sig { params(node: AlternationPatternNode).void } + def visit_alternation_pattern_node(node); end + + # Visit a AndNode node + sig { params(node: AndNode).void } + def visit_and_node(node); end + + # Visit a ArgumentsNode node + sig { params(node: ArgumentsNode).void } + def visit_arguments_node(node); end + + # Visit a ArrayNode node + sig { params(node: ArrayNode).void } + def visit_array_node(node); end + + # Visit a ArrayPatternNode node + sig { params(node: ArrayPatternNode).void } + def visit_array_pattern_node(node); end + + # Visit a AssocNode node + sig { params(node: AssocNode).void } + def visit_assoc_node(node); end + + # Visit a AssocSplatNode node + sig { params(node: AssocSplatNode).void } + def visit_assoc_splat_node(node); end + + # Visit a BackReferenceReadNode node + sig { params(node: BackReferenceReadNode).void } + def visit_back_reference_read_node(node); end + + # Visit a BeginNode node + sig { params(node: BeginNode).void } + def visit_begin_node(node); end + + # Visit a BlockArgumentNode node + sig { params(node: BlockArgumentNode).void } + def visit_block_argument_node(node); end + + # Visit a BlockLocalVariableNode node + sig { params(node: BlockLocalVariableNode).void } + def visit_block_local_variable_node(node); end + + # Visit a BlockNode node + sig { params(node: BlockNode).void } + def visit_block_node(node); end + + # Visit a BlockParameterNode node + sig { params(node: BlockParameterNode).void } + def visit_block_parameter_node(node); end + + # Visit a BlockParametersNode node + sig { params(node: BlockParametersNode).void } + def visit_block_parameters_node(node); end + + # Visit a BreakNode node + sig { params(node: BreakNode).void } + def visit_break_node(node); end + + # Visit a CallAndWriteNode node + sig { params(node: CallAndWriteNode).void } + def visit_call_and_write_node(node); end + + # Visit a CallNode node + sig { params(node: CallNode).void } + def visit_call_node(node); end + + # Visit a CallOperatorWriteNode node + sig { params(node: CallOperatorWriteNode).void } + def visit_call_operator_write_node(node); end + + # Visit a CallOrWriteNode node + sig { params(node: CallOrWriteNode).void } + def visit_call_or_write_node(node); end + + # Visit a CallTargetNode node + sig { params(node: CallTargetNode).void } + def visit_call_target_node(node); end + + # Visit a CapturePatternNode node + sig { params(node: CapturePatternNode).void } + def visit_capture_pattern_node(node); end + + # Visit a CaseMatchNode node + sig { params(node: CaseMatchNode).void } + def visit_case_match_node(node); end + + # Visit a CaseNode node + sig { params(node: CaseNode).void } + def visit_case_node(node); end + + # Visit a ClassNode node + sig { params(node: ClassNode).void } + def visit_class_node(node); end + + # Visit a ClassVariableAndWriteNode node + sig { params(node: ClassVariableAndWriteNode).void } + def visit_class_variable_and_write_node(node); end + + # Visit a ClassVariableOperatorWriteNode node + sig { params(node: ClassVariableOperatorWriteNode).void } + def visit_class_variable_operator_write_node(node); end + + # Visit a ClassVariableOrWriteNode node + sig { params(node: ClassVariableOrWriteNode).void } + def visit_class_variable_or_write_node(node); end + + # Visit a ClassVariableReadNode node + sig { params(node: ClassVariableReadNode).void } + def visit_class_variable_read_node(node); end + + # Visit a ClassVariableTargetNode node + sig { params(node: ClassVariableTargetNode).void } + def visit_class_variable_target_node(node); end + + # Visit a ClassVariableWriteNode node + sig { params(node: ClassVariableWriteNode).void } + def visit_class_variable_write_node(node); end + + # Visit a ConstantAndWriteNode node + sig { params(node: ConstantAndWriteNode).void } + def visit_constant_and_write_node(node); end + + # Visit a ConstantOperatorWriteNode node + sig { params(node: ConstantOperatorWriteNode).void } + def visit_constant_operator_write_node(node); end + + # Visit a ConstantOrWriteNode node + sig { params(node: ConstantOrWriteNode).void } + def visit_constant_or_write_node(node); end + + # Visit a ConstantPathAndWriteNode node + sig { params(node: ConstantPathAndWriteNode).void } + def visit_constant_path_and_write_node(node); end + + # Visit a ConstantPathNode node + sig { params(node: ConstantPathNode).void } + def visit_constant_path_node(node); end + + # Visit a ConstantPathOperatorWriteNode node + sig { params(node: ConstantPathOperatorWriteNode).void } + def visit_constant_path_operator_write_node(node); end + + # Visit a ConstantPathOrWriteNode node + sig { params(node: ConstantPathOrWriteNode).void } + def visit_constant_path_or_write_node(node); end + + # Visit a ConstantPathTargetNode node + sig { params(node: ConstantPathTargetNode).void } + def visit_constant_path_target_node(node); end + + # Visit a ConstantPathWriteNode node + sig { params(node: ConstantPathWriteNode).void } + def visit_constant_path_write_node(node); end + + # Visit a ConstantReadNode node + sig { params(node: ConstantReadNode).void } + def visit_constant_read_node(node); end + + # Visit a ConstantTargetNode node + sig { params(node: ConstantTargetNode).void } + def visit_constant_target_node(node); end + + # Visit a ConstantWriteNode node + sig { params(node: ConstantWriteNode).void } + def visit_constant_write_node(node); end + + # Visit a DefNode node + sig { params(node: DefNode).void } + def visit_def_node(node); end + + # Visit a DefinedNode node + sig { params(node: DefinedNode).void } + def visit_defined_node(node); end + + # Visit a ElseNode node + sig { params(node: ElseNode).void } + def visit_else_node(node); end + + # Visit a EmbeddedStatementsNode node + sig { params(node: EmbeddedStatementsNode).void } + def visit_embedded_statements_node(node); end + + # Visit a EmbeddedVariableNode node + sig { params(node: EmbeddedVariableNode).void } + def visit_embedded_variable_node(node); end + + # Visit a EnsureNode node + sig { params(node: EnsureNode).void } + def visit_ensure_node(node); end + + # Visit a FalseNode node + sig { params(node: FalseNode).void } + def visit_false_node(node); end + + # Visit a FindPatternNode node + sig { params(node: FindPatternNode).void } + def visit_find_pattern_node(node); end + + # Visit a FlipFlopNode node + sig { params(node: FlipFlopNode).void } + def visit_flip_flop_node(node); end + + # Visit a FloatNode node + sig { params(node: FloatNode).void } + def visit_float_node(node); end + + # Visit a ForNode node + sig { params(node: ForNode).void } + def visit_for_node(node); end + + # Visit a ForwardingArgumentsNode node + sig { params(node: ForwardingArgumentsNode).void } + def visit_forwarding_arguments_node(node); end + + # Visit a ForwardingParameterNode node + sig { params(node: ForwardingParameterNode).void } + def visit_forwarding_parameter_node(node); end + + # Visit a ForwardingSuperNode node + sig { params(node: ForwardingSuperNode).void } + def visit_forwarding_super_node(node); end + + # Visit a GlobalVariableAndWriteNode node + sig { params(node: GlobalVariableAndWriteNode).void } + def visit_global_variable_and_write_node(node); end + + # Visit a GlobalVariableOperatorWriteNode node + sig { params(node: GlobalVariableOperatorWriteNode).void } + def visit_global_variable_operator_write_node(node); end + + # Visit a GlobalVariableOrWriteNode node + sig { params(node: GlobalVariableOrWriteNode).void } + def visit_global_variable_or_write_node(node); end + + # Visit a GlobalVariableReadNode node + sig { params(node: GlobalVariableReadNode).void } + def visit_global_variable_read_node(node); end + + # Visit a GlobalVariableTargetNode node + sig { params(node: GlobalVariableTargetNode).void } + def visit_global_variable_target_node(node); end + + # Visit a GlobalVariableWriteNode node + sig { params(node: GlobalVariableWriteNode).void } + def visit_global_variable_write_node(node); end + + # Visit a HashNode node + sig { params(node: HashNode).void } + def visit_hash_node(node); end + + # Visit a HashPatternNode node + sig { params(node: HashPatternNode).void } + def visit_hash_pattern_node(node); end + + # Visit a IfNode node + sig { params(node: IfNode).void } + def visit_if_node(node); end + + # Visit a ImaginaryNode node + sig { params(node: ImaginaryNode).void } + def visit_imaginary_node(node); end + + # Visit a ImplicitNode node + sig { params(node: ImplicitNode).void } + def visit_implicit_node(node); end + + # Visit a ImplicitRestNode node + sig { params(node: ImplicitRestNode).void } + def visit_implicit_rest_node(node); end + + # Visit a InNode node + sig { params(node: InNode).void } + def visit_in_node(node); end + + # Visit a IndexAndWriteNode node + sig { params(node: IndexAndWriteNode).void } + def visit_index_and_write_node(node); end + + # Visit a IndexOperatorWriteNode node + sig { params(node: IndexOperatorWriteNode).void } + def visit_index_operator_write_node(node); end + + # Visit a IndexOrWriteNode node + sig { params(node: IndexOrWriteNode).void } + def visit_index_or_write_node(node); end + + # Visit a IndexTargetNode node + sig { params(node: IndexTargetNode).void } + def visit_index_target_node(node); end + + # Visit a InstanceVariableAndWriteNode node + sig { params(node: InstanceVariableAndWriteNode).void } + def visit_instance_variable_and_write_node(node); end + + # Visit a InstanceVariableOperatorWriteNode node + sig { params(node: InstanceVariableOperatorWriteNode).void } + def visit_instance_variable_operator_write_node(node); end + + # Visit a InstanceVariableOrWriteNode node + sig { params(node: InstanceVariableOrWriteNode).void } + def visit_instance_variable_or_write_node(node); end + + # Visit a InstanceVariableReadNode node + sig { params(node: InstanceVariableReadNode).void } + def visit_instance_variable_read_node(node); end + + # Visit a InstanceVariableTargetNode node + sig { params(node: InstanceVariableTargetNode).void } + def visit_instance_variable_target_node(node); end + + # Visit a InstanceVariableWriteNode node + sig { params(node: InstanceVariableWriteNode).void } + def visit_instance_variable_write_node(node); end + + # Visit a IntegerNode node + sig { params(node: IntegerNode).void } + def visit_integer_node(node); end + + # Visit a InterpolatedMatchLastLineNode node + sig { params(node: InterpolatedMatchLastLineNode).void } + def visit_interpolated_match_last_line_node(node); end + + # Visit a InterpolatedRegularExpressionNode node + sig { params(node: InterpolatedRegularExpressionNode).void } + def visit_interpolated_regular_expression_node(node); end + + # Visit a InterpolatedStringNode node + sig { params(node: InterpolatedStringNode).void } + def visit_interpolated_string_node(node); end + + # Visit a InterpolatedSymbolNode node + sig { params(node: InterpolatedSymbolNode).void } + def visit_interpolated_symbol_node(node); end + + # Visit a InterpolatedXStringNode node + sig { params(node: InterpolatedXStringNode).void } + def visit_interpolated_x_string_node(node); end + + # Visit a ItLocalVariableReadNode node + sig { params(node: ItLocalVariableReadNode).void } + def visit_it_local_variable_read_node(node); end + + # Visit a ItParametersNode node + sig { params(node: ItParametersNode).void } + def visit_it_parameters_node(node); end + + # Visit a KeywordHashNode node + sig { params(node: KeywordHashNode).void } + def visit_keyword_hash_node(node); end + + # Visit a KeywordRestParameterNode node + sig { params(node: KeywordRestParameterNode).void } + def visit_keyword_rest_parameter_node(node); end + + # Visit a LambdaNode node + sig { params(node: LambdaNode).void } + def visit_lambda_node(node); end + + # Visit a LocalVariableAndWriteNode node + sig { params(node: LocalVariableAndWriteNode).void } + def visit_local_variable_and_write_node(node); end + + # Visit a LocalVariableOperatorWriteNode node + sig { params(node: LocalVariableOperatorWriteNode).void } + def visit_local_variable_operator_write_node(node); end + + # Visit a LocalVariableOrWriteNode node + sig { params(node: LocalVariableOrWriteNode).void } + def visit_local_variable_or_write_node(node); end + + # Visit a LocalVariableReadNode node + sig { params(node: LocalVariableReadNode).void } + def visit_local_variable_read_node(node); end + + # Visit a LocalVariableTargetNode node + sig { params(node: LocalVariableTargetNode).void } + def visit_local_variable_target_node(node); end + + # Visit a LocalVariableWriteNode node + sig { params(node: LocalVariableWriteNode).void } + def visit_local_variable_write_node(node); end + + # Visit a MatchLastLineNode node + sig { params(node: MatchLastLineNode).void } + def visit_match_last_line_node(node); end + + # Visit a MatchPredicateNode node + sig { params(node: MatchPredicateNode).void } + def visit_match_predicate_node(node); end + + # Visit a MatchRequiredNode node + sig { params(node: MatchRequiredNode).void } + def visit_match_required_node(node); end + + # Visit a MatchWriteNode node + sig { params(node: MatchWriteNode).void } + def visit_match_write_node(node); end + + # Visit a MissingNode node + sig { params(node: MissingNode).void } + def visit_missing_node(node); end + + # Visit a ModuleNode node + sig { params(node: ModuleNode).void } + def visit_module_node(node); end + + # Visit a MultiTargetNode node + sig { params(node: MultiTargetNode).void } + def visit_multi_target_node(node); end + + # Visit a MultiWriteNode node + sig { params(node: MultiWriteNode).void } + def visit_multi_write_node(node); end + + # Visit a NextNode node + sig { params(node: NextNode).void } + def visit_next_node(node); end + + # Visit a NilNode node + sig { params(node: NilNode).void } + def visit_nil_node(node); end + + # Visit a NoBlockParameterNode node + sig { params(node: NoBlockParameterNode).void } + def visit_no_block_parameter_node(node); end + + # Visit a NoKeywordsParameterNode node + sig { params(node: NoKeywordsParameterNode).void } + def visit_no_keywords_parameter_node(node); end + + # Visit a NumberedParametersNode node + sig { params(node: NumberedParametersNode).void } + def visit_numbered_parameters_node(node); end + + # Visit a NumberedReferenceReadNode node + sig { params(node: NumberedReferenceReadNode).void } + def visit_numbered_reference_read_node(node); end + + # Visit a OptionalKeywordParameterNode node + sig { params(node: OptionalKeywordParameterNode).void } + def visit_optional_keyword_parameter_node(node); end + + # Visit a OptionalParameterNode node + sig { params(node: OptionalParameterNode).void } + def visit_optional_parameter_node(node); end + + # Visit a OrNode node + sig { params(node: OrNode).void } + def visit_or_node(node); end + + # Visit a ParametersNode node + sig { params(node: ParametersNode).void } + def visit_parameters_node(node); end + + # Visit a ParenthesesNode node + sig { params(node: ParenthesesNode).void } + def visit_parentheses_node(node); end + + # Visit a PinnedExpressionNode node + sig { params(node: PinnedExpressionNode).void } + def visit_pinned_expression_node(node); end + + # Visit a PinnedVariableNode node + sig { params(node: PinnedVariableNode).void } + def visit_pinned_variable_node(node); end + + # Visit a PostExecutionNode node + sig { params(node: PostExecutionNode).void } + def visit_post_execution_node(node); end + + # Visit a PreExecutionNode node + sig { params(node: PreExecutionNode).void } + def visit_pre_execution_node(node); end + + # Visit a ProgramNode node + sig { params(node: ProgramNode).void } + def visit_program_node(node); end + + # Visit a RangeNode node + sig { params(node: RangeNode).void } + def visit_range_node(node); end + + # Visit a RationalNode node + sig { params(node: RationalNode).void } + def visit_rational_node(node); end + + # Visit a RedoNode node + sig { params(node: RedoNode).void } + def visit_redo_node(node); end + + # Visit a RegularExpressionNode node + sig { params(node: RegularExpressionNode).void } + def visit_regular_expression_node(node); end + + # Visit a RequiredKeywordParameterNode node + sig { params(node: RequiredKeywordParameterNode).void } + def visit_required_keyword_parameter_node(node); end + + # Visit a RequiredParameterNode node + sig { params(node: RequiredParameterNode).void } + def visit_required_parameter_node(node); end + + # Visit a RescueModifierNode node + sig { params(node: RescueModifierNode).void } + def visit_rescue_modifier_node(node); end + + # Visit a RescueNode node + sig { params(node: RescueNode).void } + def visit_rescue_node(node); end + + # Visit a RestParameterNode node + sig { params(node: RestParameterNode).void } + def visit_rest_parameter_node(node); end + + # Visit a RetryNode node + sig { params(node: RetryNode).void } + def visit_retry_node(node); end + + # Visit a ReturnNode node + sig { params(node: ReturnNode).void } + def visit_return_node(node); end + + # Visit a SelfNode node + sig { params(node: SelfNode).void } + def visit_self_node(node); end + + # Visit a ShareableConstantNode node + sig { params(node: ShareableConstantNode).void } + def visit_shareable_constant_node(node); end + + # Visit a SingletonClassNode node + sig { params(node: SingletonClassNode).void } + def visit_singleton_class_node(node); end + + # Visit a SourceEncodingNode node + sig { params(node: SourceEncodingNode).void } + def visit_source_encoding_node(node); end + + # Visit a SourceFileNode node + sig { params(node: SourceFileNode).void } + def visit_source_file_node(node); end + + # Visit a SourceLineNode node + sig { params(node: SourceLineNode).void } + def visit_source_line_node(node); end + + # Visit a SplatNode node + sig { params(node: SplatNode).void } + def visit_splat_node(node); end + + # Visit a StatementsNode node + sig { params(node: StatementsNode).void } + def visit_statements_node(node); end + + # Visit a StringNode node + sig { params(node: StringNode).void } + def visit_string_node(node); end + + # Visit a SuperNode node + sig { params(node: SuperNode).void } + def visit_super_node(node); end + + # Visit a SymbolNode node + sig { params(node: SymbolNode).void } + def visit_symbol_node(node); end + + # Visit a TrueNode node + sig { params(node: TrueNode).void } + def visit_true_node(node); end + + # Visit a UndefNode node + sig { params(node: UndefNode).void } + def visit_undef_node(node); end + + # Visit a UnlessNode node + sig { params(node: UnlessNode).void } + def visit_unless_node(node); end + + # Visit a UntilNode node + sig { params(node: UntilNode).void } + def visit_until_node(node); end + + # Visit a WhenNode node + sig { params(node: WhenNode).void } + def visit_when_node(node); end + + # Visit a WhileNode node + sig { params(node: WhileNode).void } + def visit_while_node(node); end + + # Visit a XStringNode node + sig { params(node: XStringNode).void } + def visit_x_string_node(node); end + + # Visit a YieldNode node + sig { params(node: YieldNode).void } + def visit_yield_node(node); end + end +end diff --git a/rbi/prism.rbi b/rbi/prism.rbi deleted file mode 100644 index b31adc64a1..0000000000 --- a/rbi/prism.rbi +++ /dev/null @@ -1,63 +0,0 @@ -# typed: strict - -module Prism - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(String) } - def self.dump(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(String) } - def self.dump_file(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::LexResult) } - def self.lex(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::LexResult) } - def self.lex_file(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(source: String, options: T::Hash[Symbol, T.untyped]).returns(Prism::LexCompat::Result) } - def self.lex_compat(source, **options); end - - sig { params(source: String, serialized: String, freeze: T.nilable(T::Boolean)).returns(Prism::ParseResult) } - def self.load(source, serialized, freeze = false); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } - def self.parse(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } - def self.parse_file(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).void } - def self.profile(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).void } - def self.profile_file(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(stream: T.any(IO, StringIO), command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseResult) } - def self.parse_stream(stream, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(String, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Array[Prism::Comment]) } - def self.parse_comments(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Array[Prism::Comment]) } - def self.parse_file_comments(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseLexResult) } - def self.parse_lex(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(Prism::ParseLexResult) } - def self.parse_lex_file(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_success?(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(source: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), filepath: T.nilable(String), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_failure?(source, command_line: nil, encoding: nil, filepath: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_file_success?(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(filepath: String, command_line: T.nilable(String), encoding: T.nilable(T.any(FalseClass, Encoding)), freeze: T.nilable(T::Boolean), frozen_string_literal: T.nilable(T::Boolean), line: T.nilable(Integer), main_script: T.nilable(T::Boolean), partial_script: T.nilable(T::Boolean), scopes: T.nilable(T::Array[T::Array[Symbol]]), version: T.nilable(String)).returns(T::Boolean) } - def self.parse_file_failure?(filepath, command_line: nil, encoding: nil, freeze: nil, frozen_string_literal: nil, line: nil, main_script: nil, partial_script: nil, scopes: nil, version: nil); end - - sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).returns(Prism::Scope) } - def self.scope(locals: [], forwarding: []); end -end diff --git a/rbi/prism/compiler.rbi b/rbi/prism/compiler.rbi deleted file mode 100644 index c738236dea..0000000000 --- a/rbi/prism/compiler.rbi +++ /dev/null @@ -1,12 +0,0 @@ -# typed: strict - -class Prism::Compiler - sig { params(node: T.nilable(Prism::Node)).returns(T.untyped) } - def visit(node); end - - sig { params(nodes: T::Array[T.nilable(Prism::Node)]).returns(T::Array[T.untyped]) } - def visit_all(nodes); end - - sig { params(node: Prism::Node).returns(T::Array[T.untyped]) } - def visit_child_nodes(node); end -end diff --git a/rbi/prism/inspect_visitor.rbi b/rbi/prism/inspect_visitor.rbi deleted file mode 100644 index bb0c22409e..0000000000 --- a/rbi/prism/inspect_visitor.rbi +++ /dev/null @@ -1,12 +0,0 @@ -# typed: strict - -class Prism::InspectVisitor < Prism::Visitor - sig { params(indent: String).void } - def initialize(indent = ""); end - - sig { params(node: Prism::Node).returns(String) } - def self.compose(node); end - - sig { returns(String) } - def compose; end -end diff --git a/rbi/prism/node_ext.rbi b/rbi/prism/node_ext.rbi deleted file mode 100644 index e5cf7376cc..0000000000 --- a/rbi/prism/node_ext.rbi +++ /dev/null @@ -1,107 +0,0 @@ -# typed: strict - -class Prism::InterpolatedMatchLastLineNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::InterpolatedRegularExpressionNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::MatchLastLineNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::RegularExpressionNode < Prism::Node - sig { returns(Integer) } - def options; end -end - -class Prism::InterpolatedStringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end -end - -class Prism::InterpolatedXStringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end -end - -class Prism::StringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end - - sig { returns(Prism::InterpolatedStringNode) } - def to_interpolated; end -end - -class Prism::XStringNode < Prism::Node - sig { returns(T::Boolean) } - def heredoc?; end - - sig { returns(Prism::InterpolatedXStringNode) } - def to_interpolated; end -end - -class Prism::ImaginaryNode < Prism::Node - sig { returns(Complex) } - def value; end -end - -class Prism::RationalNode < Prism::Node - sig { returns(Rational) } - def value; end -end - -class Prism::ConstantReadNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantWriteNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantPathNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantPathTargetNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ConstantTargetNode < Prism::Node - sig { returns(T::Array[Symbol]) } - def full_name_parts; end - - sig { returns(String) } - def full_name; end -end - -class Prism::ParametersNode < Prism::Node - sig { returns(T::Array[T.any([Symbol, Symbol], [Symbol])]) } - def signature; end -end - -class Prism::CallNode < Prism::Node - sig { returns(T.nilable(Prism::Location)) } - def full_message_loc; end -end diff --git a/rbi/prism/parse_result.rbi b/rbi/prism/parse_result.rbi deleted file mode 100644 index 6f2bbb6146..0000000000 --- a/rbi/prism/parse_result.rbi +++ /dev/null @@ -1,404 +0,0 @@ -# typed: strict - -class Prism::Source - sig { returns(String) } - def source; end - - sig { returns(Integer) } - def start_line; end - - sig { returns(T::Array[Integer]) } - def offsets; end - - sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).void } - def initialize(source, start_line = 1, offsets = []); end - - sig { params(start_line: Integer).void } - def replace_start_line(start_line); end - - sig { params(offsets: T::Array[Integer]).void } - def replace_offsets(offsets); end - - sig { returns(Encoding) } - def encoding; end - - sig { returns(T::Array[String]) } - def lines; end - - sig { params(byte_offset: Integer, length: Integer).returns(String) } - def slice(byte_offset, length); end - - sig { params(byte_offset: Integer).returns(Integer) } - def line(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def line_start(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def column(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def character_offset(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def character_column(byte_offset); end - - sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } - def code_units_offset(byte_offset, encoding); end - - sig { params(encoding: Encoding).returns(T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))) } - def code_units_cache(encoding); end - - sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } - def code_units_column(byte_offset, encoding); end -end - -class Prism::CodeUnitsCache - sig { params(source: String, encoding: Encoding).void } - def initialize(source, encoding); end - - sig { params(byte_offset: Integer).returns(Integer) } - def [](byte_offset); end -end - -class Prism::ASCIISource < Prism::Source - sig { params(byte_offset: Integer).returns(Integer) } - def character_offset(byte_offset); end - - sig { params(byte_offset: Integer).returns(Integer) } - def character_column(byte_offset); end - - sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } - def code_units_offset(byte_offset, encoding); end - - sig { params(encoding: Encoding).returns(T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))) } - def code_units_cache(encoding); end - - sig { params(byte_offset: Integer, encoding: Encoding).returns(Integer) } - def code_units_column(byte_offset, encoding); end -end - -class Prism::Location - sig { returns(Prism::Source) } - def source; end - - sig { returns(Integer) } - def start_offset; end - - sig { returns(Integer) } - def length; end - - sig { params(source: Prism::Source, start_offset: Integer, length: Integer).void } - def initialize(source, start_offset, length); end - - sig { returns(T::Array[Prism::Comment]) } - def leading_comments; end - - sig { params(comment: Prism::Comment).void } - def leading_comment(comment); end - - sig { returns(T::Array[Prism::Comment]) } - def trailing_comments; end - - sig { params(comment: Prism::Comment).void } - def trailing_comment(comment); end - - sig { returns(T::Array[Prism::Comment]) } - def comments; end - - sig { params(source: Prism::Source, start_offset: Integer, length: Integer).returns(Prism::Location) } - def copy(source: self.source, start_offset: self.start_offset, length: self.length); end - - sig { returns(Prism::Location) } - def chop; end - - sig { returns(String) } - def inspect; end - - sig { returns(T::Array[String]) } - def source_lines; end - - sig { returns(String) } - def slice; end - - sig { returns(Integer) } - def start_character_offset; end - - sig { params(encoding: Encoding).returns(Integer) } - def start_code_units_offset(encoding = Encoding::UTF_16LE); end - - sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } - def cached_start_code_units_offset(cache); end - - sig { returns(Integer) } - def end_offset; end - - sig { returns(Integer) } - def end_character_offset; end - - sig { params(encoding: Encoding).returns(Integer) } - def end_code_units_offset(encoding = Encoding::UTF_16LE); end - - sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } - def cached_end_code_units_offset(cache); end - - sig { returns(Integer) } - def start_line; end - - sig { returns(String) } - def start_line_slice; end - - sig { returns(Integer) } - def end_line; end - - sig { returns(Integer) } - def start_column; end - - sig { returns(Integer) } - def start_character_column; end - - sig { params(encoding: Encoding).returns(Integer) } - def start_code_units_column(encoding = Encoding::UTF_16LE); end - - sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } - def cached_start_code_units_column(cache); end - - sig { returns(Integer) } - def end_column; end - - sig { returns(Integer) } - def end_character_column; end - - sig { params(encoding: Encoding).returns(Integer) } - def end_code_units_column(encoding = Encoding::UTF_16LE); end - - sig { params(cache: T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))).returns(Integer) } - def cached_end_code_units_column(cache); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { params(q: T.untyped).void } - def pretty_print(q); end - - sig { params(other: T.untyped).returns(T::Boolean) } - def ==(other); end - - sig { params(other: Prism::Location).returns(Prism::Location) } - def join(other); end - - sig { params(string: String).returns(Prism::Location) } - def adjoin(string); end -end - -class Prism::Comment - abstract! - - sig { returns(Prism::Location) } - def location; end - - sig { params(location: Prism::Location).void } - def initialize(location); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def slice; end - - sig { abstract.returns(T::Boolean) } - def trailing?; end -end - -class Prism::InlineComment < Prism::Comment - sig { override.returns(T::Boolean) } - def trailing?; end - - sig { returns(String) } - def inspect; end -end - -class Prism::EmbDocComment < Prism::Comment - sig { override.returns(T::Boolean) } - def trailing?; end - - sig { returns(String) } - def inspect; end -end - -class Prism::MagicComment - sig { returns(Prism::Location) } - def key_loc; end - - sig { returns(Prism::Location) } - def value_loc; end - - sig { params(key_loc: Prism::Location, value_loc: Prism::Location).void } - def initialize(key_loc, value_loc); end - - sig { returns(String) } - def key; end - - sig { returns(String) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def inspect; end -end - -class Prism::ParseError - sig { returns(Symbol) } - def type; end - - sig { returns(String) } - def message; end - - sig { returns(Prism::Location) } - def location; end - - sig { returns(Symbol) } - def level; end - - sig { params(type: Symbol, message: String, location: Prism::Location, level: Symbol).void } - def initialize(type, message, location, level); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def inspect; end -end - -class Prism::ParseWarning - sig { returns(Symbol) } - def type; end - - sig { returns(String) } - def message; end - - sig { returns(Prism::Location) } - def location; end - - sig { returns(Symbol) } - def level; end - - sig { params(type: Symbol, message: String, location: Prism::Location, level: Symbol).void } - def initialize(type, message, location, level); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(String) } - def inspect; end -end - -class Prism::Result - sig { params(comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns(T::Array[Prism::Comment]) } - def comments; end - - sig { returns(T::Array[Prism::MagicComment]) } - def magic_comments; end - - sig { returns(T.nilable(Prism::Location)) } - def data_loc; end - - sig { returns(T::Array[Prism::ParseError]) } - def errors; end - - sig { returns(T::Array[Prism::ParseWarning]) } - def warnings; end - - sig { returns(Prism::Source) } - def source; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(Encoding) } - def encoding; end - - sig { returns(T::Boolean) } - def success?; end - - sig { returns(T::Boolean) } - def failure?; end - - sig { params(encoding: Encoding).returns(T.any(Prism::CodeUnitsCache, T.proc.params(byte_offset: Integer).returns(Integer))) } - def code_units_cache(encoding); end -end - -class Prism::ParseResult < Prism::Result - sig { params(value: Prism::ProgramNode, comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns(Prism::ProgramNode) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end -end - -class Prism::LexResult < Prism::Result - sig { params(value: T::Array[T.untyped], comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns(T::Array[T.untyped]) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end -end - -class Prism::ParseLexResult < Prism::Result - sig { params(value: [Prism::ProgramNode, T::Array[T.untyped]], comments: T::Array[Prism::Comment], magic_comments: T::Array[Prism::MagicComment], data_loc: T.nilable(Prism::Location), errors: T::Array[Prism::ParseError], warnings: T::Array[Prism::ParseWarning], source: Prism::Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end - - sig { returns([Prism::ProgramNode, T::Array[T.untyped]]) } - def value; end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end -end - -class Prism::Token - sig { returns(Prism::Source) } - def source; end - - sig { returns(Symbol) } - def type; end - - sig { returns(String) } - def value; end - - sig { params(source: Prism::Source, type: Symbol, value: String, location: T.any(Integer, Prism::Location)).void } - def initialize(source, type, value, location); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - - sig { returns(Prism::Location) } - def location; end - - sig { params(q: T.untyped).void } - def pretty_print(q); end - - sig { params(other: T.untyped).returns(T::Boolean) } - def ==(other); end -end - -class Prism::Scope - sig { returns(T::Array[Symbol]) } - def locals; end - - sig { returns(T::Array[Symbol]) } - def forwarding; end - - sig { params(locals: T::Array[Symbol], forwarding: T::Array[Symbol]).void } - def initialize(locals, forwarding); end -end diff --git a/rbi/prism/reflection.rbi b/rbi/prism/reflection.rbi deleted file mode 100644 index b21e9b5def..0000000000 --- a/rbi/prism/reflection.rbi +++ /dev/null @@ -1,58 +0,0 @@ -# typed: strict - -module Prism::Reflection -end - -class Prism::Reflection::Field - sig { params(name: Symbol).void } - def initialize(name); end - - sig { returns(Symbol) } - def name; end -end - -class Prism::Reflection::NodeField < Prism::Reflection::Field -end - -class Prism::Reflection::OptionalNodeField < Prism::Reflection::Field -end - -class Prism::Reflection::NodeListField < Prism::Reflection::Field -end - -class Prism::Reflection::ConstantField < Prism::Reflection::Field -end - -class Prism::Reflection::OptionalConstantField < Prism::Reflection::Field -end - -class Prism::Reflection::ConstantListField < Prism::Reflection::Field -end - -class Prism::Reflection::StringField < Prism::Reflection::Field -end - -class Prism::Reflection::LocationField < Prism::Reflection::Field -end - -class Prism::Reflection::OptionalLocationField < Prism::Reflection::Field -end - -class Prism::Reflection::IntegerField < Prism::Reflection::Field -end - -class Prism::Reflection::FloatField < Prism::Reflection::Field -end - -class Prism::Reflection::FlagsField < Prism::Reflection::Field - sig { params(name: Symbol, flags: T::Array[Symbol]).void } - def initialize(name, flags); end - - sig { returns(T::Array[Symbol]) } - def flags; end -end - -module Prism::Reflection - sig { params(node: T.class_of(Prism::Node)).returns(T::Array[Prism::Reflection::Field]) } - def self.fields_for(node); end -end diff --git a/rbi/prism/string_query.rbi b/rbi/prism/string_query.rbi deleted file mode 100644 index 3e5bae1572..0000000000 --- a/rbi/prism/string_query.rbi +++ /dev/null @@ -1,12 +0,0 @@ -# typed: strict - -class Prism::StringQuery - sig { params(string: String).returns(T::Boolean) } - def self.local?(string); end - - sig { params(string: String).returns(T::Boolean) } - def self.constant?(string); end - - sig { params(string: String).returns(T::Boolean) } - def self.method_name?(string); end -end diff --git a/rbi/prism/translation/parser_versions.rbi b/rbi/prism/translation/parser_versions.rbi index 8a7297be3e..2aad1be440 100644 --- a/rbi/prism/translation/parser_versions.rbi +++ b/rbi/prism/translation/parser_versions.rbi @@ -21,3 +21,8 @@ class Prism::Translation::Parser40 < Prism::Translation::Parser sig { override.returns(Integer) } def version; end end + +class Prism::Translation::Parser41 < Prism::Translation::Parser + sig { override.returns(Integer) } + def version; end +end diff --git a/sig/generated/prism/dot_visitor.rbs b/sig/generated/prism/dot_visitor.rbs index b471ec741f..2cbc0ee31b 100644 --- a/sig/generated/prism/dot_visitor.rbs +++ b/sig/generated/prism/dot_visitor.rbs @@ -74,461 +74,461 @@ module Prism # : () -> String def to_dot: () -> String - # (AliasGlobalVariableNode) -> void - def visit_alias_global_variable_node: (untyped node) -> untyped + # : (AliasGlobalVariableNode) -> void + def visit_alias_global_variable_node: (AliasGlobalVariableNode) -> void - # (AliasMethodNode) -> void - def visit_alias_method_node: (untyped node) -> untyped + # : (AliasMethodNode) -> void + def visit_alias_method_node: (AliasMethodNode) -> void - # (AlternationPatternNode) -> void - def visit_alternation_pattern_node: (untyped node) -> untyped + # : (AlternationPatternNode) -> void + def visit_alternation_pattern_node: (AlternationPatternNode) -> void - # (AndNode) -> void - def visit_and_node: (untyped node) -> untyped + # : (AndNode) -> void + def visit_and_node: (AndNode) -> void - # (ArgumentsNode) -> void - def visit_arguments_node: (untyped node) -> untyped + # : (ArgumentsNode) -> void + def visit_arguments_node: (ArgumentsNode) -> void - # (ArrayNode) -> void - def visit_array_node: (untyped node) -> untyped + # : (ArrayNode) -> void + def visit_array_node: (ArrayNode) -> void - # (ArrayPatternNode) -> void - def visit_array_pattern_node: (untyped node) -> untyped + # : (ArrayPatternNode) -> void + def visit_array_pattern_node: (ArrayPatternNode) -> void - # (AssocNode) -> void - def visit_assoc_node: (untyped node) -> untyped + # : (AssocNode) -> void + def visit_assoc_node: (AssocNode) -> void - # (AssocSplatNode) -> void - def visit_assoc_splat_node: (untyped node) -> untyped + # : (AssocSplatNode) -> void + def visit_assoc_splat_node: (AssocSplatNode) -> void - # (BackReferenceReadNode) -> void - def visit_back_reference_read_node: (untyped node) -> untyped + # : (BackReferenceReadNode) -> void + def visit_back_reference_read_node: (BackReferenceReadNode) -> void - # (BeginNode) -> void - def visit_begin_node: (untyped node) -> untyped + # : (BeginNode) -> void + def visit_begin_node: (BeginNode) -> void - # (BlockArgumentNode) -> void - def visit_block_argument_node: (untyped node) -> untyped + # : (BlockArgumentNode) -> void + def visit_block_argument_node: (BlockArgumentNode) -> void - # (BlockLocalVariableNode) -> void - def visit_block_local_variable_node: (untyped node) -> untyped + # : (BlockLocalVariableNode) -> void + def visit_block_local_variable_node: (BlockLocalVariableNode) -> void - # (BlockNode) -> void - def visit_block_node: (untyped node) -> untyped + # : (BlockNode) -> void + def visit_block_node: (BlockNode) -> void - # (BlockParameterNode) -> void - def visit_block_parameter_node: (untyped node) -> untyped + # : (BlockParameterNode) -> void + def visit_block_parameter_node: (BlockParameterNode) -> void - # (BlockParametersNode) -> void - def visit_block_parameters_node: (untyped node) -> untyped + # : (BlockParametersNode) -> void + def visit_block_parameters_node: (BlockParametersNode) -> void - # (BreakNode) -> void - def visit_break_node: (untyped node) -> untyped + # : (BreakNode) -> void + def visit_break_node: (BreakNode) -> void - # (CallAndWriteNode) -> void - def visit_call_and_write_node: (untyped node) -> untyped + # : (CallAndWriteNode) -> void + def visit_call_and_write_node: (CallAndWriteNode) -> void - # (CallNode) -> void - def visit_call_node: (untyped node) -> untyped + # : (CallNode) -> void + def visit_call_node: (CallNode) -> void - # (CallOperatorWriteNode) -> void - def visit_call_operator_write_node: (untyped node) -> untyped + # : (CallOperatorWriteNode) -> void + def visit_call_operator_write_node: (CallOperatorWriteNode) -> void - # (CallOrWriteNode) -> void - def visit_call_or_write_node: (untyped node) -> untyped + # : (CallOrWriteNode) -> void + def visit_call_or_write_node: (CallOrWriteNode) -> void - # (CallTargetNode) -> void - def visit_call_target_node: (untyped node) -> untyped + # : (CallTargetNode) -> void + def visit_call_target_node: (CallTargetNode) -> void - # (CapturePatternNode) -> void - def visit_capture_pattern_node: (untyped node) -> untyped + # : (CapturePatternNode) -> void + def visit_capture_pattern_node: (CapturePatternNode) -> void - # (CaseMatchNode) -> void - def visit_case_match_node: (untyped node) -> untyped + # : (CaseMatchNode) -> void + def visit_case_match_node: (CaseMatchNode) -> void - # (CaseNode) -> void - def visit_case_node: (untyped node) -> untyped + # : (CaseNode) -> void + def visit_case_node: (CaseNode) -> void - # (ClassNode) -> void - def visit_class_node: (untyped node) -> untyped + # : (ClassNode) -> void + def visit_class_node: (ClassNode) -> void - # (ClassVariableAndWriteNode) -> void - def visit_class_variable_and_write_node: (untyped node) -> untyped + # : (ClassVariableAndWriteNode) -> void + def visit_class_variable_and_write_node: (ClassVariableAndWriteNode) -> void - # (ClassVariableOperatorWriteNode) -> void - def visit_class_variable_operator_write_node: (untyped node) -> untyped + # : (ClassVariableOperatorWriteNode) -> void + def visit_class_variable_operator_write_node: (ClassVariableOperatorWriteNode) -> void - # (ClassVariableOrWriteNode) -> void - def visit_class_variable_or_write_node: (untyped node) -> untyped + # : (ClassVariableOrWriteNode) -> void + def visit_class_variable_or_write_node: (ClassVariableOrWriteNode) -> void - # (ClassVariableReadNode) -> void - def visit_class_variable_read_node: (untyped node) -> untyped + # : (ClassVariableReadNode) -> void + def visit_class_variable_read_node: (ClassVariableReadNode) -> void - # (ClassVariableTargetNode) -> void - def visit_class_variable_target_node: (untyped node) -> untyped + # : (ClassVariableTargetNode) -> void + def visit_class_variable_target_node: (ClassVariableTargetNode) -> void - # (ClassVariableWriteNode) -> void - def visit_class_variable_write_node: (untyped node) -> untyped + # : (ClassVariableWriteNode) -> void + def visit_class_variable_write_node: (ClassVariableWriteNode) -> void - # (ConstantAndWriteNode) -> void - def visit_constant_and_write_node: (untyped node) -> untyped + # : (ConstantAndWriteNode) -> void + def visit_constant_and_write_node: (ConstantAndWriteNode) -> void - # (ConstantOperatorWriteNode) -> void - def visit_constant_operator_write_node: (untyped node) -> untyped + # : (ConstantOperatorWriteNode) -> void + def visit_constant_operator_write_node: (ConstantOperatorWriteNode) -> void - # (ConstantOrWriteNode) -> void - def visit_constant_or_write_node: (untyped node) -> untyped + # : (ConstantOrWriteNode) -> void + def visit_constant_or_write_node: (ConstantOrWriteNode) -> void - # (ConstantPathAndWriteNode) -> void - def visit_constant_path_and_write_node: (untyped node) -> untyped + # : (ConstantPathAndWriteNode) -> void + def visit_constant_path_and_write_node: (ConstantPathAndWriteNode) -> void - # (ConstantPathNode) -> void - def visit_constant_path_node: (untyped node) -> untyped + # : (ConstantPathNode) -> void + def visit_constant_path_node: (ConstantPathNode) -> void - # (ConstantPathOperatorWriteNode) -> void - def visit_constant_path_operator_write_node: (untyped node) -> untyped + # : (ConstantPathOperatorWriteNode) -> void + def visit_constant_path_operator_write_node: (ConstantPathOperatorWriteNode) -> void - # (ConstantPathOrWriteNode) -> void - def visit_constant_path_or_write_node: (untyped node) -> untyped + # : (ConstantPathOrWriteNode) -> void + def visit_constant_path_or_write_node: (ConstantPathOrWriteNode) -> void - # (ConstantPathTargetNode) -> void - def visit_constant_path_target_node: (untyped node) -> untyped + # : (ConstantPathTargetNode) -> void + def visit_constant_path_target_node: (ConstantPathTargetNode) -> void - # (ConstantPathWriteNode) -> void - def visit_constant_path_write_node: (untyped node) -> untyped + # : (ConstantPathWriteNode) -> void + def visit_constant_path_write_node: (ConstantPathWriteNode) -> void - # (ConstantReadNode) -> void - def visit_constant_read_node: (untyped node) -> untyped + # : (ConstantReadNode) -> void + def visit_constant_read_node: (ConstantReadNode) -> void - # (ConstantTargetNode) -> void - def visit_constant_target_node: (untyped node) -> untyped + # : (ConstantTargetNode) -> void + def visit_constant_target_node: (ConstantTargetNode) -> void - # (ConstantWriteNode) -> void - def visit_constant_write_node: (untyped node) -> untyped + # : (ConstantWriteNode) -> void + def visit_constant_write_node: (ConstantWriteNode) -> void - # (DefNode) -> void - def visit_def_node: (untyped node) -> untyped + # : (DefNode) -> void + def visit_def_node: (DefNode) -> void - # (DefinedNode) -> void - def visit_defined_node: (untyped node) -> untyped + # : (DefinedNode) -> void + def visit_defined_node: (DefinedNode) -> void - # (ElseNode) -> void - def visit_else_node: (untyped node) -> untyped + # : (ElseNode) -> void + def visit_else_node: (ElseNode) -> void - # (EmbeddedStatementsNode) -> void - def visit_embedded_statements_node: (untyped node) -> untyped + # : (EmbeddedStatementsNode) -> void + def visit_embedded_statements_node: (EmbeddedStatementsNode) -> void - # (EmbeddedVariableNode) -> void - def visit_embedded_variable_node: (untyped node) -> untyped + # : (EmbeddedVariableNode) -> void + def visit_embedded_variable_node: (EmbeddedVariableNode) -> void - # (EnsureNode) -> void - def visit_ensure_node: (untyped node) -> untyped + # : (EnsureNode) -> void + def visit_ensure_node: (EnsureNode) -> void - # (FalseNode) -> void - def visit_false_node: (untyped node) -> untyped + # : (FalseNode) -> void + def visit_false_node: (FalseNode) -> void - # (FindPatternNode) -> void - def visit_find_pattern_node: (untyped node) -> untyped + # : (FindPatternNode) -> void + def visit_find_pattern_node: (FindPatternNode) -> void - # (FlipFlopNode) -> void - def visit_flip_flop_node: (untyped node) -> untyped + # : (FlipFlopNode) -> void + def visit_flip_flop_node: (FlipFlopNode) -> void - # (FloatNode) -> void - def visit_float_node: (untyped node) -> untyped + # : (FloatNode) -> void + def visit_float_node: (FloatNode) -> void - # (ForNode) -> void - def visit_for_node: (untyped node) -> untyped + # : (ForNode) -> void + def visit_for_node: (ForNode) -> void - # (ForwardingArgumentsNode) -> void - def visit_forwarding_arguments_node: (untyped node) -> untyped + # : (ForwardingArgumentsNode) -> void + def visit_forwarding_arguments_node: (ForwardingArgumentsNode) -> void - # (ForwardingParameterNode) -> void - def visit_forwarding_parameter_node: (untyped node) -> untyped + # : (ForwardingParameterNode) -> void + def visit_forwarding_parameter_node: (ForwardingParameterNode) -> void - # (ForwardingSuperNode) -> void - def visit_forwarding_super_node: (untyped node) -> untyped + # : (ForwardingSuperNode) -> void + def visit_forwarding_super_node: (ForwardingSuperNode) -> void - # (GlobalVariableAndWriteNode) -> void - def visit_global_variable_and_write_node: (untyped node) -> untyped + # : (GlobalVariableAndWriteNode) -> void + def visit_global_variable_and_write_node: (GlobalVariableAndWriteNode) -> void - # (GlobalVariableOperatorWriteNode) -> void - def visit_global_variable_operator_write_node: (untyped node) -> untyped + # : (GlobalVariableOperatorWriteNode) -> void + def visit_global_variable_operator_write_node: (GlobalVariableOperatorWriteNode) -> void - # (GlobalVariableOrWriteNode) -> void - def visit_global_variable_or_write_node: (untyped node) -> untyped + # : (GlobalVariableOrWriteNode) -> void + def visit_global_variable_or_write_node: (GlobalVariableOrWriteNode) -> void - # (GlobalVariableReadNode) -> void - def visit_global_variable_read_node: (untyped node) -> untyped + # : (GlobalVariableReadNode) -> void + def visit_global_variable_read_node: (GlobalVariableReadNode) -> void - # (GlobalVariableTargetNode) -> void - def visit_global_variable_target_node: (untyped node) -> untyped + # : (GlobalVariableTargetNode) -> void + def visit_global_variable_target_node: (GlobalVariableTargetNode) -> void - # (GlobalVariableWriteNode) -> void - def visit_global_variable_write_node: (untyped node) -> untyped + # : (GlobalVariableWriteNode) -> void + def visit_global_variable_write_node: (GlobalVariableWriteNode) -> void - # (HashNode) -> void - def visit_hash_node: (untyped node) -> untyped + # : (HashNode) -> void + def visit_hash_node: (HashNode) -> void - # (HashPatternNode) -> void - def visit_hash_pattern_node: (untyped node) -> untyped + # : (HashPatternNode) -> void + def visit_hash_pattern_node: (HashPatternNode) -> void - # (IfNode) -> void - def visit_if_node: (untyped node) -> untyped + # : (IfNode) -> void + def visit_if_node: (IfNode) -> void - # (ImaginaryNode) -> void - def visit_imaginary_node: (untyped node) -> untyped + # : (ImaginaryNode) -> void + def visit_imaginary_node: (ImaginaryNode) -> void - # (ImplicitNode) -> void - def visit_implicit_node: (untyped node) -> untyped + # : (ImplicitNode) -> void + def visit_implicit_node: (ImplicitNode) -> void - # (ImplicitRestNode) -> void - def visit_implicit_rest_node: (untyped node) -> untyped + # : (ImplicitRestNode) -> void + def visit_implicit_rest_node: (ImplicitRestNode) -> void - # (InNode) -> void - def visit_in_node: (untyped node) -> untyped + # : (InNode) -> void + def visit_in_node: (InNode) -> void - # (IndexAndWriteNode) -> void - def visit_index_and_write_node: (untyped node) -> untyped + # : (IndexAndWriteNode) -> void + def visit_index_and_write_node: (IndexAndWriteNode) -> void - # (IndexOperatorWriteNode) -> void - def visit_index_operator_write_node: (untyped node) -> untyped + # : (IndexOperatorWriteNode) -> void + def visit_index_operator_write_node: (IndexOperatorWriteNode) -> void - # (IndexOrWriteNode) -> void - def visit_index_or_write_node: (untyped node) -> untyped + # : (IndexOrWriteNode) -> void + def visit_index_or_write_node: (IndexOrWriteNode) -> void - # (IndexTargetNode) -> void - def visit_index_target_node: (untyped node) -> untyped + # : (IndexTargetNode) -> void + def visit_index_target_node: (IndexTargetNode) -> void - # (InstanceVariableAndWriteNode) -> void - def visit_instance_variable_and_write_node: (untyped node) -> untyped + # : (InstanceVariableAndWriteNode) -> void + def visit_instance_variable_and_write_node: (InstanceVariableAndWriteNode) -> void - # (InstanceVariableOperatorWriteNode) -> void - def visit_instance_variable_operator_write_node: (untyped node) -> untyped + # : (InstanceVariableOperatorWriteNode) -> void + def visit_instance_variable_operator_write_node: (InstanceVariableOperatorWriteNode) -> void - # (InstanceVariableOrWriteNode) -> void - def visit_instance_variable_or_write_node: (untyped node) -> untyped + # : (InstanceVariableOrWriteNode) -> void + def visit_instance_variable_or_write_node: (InstanceVariableOrWriteNode) -> void - # (InstanceVariableReadNode) -> void - def visit_instance_variable_read_node: (untyped node) -> untyped + # : (InstanceVariableReadNode) -> void + def visit_instance_variable_read_node: (InstanceVariableReadNode) -> void - # (InstanceVariableTargetNode) -> void - def visit_instance_variable_target_node: (untyped node) -> untyped + # : (InstanceVariableTargetNode) -> void + def visit_instance_variable_target_node: (InstanceVariableTargetNode) -> void - # (InstanceVariableWriteNode) -> void - def visit_instance_variable_write_node: (untyped node) -> untyped + # : (InstanceVariableWriteNode) -> void + def visit_instance_variable_write_node: (InstanceVariableWriteNode) -> void - # (IntegerNode) -> void - def visit_integer_node: (untyped node) -> untyped + # : (IntegerNode) -> void + def visit_integer_node: (IntegerNode) -> void - # (InterpolatedMatchLastLineNode) -> void - def visit_interpolated_match_last_line_node: (untyped node) -> untyped + # : (InterpolatedMatchLastLineNode) -> void + def visit_interpolated_match_last_line_node: (InterpolatedMatchLastLineNode) -> void - # (InterpolatedRegularExpressionNode) -> void - def visit_interpolated_regular_expression_node: (untyped node) -> untyped + # : (InterpolatedRegularExpressionNode) -> void + def visit_interpolated_regular_expression_node: (InterpolatedRegularExpressionNode) -> void - # (InterpolatedStringNode) -> void - def visit_interpolated_string_node: (untyped node) -> untyped + # : (InterpolatedStringNode) -> void + def visit_interpolated_string_node: (InterpolatedStringNode) -> void - # (InterpolatedSymbolNode) -> void - def visit_interpolated_symbol_node: (untyped node) -> untyped + # : (InterpolatedSymbolNode) -> void + def visit_interpolated_symbol_node: (InterpolatedSymbolNode) -> void - # (InterpolatedXStringNode) -> void - def visit_interpolated_x_string_node: (untyped node) -> untyped + # : (InterpolatedXStringNode) -> void + def visit_interpolated_x_string_node: (InterpolatedXStringNode) -> void - # (ItLocalVariableReadNode) -> void - def visit_it_local_variable_read_node: (untyped node) -> untyped + # : (ItLocalVariableReadNode) -> void + def visit_it_local_variable_read_node: (ItLocalVariableReadNode) -> void - # (ItParametersNode) -> void - def visit_it_parameters_node: (untyped node) -> untyped + # : (ItParametersNode) -> void + def visit_it_parameters_node: (ItParametersNode) -> void - # (KeywordHashNode) -> void - def visit_keyword_hash_node: (untyped node) -> untyped + # : (KeywordHashNode) -> void + def visit_keyword_hash_node: (KeywordHashNode) -> void - # (KeywordRestParameterNode) -> void - def visit_keyword_rest_parameter_node: (untyped node) -> untyped + # : (KeywordRestParameterNode) -> void + def visit_keyword_rest_parameter_node: (KeywordRestParameterNode) -> void - # (LambdaNode) -> void - def visit_lambda_node: (untyped node) -> untyped + # : (LambdaNode) -> void + def visit_lambda_node: (LambdaNode) -> void - # (LocalVariableAndWriteNode) -> void - def visit_local_variable_and_write_node: (untyped node) -> untyped + # : (LocalVariableAndWriteNode) -> void + def visit_local_variable_and_write_node: (LocalVariableAndWriteNode) -> void - # (LocalVariableOperatorWriteNode) -> void - def visit_local_variable_operator_write_node: (untyped node) -> untyped + # : (LocalVariableOperatorWriteNode) -> void + def visit_local_variable_operator_write_node: (LocalVariableOperatorWriteNode) -> void - # (LocalVariableOrWriteNode) -> void - def visit_local_variable_or_write_node: (untyped node) -> untyped + # : (LocalVariableOrWriteNode) -> void + def visit_local_variable_or_write_node: (LocalVariableOrWriteNode) -> void - # (LocalVariableReadNode) -> void - def visit_local_variable_read_node: (untyped node) -> untyped + # : (LocalVariableReadNode) -> void + def visit_local_variable_read_node: (LocalVariableReadNode) -> void - # (LocalVariableTargetNode) -> void - def visit_local_variable_target_node: (untyped node) -> untyped + # : (LocalVariableTargetNode) -> void + def visit_local_variable_target_node: (LocalVariableTargetNode) -> void - # (LocalVariableWriteNode) -> void - def visit_local_variable_write_node: (untyped node) -> untyped + # : (LocalVariableWriteNode) -> void + def visit_local_variable_write_node: (LocalVariableWriteNode) -> void - # (MatchLastLineNode) -> void - def visit_match_last_line_node: (untyped node) -> untyped + # : (MatchLastLineNode) -> void + def visit_match_last_line_node: (MatchLastLineNode) -> void - # (MatchPredicateNode) -> void - def visit_match_predicate_node: (untyped node) -> untyped + # : (MatchPredicateNode) -> void + def visit_match_predicate_node: (MatchPredicateNode) -> void - # (MatchRequiredNode) -> void - def visit_match_required_node: (untyped node) -> untyped + # : (MatchRequiredNode) -> void + def visit_match_required_node: (MatchRequiredNode) -> void - # (MatchWriteNode) -> void - def visit_match_write_node: (untyped node) -> untyped + # : (MatchWriteNode) -> void + def visit_match_write_node: (MatchWriteNode) -> void - # (MissingNode) -> void - def visit_missing_node: (untyped node) -> untyped + # : (MissingNode) -> void + def visit_missing_node: (MissingNode) -> void - # (ModuleNode) -> void - def visit_module_node: (untyped node) -> untyped + # : (ModuleNode) -> void + def visit_module_node: (ModuleNode) -> void - # (MultiTargetNode) -> void - def visit_multi_target_node: (untyped node) -> untyped + # : (MultiTargetNode) -> void + def visit_multi_target_node: (MultiTargetNode) -> void - # (MultiWriteNode) -> void - def visit_multi_write_node: (untyped node) -> untyped + # : (MultiWriteNode) -> void + def visit_multi_write_node: (MultiWriteNode) -> void - # (NextNode) -> void - def visit_next_node: (untyped node) -> untyped + # : (NextNode) -> void + def visit_next_node: (NextNode) -> void - # (NilNode) -> void - def visit_nil_node: (untyped node) -> untyped + # : (NilNode) -> void + def visit_nil_node: (NilNode) -> void - # (NoBlockParameterNode) -> void - def visit_no_block_parameter_node: (untyped node) -> untyped + # : (NoBlockParameterNode) -> void + def visit_no_block_parameter_node: (NoBlockParameterNode) -> void - # (NoKeywordsParameterNode) -> void - def visit_no_keywords_parameter_node: (untyped node) -> untyped + # : (NoKeywordsParameterNode) -> void + def visit_no_keywords_parameter_node: (NoKeywordsParameterNode) -> void - # (NumberedParametersNode) -> void - def visit_numbered_parameters_node: (untyped node) -> untyped + # : (NumberedParametersNode) -> void + def visit_numbered_parameters_node: (NumberedParametersNode) -> void - # (NumberedReferenceReadNode) -> void - def visit_numbered_reference_read_node: (untyped node) -> untyped + # : (NumberedReferenceReadNode) -> void + def visit_numbered_reference_read_node: (NumberedReferenceReadNode) -> void - # (OptionalKeywordParameterNode) -> void - def visit_optional_keyword_parameter_node: (untyped node) -> untyped + # : (OptionalKeywordParameterNode) -> void + def visit_optional_keyword_parameter_node: (OptionalKeywordParameterNode) -> void - # (OptionalParameterNode) -> void - def visit_optional_parameter_node: (untyped node) -> untyped + # : (OptionalParameterNode) -> void + def visit_optional_parameter_node: (OptionalParameterNode) -> void - # (OrNode) -> void - def visit_or_node: (untyped node) -> untyped + # : (OrNode) -> void + def visit_or_node: (OrNode) -> void - # (ParametersNode) -> void - def visit_parameters_node: (untyped node) -> untyped + # : (ParametersNode) -> void + def visit_parameters_node: (ParametersNode) -> void - # (ParenthesesNode) -> void - def visit_parentheses_node: (untyped node) -> untyped + # : (ParenthesesNode) -> void + def visit_parentheses_node: (ParenthesesNode) -> void - # (PinnedExpressionNode) -> void - def visit_pinned_expression_node: (untyped node) -> untyped + # : (PinnedExpressionNode) -> void + def visit_pinned_expression_node: (PinnedExpressionNode) -> void - # (PinnedVariableNode) -> void - def visit_pinned_variable_node: (untyped node) -> untyped + # : (PinnedVariableNode) -> void + def visit_pinned_variable_node: (PinnedVariableNode) -> void - # (PostExecutionNode) -> void - def visit_post_execution_node: (untyped node) -> untyped + # : (PostExecutionNode) -> void + def visit_post_execution_node: (PostExecutionNode) -> void - # (PreExecutionNode) -> void - def visit_pre_execution_node: (untyped node) -> untyped + # : (PreExecutionNode) -> void + def visit_pre_execution_node: (PreExecutionNode) -> void - # (ProgramNode) -> void - def visit_program_node: (untyped node) -> untyped + # : (ProgramNode) -> void + def visit_program_node: (ProgramNode) -> void - # (RangeNode) -> void - def visit_range_node: (untyped node) -> untyped + # : (RangeNode) -> void + def visit_range_node: (RangeNode) -> void - # (RationalNode) -> void - def visit_rational_node: (untyped node) -> untyped + # : (RationalNode) -> void + def visit_rational_node: (RationalNode) -> void - # (RedoNode) -> void - def visit_redo_node: (untyped node) -> untyped + # : (RedoNode) -> void + def visit_redo_node: (RedoNode) -> void - # (RegularExpressionNode) -> void - def visit_regular_expression_node: (untyped node) -> untyped + # : (RegularExpressionNode) -> void + def visit_regular_expression_node: (RegularExpressionNode) -> void - # (RequiredKeywordParameterNode) -> void - def visit_required_keyword_parameter_node: (untyped node) -> untyped + # : (RequiredKeywordParameterNode) -> void + def visit_required_keyword_parameter_node: (RequiredKeywordParameterNode) -> void - # (RequiredParameterNode) -> void - def visit_required_parameter_node: (untyped node) -> untyped + # : (RequiredParameterNode) -> void + def visit_required_parameter_node: (RequiredParameterNode) -> void - # (RescueModifierNode) -> void - def visit_rescue_modifier_node: (untyped node) -> untyped + # : (RescueModifierNode) -> void + def visit_rescue_modifier_node: (RescueModifierNode) -> void - # (RescueNode) -> void - def visit_rescue_node: (untyped node) -> untyped + # : (RescueNode) -> void + def visit_rescue_node: (RescueNode) -> void - # (RestParameterNode) -> void - def visit_rest_parameter_node: (untyped node) -> untyped + # : (RestParameterNode) -> void + def visit_rest_parameter_node: (RestParameterNode) -> void - # (RetryNode) -> void - def visit_retry_node: (untyped node) -> untyped + # : (RetryNode) -> void + def visit_retry_node: (RetryNode) -> void - # (ReturnNode) -> void - def visit_return_node: (untyped node) -> untyped + # : (ReturnNode) -> void + def visit_return_node: (ReturnNode) -> void - # (SelfNode) -> void - def visit_self_node: (untyped node) -> untyped + # : (SelfNode) -> void + def visit_self_node: (SelfNode) -> void - # (ShareableConstantNode) -> void - def visit_shareable_constant_node: (untyped node) -> untyped + # : (ShareableConstantNode) -> void + def visit_shareable_constant_node: (ShareableConstantNode) -> void - # (SingletonClassNode) -> void - def visit_singleton_class_node: (untyped node) -> untyped + # : (SingletonClassNode) -> void + def visit_singleton_class_node: (SingletonClassNode) -> void - # (SourceEncodingNode) -> void - def visit_source_encoding_node: (untyped node) -> untyped + # : (SourceEncodingNode) -> void + def visit_source_encoding_node: (SourceEncodingNode) -> void - # (SourceFileNode) -> void - def visit_source_file_node: (untyped node) -> untyped + # : (SourceFileNode) -> void + def visit_source_file_node: (SourceFileNode) -> void - # (SourceLineNode) -> void - def visit_source_line_node: (untyped node) -> untyped + # : (SourceLineNode) -> void + def visit_source_line_node: (SourceLineNode) -> void - # (SplatNode) -> void - def visit_splat_node: (untyped node) -> untyped + # : (SplatNode) -> void + def visit_splat_node: (SplatNode) -> void - # (StatementsNode) -> void - def visit_statements_node: (untyped node) -> untyped + # : (StatementsNode) -> void + def visit_statements_node: (StatementsNode) -> void - # (StringNode) -> void - def visit_string_node: (untyped node) -> untyped + # : (StringNode) -> void + def visit_string_node: (StringNode) -> void - # (SuperNode) -> void - def visit_super_node: (untyped node) -> untyped + # : (SuperNode) -> void + def visit_super_node: (SuperNode) -> void - # (SymbolNode) -> void - def visit_symbol_node: (untyped node) -> untyped + # : (SymbolNode) -> void + def visit_symbol_node: (SymbolNode) -> void - # (TrueNode) -> void - def visit_true_node: (untyped node) -> untyped + # : (TrueNode) -> void + def visit_true_node: (TrueNode) -> void - # (UndefNode) -> void - def visit_undef_node: (untyped node) -> untyped + # : (UndefNode) -> void + def visit_undef_node: (UndefNode) -> void - # (UnlessNode) -> void - def visit_unless_node: (untyped node) -> untyped + # : (UnlessNode) -> void + def visit_unless_node: (UnlessNode) -> void - # (UntilNode) -> void - def visit_until_node: (untyped node) -> untyped + # : (UntilNode) -> void + def visit_until_node: (UntilNode) -> void - # (WhenNode) -> void - def visit_when_node: (untyped node) -> untyped + # : (WhenNode) -> void + def visit_when_node: (WhenNode) -> void - # (WhileNode) -> void - def visit_while_node: (untyped node) -> untyped + # : (WhileNode) -> void + def visit_while_node: (WhileNode) -> void - # (XStringNode) -> void - def visit_x_string_node: (untyped node) -> untyped + # : (XStringNode) -> void + def visit_x_string_node: (XStringNode) -> void - # (YieldNode) -> void - def visit_yield_node: (untyped node) -> untyped + # : (YieldNode) -> void + def visit_yield_node: (YieldNode) -> void private diff --git a/sig/generated/prism/lex_compat.rbs b/sig/generated/prism/lex_compat.rbs index 4c9e6d9c16..d6bf985b0a 100644 --- a/sig/generated/prism/lex_compat.rbs +++ b/sig/generated/prism/lex_compat.rbs @@ -3,7 +3,16 @@ module Prism module Translation class Ripper + EXPR_NONE: Integer EXPR_BEG: Integer + EXPR_MID: Integer + EXPR_END: Integer + EXPR_CLASS: Integer + EXPR_VALUE: Integer + EXPR_ARG: Integer + EXPR_CMDARG: Integer + EXPR_ENDARG: Integer + EXPR_ENDFN: Integer class Lexer < Ripper class State diff --git a/sig/generated/prism/node.rbs b/sig/generated/prism/node.rbs index 032c26056a..bb42a24caf 100644 --- a/sig/generated/prism/node.rbs +++ b/sig/generated/prism/node.rbs @@ -240,10 +240,10 @@ module Prism # an enumerator that contains each child node. Excludes any `nil`s in # the place of optional nodes that were not present. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # Returns an array of child nodes, excluding any `nil`s in the place of # optional nodes that were not present. @@ -315,10 +315,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -405,8 +405,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `alias` keyword to alias a method. @@ -437,10 +437,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -539,8 +539,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an alternation pattern in pattern matching. @@ -571,10 +571,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -661,8 +661,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&` operator or the `and` keyword. @@ -693,10 +693,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -789,8 +789,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a set of arguments to a method or a keyword. @@ -817,10 +817,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -899,8 +899,8 @@ module Prism # : () -> Array[Prism::node] def arguments: () -> Array[Prism::node] - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i. @@ -931,10 +931,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1044,8 +1044,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an array pattern in pattern matching. @@ -1094,10 +1094,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1239,8 +1239,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a hash key/value pair. @@ -1271,10 +1271,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1370,8 +1370,8 @@ module Prism # : () -> String? def operator: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a splat in a hash literal. @@ -1400,10 +1400,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1479,8 +1479,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents reading a reference to a field in the previous match. @@ -1507,10 +1507,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1560,8 +1560,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a begin statement. @@ -1600,10 +1600,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1739,8 +1739,8 @@ module Prism # : () -> String? def end_keyword: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a block argument using `&`. @@ -1769,10 +1769,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1848,8 +1848,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a block local variable. @@ -1876,10 +1876,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -1934,8 +1934,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a block of ruby code. @@ -1970,10 +1970,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -2102,8 +2102,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a block parameter of a method, block, or lambda definition. @@ -2135,10 +2135,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -2241,8 +2241,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a block's parameters declaration. @@ -2279,10 +2279,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -2412,8 +2412,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `break` keyword. @@ -2442,10 +2442,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -2521,8 +2521,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator on a call. @@ -2561,10 +2561,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -2751,8 +2751,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a method call, in all of the various forms that can take. @@ -2810,10 +2810,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -3066,8 +3066,8 @@ module Prism # : () -> String? def equal: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of an assignment operator on a call. @@ -3108,10 +3108,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -3301,8 +3301,8 @@ module Prism # : () -> String? def message: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator on a call. @@ -3341,10 +3341,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -3531,8 +3531,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to a method call. @@ -3573,10 +3573,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -3714,8 +3714,8 @@ module Prism # : () -> String def message: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to a local variable in pattern matching. @@ -3746,10 +3746,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -3836,8 +3836,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of a case statement for pattern matching. @@ -3874,10 +3874,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4002,8 +4002,8 @@ module Prism # : () -> String def end_keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of a case statement. @@ -4040,10 +4040,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4168,8 +4168,8 @@ module Prism # : () -> String def end_keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a class declaration involving the `class` keyword. @@ -4210,10 +4210,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4381,8 +4381,8 @@ module Prism # : () -> String def end_keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator for assignment to a class variable. @@ -4415,10 +4415,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4524,8 +4524,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to a class variable using an operator that isn't `=`. @@ -4560,10 +4560,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4657,8 +4657,8 @@ module Prism # : () -> Symbol def binary_operator: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator for assignment to a class variable. @@ -4691,10 +4691,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4788,8 +4788,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents referencing a class variable. @@ -4816,10 +4816,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4869,8 +4869,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a class variable in a context that doesn't have an explicit value. @@ -4897,10 +4897,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -4946,8 +4946,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a class variable. @@ -4980,10 +4980,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5093,8 +5093,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator for assignment to a constant. @@ -5127,10 +5127,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5224,8 +5224,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to a constant using an operator that isn't `=`. @@ -5260,10 +5260,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5357,8 +5357,8 @@ module Prism # : () -> Symbol def binary_operator: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator for assignment to a constant. @@ -5391,10 +5391,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5488,8 +5488,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator for assignment to a constant path. @@ -5520,10 +5520,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5601,8 +5601,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents accessing a constant through a path of `::` operators. @@ -5635,10 +5635,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5753,8 +5753,8 @@ module Prism # : () -> String def delimiter: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to a constant path using an operator that isn't `=`. @@ -5787,10 +5787,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5868,8 +5868,8 @@ module Prism # : () -> Symbol def binary_operator: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator for assignment to a constant path. @@ -5900,10 +5900,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -5981,8 +5981,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a constant path in a context that doesn't have an explicit value. @@ -6015,10 +6015,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -6112,8 +6112,8 @@ module Prism # : () -> String def delimiter: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a constant path. @@ -6150,10 +6150,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -6243,8 +6243,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents referencing a constant. @@ -6271,10 +6271,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -6324,8 +6324,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a constant in a context that doesn't have an explicit value. @@ -6352,10 +6352,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -6401,8 +6401,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a constant. @@ -6435,10 +6435,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -6548,8 +6548,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a method definition. @@ -6599,10 +6599,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -6840,8 +6840,8 @@ module Prism # : () -> String? def end_keyword: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `defined?` keyword. @@ -6874,10 +6874,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -6995,8 +6995,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an `else` clause in a `case`, `if`, or `unless` statement. @@ -7027,10 +7027,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7124,8 +7124,8 @@ module Prism # : () -> String? def end_keyword: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an interpolated set of statements. @@ -7156,10 +7156,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7253,8 +7253,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an interpolated variable. @@ -7283,10 +7283,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7356,8 +7356,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an `ensure` clause in a `begin` statement. @@ -7392,10 +7392,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7489,8 +7489,8 @@ module Prism # : () -> String def end_keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the literal `false` keyword. @@ -7515,10 +7515,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7556,8 +7556,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a find pattern in pattern matching. @@ -7603,10 +7603,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7757,8 +7757,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `..` or `...` operators to create flip flops. @@ -7789,10 +7789,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7876,8 +7876,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a floating point number literal. @@ -7904,10 +7904,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -7953,8 +7953,8 @@ module Prism # : () -> Float def value: () -> Float - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `for` keyword. @@ -7993,10 +7993,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8177,8 +8177,8 @@ module Prism # : () -> String def end_keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents forwarding all arguments to this method to another method. @@ -8205,10 +8205,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8246,8 +8246,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the forwarding parameter in a method, block, or lambda declaration. @@ -8273,10 +8273,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8314,8 +8314,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `super` keyword without parentheses or arguments, but which might have a block. @@ -8347,10 +8347,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8396,8 +8396,8 @@ module Prism # : () -> BlockNode? def block: () -> BlockNode? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator for assignment to a global variable. @@ -8430,10 +8430,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8527,8 +8527,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to a global variable using an operator that isn't `=`. @@ -8563,10 +8563,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8660,8 +8660,8 @@ module Prism # : () -> Symbol def binary_operator: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator for assignment to a global variable. @@ -8694,10 +8694,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8791,8 +8791,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents referencing a global variable. @@ -8819,10 +8819,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8872,8 +8872,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a global variable in a context that doesn't have an explicit value. @@ -8900,10 +8900,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -8949,8 +8949,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a global variable. @@ -8983,10 +8983,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -9096,8 +9096,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a hash literal. @@ -9128,10 +9128,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -9237,8 +9237,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a hash pattern in pattern matching. @@ -9282,10 +9282,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -9425,8 +9425,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `if` keyword, either in the block form or the modifier form, or a ternary expression. @@ -9469,10 +9469,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -9652,8 +9652,8 @@ module Prism # : () -> String? def end_keyword: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an imaginary number literal. @@ -9680,10 +9680,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -9729,8 +9729,8 @@ module Prism # : () -> (FloatNode | IntegerNode | RationalNode) def numeric: () -> (FloatNode | IntegerNode | RationalNode) - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source. @@ -9763,10 +9763,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -9812,8 +9812,8 @@ module Prism # : () -> (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) def value: () -> (LocalVariableReadNode | CallNode | ConstantReadNode | LocalVariableTargetNode) - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents using a trailing comma to indicate an implicit rest parameter. @@ -9847,10 +9847,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -9888,8 +9888,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `in` keyword in a case statement. @@ -9922,10 +9922,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -10027,8 +10027,8 @@ module Prism # : () -> String? def then: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator on a call to the `[]` method. @@ -10069,10 +10069,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -10262,8 +10262,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of an assignment operator on a call to `[]`. @@ -10306,10 +10306,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -10499,8 +10499,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator on a call to `[]`. @@ -10541,10 +10541,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -10734,8 +10734,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to an index. @@ -10778,10 +10778,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -10915,8 +10915,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator for assignment to an instance variable. @@ -10949,10 +10949,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11046,8 +11046,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to an instance variable using an operator that isn't `=`. @@ -11082,10 +11082,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11179,8 +11179,8 @@ module Prism # : () -> Symbol def binary_operator: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator for assignment to an instance variable. @@ -11213,10 +11213,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11310,8 +11310,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents referencing an instance variable. @@ -11338,10 +11338,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11391,8 +11391,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to an instance variable in a context that doesn't have an explicit value. @@ -11419,10 +11419,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11468,8 +11468,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to an instance variable. @@ -11502,10 +11502,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11615,8 +11615,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an integer number literal. @@ -11643,10 +11643,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11716,8 +11716,8 @@ module Prism # : () -> Integer def value: () -> Integer - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object. @@ -11748,10 +11748,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -11911,8 +11911,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a regular expression literal that contains interpolation. @@ -11943,10 +11943,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12106,8 +12106,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a string literal that contains interpolation. @@ -12138,10 +12138,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12247,8 +12247,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a symbol literal that contains interpolation. @@ -12279,10 +12279,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12376,8 +12376,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an xstring literal that contains interpolation. @@ -12408,10 +12408,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12505,8 +12505,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents reading from the implicit `it` local variable. @@ -12531,10 +12531,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12572,8 +12572,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda. @@ -12598,10 +12598,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12639,8 +12639,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a hash literal without opening and closing braces. @@ -12667,10 +12667,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12722,8 +12722,8 @@ module Prism # : () -> Array[AssocNode | AssocSplatNode] def elements: () -> Array[AssocNode | AssocSplatNode] - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a keyword rest parameter to a method, block, or lambda definition. @@ -12755,10 +12755,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -12850,8 +12850,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents using a lambda literal (not the lambda method call). @@ -12888,10 +12888,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -13025,8 +13025,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `&&=` operator for assignment to a local variable. @@ -13061,10 +13061,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -13166,8 +13166,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents assigning to a local variable using an operator that isn't `=`. @@ -13204,10 +13204,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -13309,8 +13309,8 @@ module Prism # : () -> Integer def depth: () -> Integer - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||=` operator for assignment to a local variable. @@ -13345,10 +13345,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -13450,8 +13450,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call. @@ -13480,10 +13480,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -13551,8 +13551,8 @@ module Prism # : () -> Integer def depth: () -> Integer - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a local variable in a context that doesn't have an explicit value. @@ -13584,10 +13584,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -13641,8 +13641,8 @@ module Prism # : () -> Integer def depth: () -> Integer - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing to a local variable. @@ -13677,10 +13677,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -13808,8 +13808,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object. @@ -13842,10 +13842,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -14029,8 +14029,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the modifier `in` operator. @@ -14061,10 +14061,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -14142,8 +14142,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `=>` operator. @@ -14174,10 +14174,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -14303,8 +14303,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents writing local variables using a regular expression match with named capture groups. @@ -14333,10 +14333,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -14390,8 +14390,8 @@ module Prism # : () -> Array[LocalVariableTargetNode] def targets: () -> Array[LocalVariableTargetNode] - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a node that is missing from the source and results in a syntax error. @@ -14413,10 +14413,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -14454,8 +14454,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a module declaration involving the `module` keyword. @@ -14492,10 +14492,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -14613,8 +14613,8 @@ module Prism # : () -> String def end_keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a multi-target expression. @@ -14654,10 +14654,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -14797,8 +14797,8 @@ module Prism # : () -> String? def rparen: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a write to a multi-target expression. @@ -14837,10 +14837,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15018,8 +15018,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `next` keyword. @@ -15048,10 +15048,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15121,8 +15121,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `nil` keyword. @@ -15147,10 +15147,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15188,8 +15188,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of `&nil` inside method arguments. @@ -15219,10 +15219,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15308,8 +15308,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of `**nil` inside method arguments. @@ -15339,10 +15339,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15428,8 +15428,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an implicit set of parameters through the use of numbered parameters within a block or lambda. @@ -15456,10 +15456,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15505,8 +15505,8 @@ module Prism # : () -> Integer def maximum: () -> Integer - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents reading a numbered reference to a capture in the previous match. @@ -15533,10 +15533,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15588,8 +15588,8 @@ module Prism # : () -> Integer def number: () -> Integer - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an optional keyword parameter to a method, block, or lambda definition. @@ -15621,10 +15621,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15700,8 +15700,8 @@ module Prism # : () -> Prism::node def value: () -> Prism::node - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an optional parameter to a method, block, or lambda definition. @@ -15735,10 +15735,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15838,8 +15838,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `||` operator or the `or` keyword. @@ -15870,10 +15870,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -15966,8 +15966,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the list of parameters on a method, block, or lambda definition. @@ -16007,10 +16007,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -16104,8 +16104,8 @@ module Prism # : () -> (BlockParameterNode | NoBlockParameterNode)? def block: () -> (BlockParameterNode | NoBlockParameterNode)? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a parenthesized expression @@ -16136,10 +16136,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -16239,8 +16239,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `^` operator for pinning an expression in a pattern matching expression. @@ -16273,10 +16273,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -16406,8 +16406,8 @@ module Prism # : () -> String def rparen: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `^` operator for pinning a variable in a pattern matching expression. @@ -16436,10 +16436,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -16515,8 +16515,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `END` keyword. @@ -16549,10 +16549,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -16670,8 +16670,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `BEGIN` keyword. @@ -16704,10 +16704,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -16825,8 +16825,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # The top level node of any parse tree. @@ -16852,10 +16852,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -16909,8 +16909,8 @@ module Prism # : () -> StatementsNode def statements: () -> StatementsNode - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `..` or `...` operators. @@ -16944,10 +16944,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17044,8 +17044,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a rational number literal. @@ -17074,10 +17074,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17159,8 +17159,8 @@ module Prism # : () -> Integer def denominator: () -> Integer - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `redo` keyword. @@ -17185,10 +17185,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17226,8 +17226,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a regular expression literal with no interpolation. @@ -17260,10 +17260,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17447,8 +17447,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a required keyword parameter to a method, block, or lambda definition. @@ -17478,10 +17478,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17549,8 +17549,8 @@ module Prism # : (_Repository repository) -> Relocation::Entry def save_name_loc: (_Repository repository) -> Relocation::Entry - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a required parameter to a method, block, or lambda definition. @@ -17578,10 +17578,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17633,8 +17633,8 @@ module Prism # : () -> Symbol def name: () -> Symbol - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an expression modified with a rescue. @@ -17665,10 +17665,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17746,8 +17746,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a rescue statement. @@ -17791,10 +17791,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -17936,8 +17936,8 @@ module Prism # : () -> String? def then_keyword: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a rest parameter to a method, block, or lambda definition. @@ -17969,10 +17969,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18064,8 +18064,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `retry` keyword. @@ -18090,10 +18090,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18131,8 +18131,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `return` keyword. @@ -18161,10 +18161,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18234,8 +18234,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the `self` keyword. @@ -18260,10 +18260,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18301,8 +18301,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # This node wraps a constant write to indicate that when the value is written, it should have its shareability state modified. @@ -18330,10 +18330,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18397,8 +18397,8 @@ module Prism # : () -> (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) def write: () -> (ConstantWriteNode | ConstantAndWriteNode | ConstantOrWriteNode | ConstantOperatorWriteNode | ConstantPathWriteNode | ConstantPathAndWriteNode | ConstantPathOrWriteNode | ConstantPathOperatorWriteNode) - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a singleton class declaration involving the `class` keyword. @@ -18435,10 +18435,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18572,8 +18572,8 @@ module Prism # : () -> String def end_keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `__ENCODING__` keyword. @@ -18598,10 +18598,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18639,8 +18639,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `__FILE__` keyword. @@ -18667,10 +18667,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18740,8 +18740,8 @@ module Prism # : () -> String def filepath: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `__LINE__` keyword. @@ -18766,10 +18766,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18807,8 +18807,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the splat operator. @@ -18837,10 +18837,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18910,8 +18910,8 @@ module Prism # : () -> String def operator: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a set of statements contained within some scope. @@ -18938,10 +18938,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -18987,8 +18987,8 @@ module Prism # : () -> Array[Prism::node] def body: () -> Array[Prism::node] - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string. @@ -19027,10 +19027,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -19172,8 +19172,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `super` keyword with parentheses or arguments. @@ -19213,10 +19213,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -19342,8 +19342,8 @@ module Prism # : () -> String? def rparen: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents a symbol literal or a symbol contained within a `%i` list. @@ -19379,10 +19379,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -19518,8 +19518,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the literal `true` keyword. @@ -19544,10 +19544,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -19585,8 +19585,8 @@ module Prism # : () -> String def inspect: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `undef` keyword. @@ -19615,10 +19615,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -19688,8 +19688,8 @@ module Prism # : () -> String def keyword: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `unless` keyword, either in the block form or the modifier form. @@ -19729,10 +19729,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -19891,8 +19891,8 @@ module Prism # : () -> String? def end_keyword: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `until` keyword, either in the block form or the modifier form. @@ -19930,10 +19930,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -20065,8 +20065,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `when` keyword within a case statement. @@ -20101,10 +20101,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -20206,8 +20206,8 @@ module Prism # : () -> String? def then_keyword: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `while` keyword, either in the block form or the modifier form. @@ -20245,10 +20245,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -20380,8 +20380,8 @@ module Prism # : () -> String? def closing: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents an xstring literal with no interpolation. @@ -20414,10 +20414,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -20547,8 +20547,8 @@ module Prism # : () -> String def closing: () -> String - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Represents the use of the `yield` keyword. @@ -20581,10 +20581,10 @@ module Prism # See Node.each_child_node. # -- - # : () { (node) -> void } -> void # : () -> Enumerator[node, void] - def each_child_node: () { (node) -> void } -> void - | () -> Enumerator[node, void] + # : () { (node) -> void } -> void + def each_child_node: () -> Enumerator[node, void] + | () { (node) -> void } -> void # See Node.compact_child_nodes. # -- @@ -20702,8 +20702,8 @@ module Prism # : () -> String? def rparen: () -> String? - # : (untyped other) -> bool - def ===: (untyped other) -> bool + # : (untyped other) -> boolish + def ===: (untyped other) -> boolish end # Flags for arguments nodes. diff --git a/sig/generated/prism/parse_result/newlines.rbs b/sig/generated/prism/parse_result/newlines.rbs index 7037631712..45c04783d0 100644 --- a/sig/generated/prism/parse_result/newlines.rbs +++ b/sig/generated/prism/parse_result/newlines.rbs @@ -68,62 +68,62 @@ module Prism end class BeginNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class ParenthesesNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class IfNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class UnlessNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class UntilNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class WhileNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class RescueModifierNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class InterpolatedMatchLastLineNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class InterpolatedRegularExpressionNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class InterpolatedStringNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class InterpolatedSymbolNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end class InterpolatedXStringNode < Node - # @rbs override - def newline_flag!: ... + # : (Array[bool] lines) -> void + def newline_flag!: (Array[bool] lines) -> void end end diff --git a/sig/generated/prism/pattern.rbs b/sig/generated/prism/pattern.rbs index d427b0098b..7ea2808da4 100644 --- a/sig/generated/prism/pattern.rbs +++ b/sig/generated/prism/pattern.rbs @@ -67,10 +67,10 @@ module Prism # matches the pattern. If no block is given, an enumerator will be returned # that will yield each node that matches the pattern. # -- - # : (node root) { (node) -> void } -> void # : (node root) -> Enumerator[node, void] - def scan: (node root) { (node) -> void } -> void - | (node root) -> Enumerator[node, void] + # : (node root) { (node) -> void } -> void + def scan: (node root) -> Enumerator[node, void] + | (node root) { (node) -> void } -> void private diff --git a/templates/lib/prism/dot_visitor.rb.erb b/templates/lib/prism/dot_visitor.rb.erb index bdac9cfd3c..88ef1e1f36 100644 --- a/templates/lib/prism/dot_visitor.rb.erb +++ b/templates/lib/prism/dot_visitor.rb.erb @@ -126,7 +126,7 @@ module Prism end <%- nodes.each do |node| -%> - # (<%= node.name %>) -> void + #: (<%= node.name %>) -> void def visit_<%= node.human %>(node) # :nodoc: table = Table.new("<%= node.name %>") id = node_id(node) diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index 2e42eeea13..817b59b477 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -294,7 +294,7 @@ module Prism # node.breadth_first_search { |node| node.node_id == node_id } #-- #: () { (node) -> bool } -> node? - def breadth_first_search(&block) + def breadth_first_search(&blk) queue = [self] #: Array[node] while (node = queue.shift) @@ -313,7 +313,7 @@ module Prism # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } #-- #: () { (node) -> bool } -> Array[node] - def breadth_first_search_all(&block) + def breadth_first_search_all(&blk) queue = [self] #: Array[Prism::node] results = [] #: Array[Prism::node] @@ -366,9 +366,9 @@ module Prism # an enumerator that contains each child node. Excludes any `nil`s in # the place of optional nodes that were not present. #-- - #: () { (node) -> void } -> void #: () -> Enumerator[node, void] - def each_child_node + #: () { (node) -> void } -> void + def each_child_node(&blk) raise NoMethodError, "undefined method `each_child_node' for #{inspect}" end @@ -481,9 +481,9 @@ module Prism # See Node.each_child_node. #-- - #: () { (node) -> void } -> void #: () -> Enumerator[node, void] - def each_child_node + #: () { (node) -> void } -> void + def each_child_node(&blk) return to_enum(:each_child_node) unless block_given? <%- node.fields.each do |field| -%> @@ -705,7 +705,7 @@ module Prism <%- end -%> # :section: - #: (untyped other) -> bool + #: (untyped other) -> boolish def ===(other) # :nodoc: other.is_a?(<%= node.name %>)<%= " &&" if (fields = [*node.flags, *node.fields]).any? %> <%- fields.each_with_index do |field, index| -%> diff --git a/templates/rbi/prism/dsl.rbi.erb b/templates/rbi/prism/dsl.rbi.erb deleted file mode 100644 index 76a39c5051..0000000000 --- a/templates/rbi/prism/dsl.rbi.erb +++ /dev/null @@ -1,68 +0,0 @@ -module Prism::DSL - sig { params(string: String).returns(Prism::Source) } - def source(string); end - - sig { params(source: Prism::Source, start_offset: Integer, length: Integer).returns(Prism::Location) } - def location(source: default_source, start_offset: 0, length: 0); end - <%- nodes.each do |node| -%> - <%- - params = [ - ["source", "default_source", "Prism::Source"], - ["node_id", "0", "Integer"], - ["location", "default_location", "Prism::Location"], - ["flags", "0", "Integer"] - ].concat(node.fields.map { |field| - case field - when Prism::Template::NodeField - kind = field.specific_kind || field.union_kind&.first - if kind.nil? - [field.name, "default_node(source, location)", field.rbi_class] - else - [field.name, %Q{#{kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}(source: source)}, field.rbi_class] - end - when Prism::Template::OptionalNodeField - [field.name, "nil", field.rbi_class] - when Prism::Template::NodeListField - [field.name, "[]", field.rbi_class] - when Prism::Template::ConstantField - [field.name, ":\"\"", field.rbi_class] - when Prism::Template::OptionalConstantField - [field.name, "nil", field.rbi_class] - when Prism::Template::ConstantListField - [field.name, "[]", field.rbi_class] - when Prism::Template::StringField - [field.name, "\"\"", field.rbi_class] - when Prism::Template::LocationField - [field.name, "location", field.rbi_class] - when Prism::Template::OptionalLocationField - [field.name, "nil", field.rbi_class] - when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField - [field.name, "0", field.rbi_class] - when Prism::Template::DoubleField - [field.name, "0.0", field.rbi_class] - else - raise - end - }) - -%> - - sig { params(<%= params.map { |(name, _, type)| "#{name}: #{type}" }.join(", ") %>).returns(Prism::<%= node.name %>) } - def <%= node.human %>(<%= params.map { |(name, default, _)| "#{name}: #{default}" }.join(", ") %>); end - <%- end -%> - <%- flags.each do |flag| -%> - - sig { params(name: Symbol).returns(Integer) } - def <%= flag.human.chomp("s") %>(name); end - <%- end -%> - - private - - sig { returns(Prism::Source) } - def default_source; end - - sig { returns(Prism::Location) } - def default_location; end - - sig { params(source: Prism::Source, location: Prism::Location).returns(Prism::Node) } - def default_node(source, location); end -end diff --git a/templates/rbi/prism/node.rbi.erb b/templates/rbi/prism/node.rbi.erb deleted file mode 100644 index 0c89b4524c..0000000000 --- a/templates/rbi/prism/node.rbi.erb +++ /dev/null @@ -1,167 +0,0 @@ -class Prism::Node - abstract! - - sig { returns(Prism::Source) } - def source; end - - sig { returns(Integer) } - def node_id; end - - sig { returns(Prism::Location) } - def location; end - - sig{ returns(Integer) } - def flags; end - - sig { returns(T::Boolean) } - def newline?; end - - sig { returns(T::Boolean) } - def static_literal?; end - - sig { returns(Integer) } - def start_offset; end - - sig { returns(Integer) } - def end_offset; end - - sig { returns(T::Array[String]) } - def source_lines; end - - sig { returns(T::Array[String]) } - def script_lines; end - - sig { returns(String) } - def slice; end - - sig { returns(String) } - def slice_lines; end - - sig { params(q: T.untyped).void } - def pretty_print(q); end - - sig { returns(String) } - def to_dot; end - - sig { params(line: Integer, column: Integer).returns(T::Array[Prism::Node]) } - def tunnel(line, column); end - - sig { params(block: T.proc.params(node: Prism::Node).returns(T::Boolean)).returns(T.nilable(Prism::Node)) } - def breadth_first_search(&block); end - - sig { params(block: T.proc.params(node: Prism::Node).returns(T::Boolean)).returns(T::Array[Prism::Node]) } - def breadth_first_search_all(&block); end - - sig { abstract.params(visitor: Prism::Visitor).returns(T.untyped) } - def accept(visitor); end - - sig { abstract.returns(T::Array[T.nilable(Prism::Node)]) } - def child_nodes; end - - sig { abstract.returns(T::Array[T.nilable(Prism::Node)]) } - def deconstruct; end - - sig { abstract.returns(T::Array[Prism::Node]) } - def compact_child_nodes; end - - sig { abstract.returns(T::Array[T.any(Prism::Node, Prism::Location)]) } - def comment_targets; end - - sig { abstract.returns(T::Array[Prism::Reflection::Field]) } - def fields; end - - sig { abstract.returns(Symbol) } - def type; end - - sig { abstract.returns(String) } - def inspect; end -end -<%- nodes.each do |node| -%> - -<%- node.each_comment_line do |line| -%> -#<%= line %> -<%- end -%> -class Prism::<%= node.name -%> < Prism::Node - <%- if (node_flags = node.flags) -%> - <%- node_flags.values.each do |value| -%> - sig { returns(T::Boolean) } - def <%= value.name.downcase %>?; end - - <%- end -%> - <%- end -%> - <%- node.fields.each do |field| -%> - sig { returns(<%= field.rbi_class %>) } - def <%= field.name %>; end - - <%- end -%> - sig { params(<%= ["source: Prism::Source", "node_id: Integer", "location: Prism::Location", "flags: Integer", *node.fields.map { |field| "#{field.name}: #{field.rbi_class}" }].join(", ") %>).void } - def initialize(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>); end - - sig { override.params(visitor: Prism::Visitor).returns(T.untyped) } - def accept(visitor); end - - sig { override.returns(T::Array[T.nilable(Prism::Node)]) } - def child_nodes; end - - sig { override.returns(T::Array[T.nilable(Prism::Node)]) } - def deconstruct; end - - sig { override.returns(T::Array[Prism::Node]) } - def compact_child_nodes; end - - sig { override.returns(T::Array[T.any(Prism::Node, Prism::Location)]) } - def comment_targets; end - - sig { params(<%= (["node_id: Integer", "location: Prism::Location", "flags: Integer"] + node.fields.map { |field| "#{field.name}: #{field.rbi_class}" }).join(", ") %>).returns(Prism::<%= node.name %>) } - def copy(<%= (["node_id", "location", "flags"] + node.fields.map(&:name)).map { |field| "#{field}: self.#{field}" }.join(", ") %>); end - - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } - def deconstruct_keys(keys); end - <%- node.fields.each do |field| -%> - <%- case field -%> - <%- when Prism::Template::LocationField -%> - <%- raise unless field.name.end_with?("_loc") -%> - <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - - sig { returns(String) } - def <%= field.name.delete_suffix("_loc") %>; end - <%- when Prism::Template::OptionalLocationField -%> - <%- raise unless field.name.end_with?("_loc") -%> - <%- next if node.fields.any? { |other| other.name == field.name.delete_suffix("_loc") } -%> - - sig { returns(T.nilable(String)) } - def <%= field.name.delete_suffix("_loc") %>; end - <%- end -%> - <%- end -%> - - sig { override.returns(T::Array[Prism::Reflection::Field]) } - def fields; end - - sig { override.returns(String) } - def inspect; end - - sig { override.returns(Symbol) } - def type; end -end -<%- end -%> -<%- flags.each do |flag| -%> - -# <%= flag.comment %> -module Prism::<%= flag.name %> - <%- flag.values.each_with_index do |value, index| -%> - # <%= value.comment %> - <%= value.name %> = T.let(1 << <%= index + Prism::Template::COMMON_FLAGS_COUNT %>, Integer) - <%- end -%> -end -<%- end -%> - -# The flags that are common to all nodes. -module Prism::NodeFlags - # A flag to indicate that the node is a candidate to emit a :line event - # through tracepoint when compiled. - NEWLINE = T.let(1, Integer) - - # A flag to indicate that the value that the node represents is a value that - # can be determined at parse-time. - STATIC_LITERAL = T.let(2, Integer) -end diff --git a/templates/rbi/prism/visitor.rbi.erb b/templates/rbi/prism/visitor.rbi.erb deleted file mode 100644 index dd42432186..0000000000 --- a/templates/rbi/prism/visitor.rbi.erb +++ /dev/null @@ -1,18 +0,0 @@ -class Prism::BasicVisitor - sig { params(node: T.nilable(Prism::Node)).void } - def visit(node); end - - sig { params(nodes: T::Array[T.nilable(Prism::Node)]).void } - def visit_all(nodes); end - - sig { params(node: Prism::Node).void } - def visit_child_nodes(node); end -end - -class Prism::Visitor < Prism::BasicVisitor - <%- nodes.each_with_index do |node, index| -%> -<%= "\n" if index != 0 -%> - sig { params(node: Prism::<%= node.name %>).void } - def visit_<%= node.human %>(node); end - <%- end -%> -end diff --git a/templates/template.rb b/templates/template.rb index a39f8bbb78..e571c58bf2 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -166,16 +166,6 @@ def call_seq_type end end - def rbi_class - if specific_kind - "Prism::#{specific_kind}" - elsif union_kind - "T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")})" - else - "Prism::Node" - end - end - def check_field_kind if union_kind "[#{union_kind.join(', ')}].include?(#{name}.class)" @@ -208,16 +198,6 @@ def call_seq_type end end - def rbi_class - if specific_kind - "T.nilable(Prism::#{specific_kind})" - elsif union_kind - "T.nilable(T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")}))" - else - "T.nilable(Prism::Node)" - end - end - def check_field_kind if union_kind "[#{union_kind.join(', ')}, NilClass].include?(#{name}.class)" @@ -254,16 +234,6 @@ def call_seq_type end end - def rbi_class - if specific_kind - "T::Array[Prism::#{specific_kind}]" - elsif union_kind - "T::Array[T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")})]" - else - "T::Array[Prism::Node]" - end - end - def java_type "#{super}[]" end @@ -288,10 +258,6 @@ def call_seq_type "Symbol" end - def rbi_class - "Symbol" - end - def java_type JAVA_STRING_TYPE end @@ -308,10 +274,6 @@ def call_seq_type "Symbol | nil" end - def rbi_class - "T.nilable(Symbol)" - end - def java_type JAVA_STRING_TYPE end @@ -328,10 +290,6 @@ def call_seq_type "Array[Symbol]" end - def rbi_class - "T::Array[Symbol]" - end - def java_type "#{JAVA_STRING_TYPE}[]" end @@ -347,10 +305,6 @@ def call_seq_type "String" end - def rbi_class - "String" - end - def java_type "byte[]" end @@ -370,10 +324,6 @@ def call_seq_type "Location" end - def rbi_class - "Prism::Location" - end - def java_type "Location" end @@ -393,10 +343,6 @@ def call_seq_type "Location | nil" end - def rbi_class - "T.nilable(Prism::Location)" - end - def java_type "Location" end @@ -412,10 +358,6 @@ def call_seq_type "Integer" end - def rbi_class - "Integer" - end - def java_type "int" end @@ -431,10 +373,6 @@ def call_seq_type "Integer" end - def rbi_class - "Integer" - end - def java_type "int" end @@ -451,10 +389,6 @@ def call_seq_type "Integer" end - def rbi_class - "Integer" - end - def java_type "Object" end @@ -471,10 +405,6 @@ def call_seq_type "Float" end - def rbi_class - "Float" - end - def java_type "double" end @@ -629,8 +559,7 @@ def render(name, write_to: nil) extension = File.extname(filepath.gsub(".erb", "")) heading = - case extension - when ".rb" + if extension == ".rb" <<~HEADING # frozen_string_literal: true # :markup: markdown @@ -643,17 +572,6 @@ def render(name, write_to: nil) ++ =end - HEADING - when ".rbi" - <<~HEADING - # typed: strict - - =begin - This file is generated by the templates/template.rb script and should not be - modified manually. See #{filepath} - if you are looking to modify the template - =end - HEADING else <<~HEADING @@ -738,10 +656,7 @@ def locals "src/node.c", "src/prettyprint.c", "src/serialize.c", - "src/token_type.c", - "rbi/prism/dsl.rbi", - "rbi/prism/node.rbi", - "rbi/prism/visitor.rbi" + "src/token_type.c" ] end end From 329e187e8aef18e087429e06edf415ed70adf1ef Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 22 Feb 2026 16:55:37 -0500 Subject: [PATCH 068/289] Typecheck _Visitor as Visitor --- .gitattributes | 2 + rakelib/typecheck.rake | 5 +- rbi/generated/prism/node.rbi | 306 +++++++++++++++++------------------ 3 files changed, 159 insertions(+), 154 deletions(-) diff --git a/.gitattributes b/.gitattributes index 6b1cb4d76a..fee51d19c2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,8 @@ test/prism/fixtures/seattlerb/**/*.txt linguist-vendored test/prism/fixtures/unparser/**/*.txt linguist-vendored test/prism/fixtures/whitequark/**/*.txt linguist-vendored test/prism/snapshots/**/*.txt linguist-generated + +rbi/generated/**/*.rbi linguist-generated sig/generated/**/*.rbs linguist-generated # All .rb files should have LF line ending, even on Windows, regardless of the git config core.autocrlf value. diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index 8fd2b09f25..7ba7a256ab 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -249,8 +249,10 @@ namespace :typecheck do end when RBS::Types::Interface case type.name.name - when :_CodeUnitsCache, :_CommentTarget, :_Field, :_Repository, :_Stream, :_Value, :_Visitor + when :_CodeUnitsCache, :_CommentTarget, :_Field, :_Repository, :_Stream, :_Value RBI::Type.untyped + when :_Visitor + RBI::Type.simple("Visitor") else raise end @@ -331,6 +333,7 @@ namespace :typecheck do - ./lib/prism/node_ext.rb - ./lib/prism/parse_result.rb - ./lib/prism/pattern.rb + - ./lib/prism/visitor.rb - ./lib/prism/translation/parser/lexer.rb - ./lib/prism/translation/ripper.rb - ./lib/prism/translation/ripper/sexp.rb diff --git a/rbi/generated/prism/node.rbi b/rbi/generated/prism/node.rbi index f7486e9f66..af23b6b42c 100644 --- a/rbi/generated/prism/node.rbi +++ b/rbi/generated/prism/node.rbi @@ -174,7 +174,7 @@ module Prism def self.fields; end # Accepts a visitor and calls back into the specialized visit function. - sig { abstract.params(visitor: T.untyped).returns(T.untyped) } + sig { abstract.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # Returns an array of child nodes, including `nil`s in the place of optional @@ -236,7 +236,7 @@ module Prism def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -318,7 +318,7 @@ module Prism def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -412,7 +412,7 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -494,7 +494,7 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -582,7 +582,7 @@ module Prism def initialize(source, node_id, location, flags, arguments); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -661,7 +661,7 @@ module Prism def initialize(source, node_id, location, flags, elements, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -769,7 +769,7 @@ module Prism def initialize(source, node_id, location, flags, constant, requireds, rest, posts, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -887,7 +887,7 @@ module Prism def initialize(source, node_id, location, flags, key, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -978,7 +978,7 @@ module Prism def initialize(source, node_id, location, flags, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1053,7 +1053,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1115,7 +1115,7 @@ module Prism def initialize(source, node_id, location, flags, begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1227,7 +1227,7 @@ module Prism def initialize(source, node_id, location, flags, expression, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1302,7 +1302,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1365,7 +1365,7 @@ module Prism def initialize(source, node_id, location, flags, locals, parameters, body, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1475,7 +1475,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1572,7 +1572,7 @@ module Prism def initialize(source, node_id, location, flags, parameters, locals, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1686,7 +1686,7 @@ module Prism def initialize(source, node_id, location, flags, arguments, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1761,7 +1761,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -1920,7 +1920,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc, opening_loc, arguments, closing_loc, equal_loc, block); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2108,7 +2108,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, binary_operator, binary_operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2255,7 +2255,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2407,7 +2407,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2521,7 +2521,7 @@ module Prism def initialize(source, node_id, location, flags, value, target, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2605,7 +2605,7 @@ module Prism def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2712,7 +2712,7 @@ module Prism def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2817,7 +2817,7 @@ module Prism def initialize(source, node_id, location, flags, locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, body, end_keyword_loc, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -2946,7 +2946,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3040,7 +3040,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3122,7 +3122,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3204,7 +3204,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3264,7 +3264,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3320,7 +3320,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3418,7 +3418,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3500,7 +3500,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3582,7 +3582,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3664,7 +3664,7 @@ module Prism def initialize(source, node_id, location, flags, target, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3737,7 +3737,7 @@ module Prism def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3840,7 +3840,7 @@ module Prism def initialize(source, node_id, location, flags, target, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3913,7 +3913,7 @@ module Prism def initialize(source, node_id, location, flags, target, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -3986,7 +3986,7 @@ module Prism def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4074,7 +4074,7 @@ module Prism def initialize(source, node_id, location, flags, target, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4159,7 +4159,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4219,7 +4219,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4275,7 +4275,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4374,7 +4374,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, receiver, parameters, body, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4533,7 +4533,7 @@ module Prism def initialize(source, node_id, location, flags, lparen_loc, value, rparen_loc, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4628,7 +4628,7 @@ module Prism def initialize(source, node_id, location, flags, else_keyword_loc, statements, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4710,7 +4710,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, statements, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4792,7 +4792,7 @@ module Prism def initialize(source, node_id, location, flags, operator_loc, variable); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4865,7 +4865,7 @@ module Prism def initialize(source, node_id, location, flags, ensure_keyword_loc, statements, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -4947,7 +4947,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5008,7 +5008,7 @@ module Prism def initialize(source, node_id, location, flags, constant, left, requireds, right, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5135,7 +5135,7 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5212,7 +5212,7 @@ module Prism def initialize(source, node_id, location, flags, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5268,7 +5268,7 @@ module Prism def initialize(source, node_id, location, flags, index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5409,7 +5409,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5462,7 +5462,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5519,7 +5519,7 @@ module Prism def initialize(source, node_id, location, flags, block); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5575,7 +5575,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5657,7 +5657,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5739,7 +5739,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5821,7 +5821,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5881,7 +5881,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -5937,7 +5937,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6035,7 +6035,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, elements, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6138,7 +6138,7 @@ module Prism def initialize(source, node_id, location, flags, constant, elements, rest, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6264,7 +6264,7 @@ module Prism def initialize(source, node_id, location, flags, if_keyword_loc, predicate, then_keyword_loc, statements, subsequent, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6413,7 +6413,7 @@ module Prism def initialize(source, node_id, location, flags, numeric); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6475,7 +6475,7 @@ module Prism def initialize(source, node_id, location, flags, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6540,7 +6540,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6592,7 +6592,7 @@ module Prism def initialize(source, node_id, location, flags, pattern, statements, in_loc, then_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6678,7 +6678,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6814,7 +6814,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, binary_operator, binary_operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -6950,7 +6950,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7094,7 +7094,7 @@ module Prism def initialize(source, node_id, location, flags, receiver, opening_loc, arguments, closing_loc, block); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7200,7 +7200,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7282,7 +7282,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7364,7 +7364,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7446,7 +7446,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7506,7 +7506,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7562,7 +7562,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7660,7 +7660,7 @@ module Prism def initialize(source, node_id, location, flags, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7732,7 +7732,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7858,7 +7858,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -7984,7 +7984,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8074,7 +8074,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8156,7 +8156,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8238,7 +8238,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8290,7 +8290,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8342,7 +8342,7 @@ module Prism def initialize(source, node_id, location, flags, elements); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8403,7 +8403,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8485,7 +8485,7 @@ module Prism def initialize(source, node_id, location, flags, locals, operator_loc, opening_loc, closing_loc, parameters, body); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8588,7 +8588,7 @@ module Prism def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8674,7 +8674,7 @@ module Prism def initialize(source, node_id, location, flags, name_loc, binary_operator_loc, value, name, binary_operator, depth); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8760,7 +8760,7 @@ module Prism def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8846,7 +8846,7 @@ module Prism def initialize(source, node_id, location, flags, name, depth); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8923,7 +8923,7 @@ module Prism def initialize(source, node_id, location, flags, name, depth); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -8983,7 +8983,7 @@ module Prism def initialize(source, node_id, location, flags, name, depth, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9095,7 +9095,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9234,7 +9234,7 @@ module Prism def initialize(source, node_id, location, flags, value, pattern, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9307,7 +9307,7 @@ module Prism def initialize(source, node_id, location, flags, value, pattern, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9428,7 +9428,7 @@ module Prism def initialize(source, node_id, location, flags, call, targets); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9485,7 +9485,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9537,7 +9537,7 @@ module Prism def initialize(source, node_id, location, flags, locals, module_keyword_loc, constant_path, body, end_keyword_loc, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9636,7 +9636,7 @@ module Prism def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9756,7 +9756,7 @@ module Prism def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9899,7 +9899,7 @@ module Prism def initialize(source, node_id, location, flags, arguments, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -9968,7 +9968,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10021,7 +10021,7 @@ module Prism def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10100,7 +10100,7 @@ module Prism def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10178,7 +10178,7 @@ module Prism def initialize(source, node_id, location, flags, maximum); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10234,7 +10234,7 @@ module Prism def initialize(source, node_id, location, flags, number); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10297,7 +10297,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10371,7 +10371,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10457,7 +10457,7 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10546,7 +10546,7 @@ module Prism def initialize(source, node_id, location, flags, requireds, optionals, rest, posts, keywords, keyword_rest, block); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10626,7 +10626,7 @@ module Prism def initialize(source, node_id, location, flags, body, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10712,7 +10712,7 @@ module Prism def initialize(source, node_id, location, flags, expression, operator_loc, lparen_loc, rparen_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10819,7 +10819,7 @@ module Prism def initialize(source, node_id, location, flags, variable, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10894,7 +10894,7 @@ module Prism def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -10989,7 +10989,7 @@ module Prism def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11081,7 +11081,7 @@ module Prism def initialize(source, node_id, location, flags, locals, statements); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11144,7 +11144,7 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11234,7 +11234,7 @@ module Prism def initialize(source, node_id, location, flags, numerator, denominator); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11314,7 +11314,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11366,7 +11366,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11506,7 +11506,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11576,7 +11576,7 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11636,7 +11636,7 @@ module Prism def initialize(source, node_id, location, flags, expression, keyword_loc, rescue_expression); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11714,7 +11714,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, then_keyword_loc, statements, subsequent); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11822,7 +11822,7 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11904,7 +11904,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -11956,7 +11956,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, arguments); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12025,7 +12025,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12078,7 +12078,7 @@ module Prism def initialize(source, node_id, location, flags, write); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12146,7 +12146,7 @@ module Prism def initialize(source, node_id, location, flags, locals, class_keyword_loc, operator_loc, expression, body, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12249,7 +12249,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12301,7 +12301,7 @@ module Prism def initialize(source, node_id, location, flags, filepath); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12373,7 +12373,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12425,7 +12425,7 @@ module Prism def initialize(source, node_id, location, flags, operator_loc, expression); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12494,7 +12494,7 @@ module Prism def initialize(source, node_id, location, flags, body); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12556,7 +12556,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12672,7 +12672,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc, block); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12774,7 +12774,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, value_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12881,7 +12881,7 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -12933,7 +12933,7 @@ module Prism def initialize(source, node_id, location, flags, names, keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -13005,7 +13005,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, predicate, then_keyword_loc, statements, else_clause, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -13136,7 +13136,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -13241,7 +13241,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, conditions, then_keyword_loc, statements); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -13330,7 +13330,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -13433,7 +13433,7 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. @@ -13536,7 +13536,7 @@ module Prism def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc); end # See Node.accept. - sig { override.params(visitor: T.untyped).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(T.untyped) } def accept(visitor); end # See Node.child_nodes. From f741032474cf7f3c9ce7076da7aa656453eba3de Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 22 Feb 2026 17:09:21 -0500 Subject: [PATCH 069/289] Handle aliases in RBI generation --- rakelib/typecheck.rake | 30 +- rbi/generated/prism/dispatcher.rbi | 4 + rbi/generated/prism/node.rbi | 470 +++++++++++++++++++++++++++++ 3 files changed, 501 insertions(+), 3 deletions(-) diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index 7ba7a256ab..be18cc3b25 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -138,8 +138,32 @@ namespace :typecheck do method.sigs << sig end end - when RBS::AST::Members::Alias, RBS::AST::Members::InstanceVariable, - RBS::AST::Declarations::Interface, RBS::AST::Declarations::TypeAlias + when RBS::AST::Members::Alias + case [node.new_name, node.old_name] + when [:dispatch, :visit] + parent << + RBI::Method.new("dispatch", visibility: @visibility, comments: compile_comments(node)) do |method| + method.add_param("node") + method.sigs << + RBI::Sig.new( + params: [RBI::SigParam.new("node", RBI::Type.nilable(RBI::Type.simple("Node")))], + return_type: RBI::Type.untyped + ) + end + when [:script_lines, :source_lines], + [:find, :breadth_first_search], + [:find_all, :breadth_first_search_all], + [:deconstruct, :child_nodes] + found = parent.nodes.find { |child| child.is_a?(RBI::Method) && child.name == node.old_name.name } + parent << + found.dup.tap do |method| + method.name = node.new_name.name + method.comments = compile_comments(node) + end + else + raise + end + when RBS::AST::Members::InstanceVariable, RBS::AST::Declarations::Interface, RBS::AST::Declarations::TypeAlias # skip else raise @@ -277,7 +301,7 @@ namespace :typecheck do end desc "Generate RBIs from RBSs" - task rbi: :rbs_inline do + task rbi: :templates do with_gemfile do require "fileutils" require "rbs" diff --git a/rbi/generated/prism/dispatcher.rbi b/rbi/generated/prism/dispatcher.rbi index 728ab5942e..14ef40c9c1 100644 --- a/rbi/generated/prism/dispatcher.rbi +++ b/rbi/generated/prism/dispatcher.rbi @@ -55,6 +55,10 @@ module Prism sig { params(arg0: T.untyped, arg1: T::Array[Symbol]).void } def register_events(arg0, arg1); end + # Walks `root` dispatching events to all registered listeners. + sig { params(node: T.nilable(Node)).returns(T.untyped) } + def dispatch(node); end + # Dispatches a single event for `node` to all registered listeners. sig { params(node: Node).void } def dispatch_once(node); end diff --git a/rbi/generated/prism/node.rbi b/rbi/generated/prism/node.rbi index af23b6b42c..1664fd88b7 100644 --- a/rbi/generated/prism/node.rbi +++ b/rbi/generated/prism/node.rbi @@ -110,6 +110,11 @@ module Prism sig { returns(T::Array[String]) } def source_lines; end + # An alias for source_lines, used to mimic the API from + # RubyVM::AbstractSyntaxTree to make it easier to migrate. + sig { returns(T::Array[String]) } + def script_lines; end + # Slice the location of the node from the source. sig { returns(String) } def slice; end @@ -159,6 +164,9 @@ module Prism sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T.nilable(Node)) } def breadth_first_search(&blk); end + sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T.nilable(Node)) } + def find(&blk); end + # Returns all of the nodes that match the given block when visited in a # breadth-first search. This is useful for finding all nodes that match a # particular condition. @@ -167,6 +175,9 @@ module Prism sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } def breadth_first_search_all(&blk); end + sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } + def find_all(&blk); end + # Returns a list of the fields that exist for this node class. Fields # describe the structure of the node. This kind of reflection is useful for # things like recursively visiting each node _and_ field in the tree. @@ -182,6 +193,9 @@ module Prism sig { abstract.returns(T::Array[T.nilable(Node)]) } def child_nodes; end + sig { abstract.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + # With a block given, yields each child node. Without a block, returns # an enumerator that contains each child node. Excludes any `nil`s in # the place of optional nodes that were not present. @@ -260,6 +274,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, new_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -342,6 +359,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, new_name: T.any(SymbolNode, InterpolatedSymbolNode), old_name: T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -436,6 +456,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AlternationPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -518,6 +541,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AndNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -606,6 +632,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).returns(ArgumentsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -685,6 +714,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -793,6 +825,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), requireds: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -911,6 +946,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: T.nilable(Location)).returns(AssocNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), key: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1002,6 +1040,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, value: T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1077,6 +1118,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BackReferenceReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1139,6 +1183,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), rescue_clause: T.nilable(RescueNode), else_clause: T.nilable(ElseNode), ensure_clause: T.nilable(EnsureNode), end_keyword_loc: T.nilable(Location)).returns(BeginNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), begin_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), rescue_clause: T.unsafe(nil), else_clause: T.unsafe(nil), ensure_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1251,6 +1298,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1326,6 +1376,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BlockLocalVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1389,6 +1442,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1499,6 +1555,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1596,6 +1655,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, parameters: T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(BlockParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parameters: T.unsafe(nil), locals: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1710,6 +1772,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1785,6 +1850,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -1944,6 +2012,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), name: Symbol, message_loc: T.nilable(Location), opening_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), closing_loc: T.nilable(Location), equal_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), block: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2132,6 +2203,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2279,6 +2353,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2431,6 +2508,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).returns(CallTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2545,6 +2625,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).returns(CapturePatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2629,6 +2712,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[InNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2736,6 +2822,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[WhenNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2841,6 +2930,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: T.nilable(Location), superclass: T.nilable(Node), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), inheritance_operator_loc: T.unsafe(nil), superclass: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -2970,6 +3062,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3064,6 +3159,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ClassVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3146,6 +3244,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3228,6 +3329,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3288,6 +3392,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3344,6 +3451,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ClassVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3442,6 +3552,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3524,6 +3637,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3606,6 +3722,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3688,6 +3807,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3761,6 +3883,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3864,6 +3989,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantPathOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -3937,6 +4065,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4010,6 +4141,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4098,6 +4232,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4183,6 +4320,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4243,6 +4383,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4299,6 +4442,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ConstantWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4398,6 +4544,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: T.nilable(Node), parameters: T.nilable(ParametersNode), body: T.nilable(T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: T.nilable(Location), lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), equal_loc: T.nilable(Location), end_keyword_loc: T.nilable(Location)).returns(DefNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), receiver: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), locals: T.unsafe(nil), def_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4557,6 +4706,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, lparen_loc: T.nilable(Location), value: Node, rparen_loc: T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lparen_loc: T.unsafe(nil), value: T.unsafe(nil), rparen_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4652,6 +4804,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: T.nilable(Location)).returns(ElseNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), else_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4734,6 +4889,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), statements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4816,6 +4974,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), variable: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4889,6 +5050,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), ensure_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -4971,6 +5135,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(FalseNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5032,6 +5199,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: T.any(SplatNode, MissingNode), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(FindPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), left: T.unsafe(nil), requireds: T.unsafe(nil), right: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5159,6 +5329,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5236,6 +5409,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, value: Float).returns(FloatNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5292,6 +5468,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, index: T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), index: T.unsafe(nil), collection: T.unsafe(nil), statements: T.unsafe(nil), for_keyword_loc: T.unsafe(nil), in_keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5433,6 +5612,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingArgumentsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5486,6 +5668,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5543,6 +5728,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, block: T.nilable(BlockNode)).returns(ForwardingSuperNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), block: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5599,6 +5787,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5681,6 +5872,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(GlobalVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5763,6 +5957,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5845,6 +6042,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5905,6 +6105,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -5961,6 +6164,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(GlobalVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6059,6 +6265,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), elements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6162,6 +6371,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(HashPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), elements: T.unsafe(nil), rest: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6288,6 +6500,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, if_keyword_loc: T.nilable(Location), predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(T.any(ElseNode, IfNode)), end_keyword_loc: T.nilable(Location)).returns(IfNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), if_keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6437,6 +6652,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, numeric: T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numeric: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6499,6 +6717,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, value: T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6564,6 +6785,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(ImplicitRestNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6616,6 +6840,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: T.nilable(StatementsNode), in_loc: Location, then_loc: T.nilable(Location)).returns(InNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), pattern: T.unsafe(nil), statements: T.unsafe(nil), in_loc: T.unsafe(nil), then_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6702,6 +6929,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6838,6 +7068,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -6974,6 +7207,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7118,6 +7354,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7224,6 +7463,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7306,6 +7548,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(InstanceVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7388,6 +7633,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7470,6 +7718,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7530,6 +7781,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7586,6 +7840,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(InstanceVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7684,6 +7941,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, value: Integer).returns(IntegerNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7756,6 +8016,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -7882,6 +8145,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8008,6 +8274,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: T.nilable(Location)).returns(InterpolatedStringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8098,6 +8367,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: T.nilable(Location)).returns(InterpolatedSymbolNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8180,6 +8452,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8262,6 +8537,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItLocalVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8314,6 +8592,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8366,6 +8647,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8427,6 +8711,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8509,6 +8796,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode))).returns(LambdaNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8612,6 +8902,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8698,6 +8991,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).returns(LocalVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), binary_operator: T.unsafe(nil), depth: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8784,6 +9080,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8870,6 +9169,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -8947,6 +9249,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9007,6 +9312,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).returns(LocalVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9119,6 +9427,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(MatchLastLineNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9258,6 +9569,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchPredicateNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9331,6 +9645,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchRequiredNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9452,6 +9769,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).returns(MatchWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), call: T.unsafe(nil), targets: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9509,6 +9829,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(MissingNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9561,6 +9884,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), module_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9660,6 +9986,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location)).returns(MultiTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9780,6 +10109,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9923,6 +10255,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -9992,6 +10327,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(NilNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10045,6 +10383,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoBlockParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10124,6 +10465,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoKeywordsParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10202,6 +10546,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, maximum: Integer).returns(NumberedParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), maximum: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10258,6 +10605,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, number: Integer).returns(NumberedReferenceReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), number: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10321,6 +10671,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).returns(OptionalKeywordParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10395,6 +10748,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(OptionalParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10481,6 +10837,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(OrNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10570,6 +10929,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, requireds: T::Array[T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: T.nilable(T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), requireds: T.unsafe(nil), optionals: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), keywords: T.unsafe(nil), keyword_rest: T.unsafe(nil), block: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10650,6 +11012,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, body: T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10736,6 +11101,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).returns(PinnedExpressionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10843,6 +11211,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, variable: T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), variable: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -10918,6 +11289,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11013,6 +11387,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11105,6 +11482,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).returns(ProgramNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), statements: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11168,6 +11548,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(RangeNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11258,6 +11641,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).returns(RationalNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numerator: T.unsafe(nil), denominator: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11338,6 +11724,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(RedoNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11390,6 +11779,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(RegularExpressionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11530,6 +11922,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).returns(RequiredKeywordParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11600,6 +11995,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(RequiredParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11660,6 +12058,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).returns(RescueModifierNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), keyword_loc: T.unsafe(nil), rescue_expression: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11738,6 +12139,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: T.nilable(Location), reference: T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(RescueNode)).returns(RescueNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), exceptions: T.unsafe(nil), operator_loc: T.unsafe(nil), reference: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11846,6 +12250,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11928,6 +12335,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(RetryNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -11980,6 +12390,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: T.nilable(ArgumentsNode)).returns(ReturnNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), arguments: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12049,6 +12462,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(SelfNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12102,6 +12518,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, write: T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), write: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12170,6 +12589,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12273,6 +12695,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceEncodingNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12325,6 +12750,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, filepath: String).returns(SourceFileNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), filepath: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12397,6 +12825,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceLineNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12449,6 +12880,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: T.nilable(Node)).returns(SplatNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12518,6 +12952,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).returns(StatementsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12580,6 +13017,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), content_loc: Location, closing_loc: T.nilable(Location), unescaped: String).returns(StringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12696,6 +13136,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil), block: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12798,6 +13241,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), value_loc: T.nilable(Location), closing_loc: T.nilable(Location), unescaped: String).returns(SymbolNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), value_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12905,6 +13351,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer).returns(TrueNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -12957,6 +13406,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, names: T::Array[T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), names: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -13029,6 +13481,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), else_clause: T.nilable(ElseNode), end_keyword_loc: T.nilable(Location)).returns(UnlessNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), else_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -13160,6 +13615,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(UntilNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -13265,6 +13723,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode)).returns(WhenNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), conditions: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -13354,6 +13815,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(WhileNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -13457,6 +13921,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(XStringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end @@ -13560,6 +14027,9 @@ module Prism sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location)).returns(YieldNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end + sig { override.returns(T::Array[T.nilable(Node)]) } + def deconstruct; end + sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } def deconstruct_keys(keys); end From 0aa2363331769c68df733b89d868f99c8d48ac0a Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:51:22 +0100 Subject: [PATCH 070/289] Fix error message for block/lambda with `...` argument They currently complain that the parent method is not forwarding. But the actual problem is that these types of arguments simply don't accept `...` Fixes [Bug #21927] --- config.yml | 2 ++ src/prism.c | 28 +++++++++++++++++-- templates/src/diagnostic.c.erb | 2 ++ ..._not_allow_forward_arguments_in_blocks.txt | 12 +++++++- ...w_forward_arguments_in_lambda_literals.txt | 12 +++++++- 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/config.yml b/config.yml index 472ab291a7..dbf0c9e1e1 100644 --- a/config.yml +++ b/config.yml @@ -17,6 +17,8 @@ errors: - ARGUMENT_FORWARDING_UNBOUND - ARGUMENT_NO_FORWARDING_AMPERSAND - ARGUMENT_NO_FORWARDING_ELLIPSES + - ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA + - ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK - ARGUMENT_NO_FORWARDING_STAR - ARGUMENT_NO_FORWARDING_STAR_STAR - ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT diff --git a/src/prism.c b/src/prism.c index bfa91f4296..3b61472cbc 100644 --- a/src/prism.c +++ b/src/prism.c @@ -13957,6 +13957,7 @@ parse_parameters( bool allows_forwarding_parameters, bool accepts_blocks_in_defaults, bool in_block, + pm_diagnostic_id_t diag_id_forwarding, uint16_t depth ) { pm_do_loop_stack_push(parser, false); @@ -14018,7 +14019,7 @@ parse_parameters( } case PM_TOKEN_UDOT_DOT_DOT: { if (!allows_forwarding_parameters) { - pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); + pm_parser_err_current(parser, diag_id_forwarding); } bool succeeded = update_parameter_state(parser, &parser->current, &order); @@ -14682,6 +14683,7 @@ parse_block_parameters( false, accepts_blocks_in_defaults, true, + is_lambda_literal ? PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA : PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK, (uint16_t) (depth + 1) ); if (!is_lambda_literal) { @@ -18904,7 +18906,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else { // https://bugs.ruby-lang.org/issues/19107 bool allow_trailing_comma = parser->version >= PM_OPTIONS_VERSION_CRUBY_4_1; - params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, allow_trailing_comma, true, true, false, (uint16_t) (depth + 1)); + params = parse_parameters( + parser, + PM_BINDING_POWER_DEFINED, + true, + allow_trailing_comma, + true, + true, + false, + PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES, + (uint16_t) (depth + 1) + ); } lex_state_set(parser, PM_LEX_STATE_BEG); @@ -18927,7 +18939,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b lex_state_set(parser, parser->lex_state | PM_LEX_STATE_LABEL); } - params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, false, (uint16_t) (depth + 1)); + params = parse_parameters( + parser, + PM_BINDING_POWER_DEFINED, + false, + false, + true, + true, + false, + PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES, + (uint16_t) (depth + 1) + ); // Reject `def * = 1` and similar. We have to specifically check // for them because they create ambiguity with optional arguments. diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index a11c7893d3..c943c3afb9 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -102,6 +102,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA] = { "unexpected ... in lambda argument", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK] = { "unexpected ... in block argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR] = { "unexpected `**`; no anonymous keyword rest parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt index df49557617..639dec3af2 100644 --- a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt +++ b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt @@ -1,3 +1,13 @@ a {|...|} - ^~~ unexpected ... when the parent method is not forwarding + ^~~ unexpected ... in block argument + +def foo(...) + a {|...|} + ^~~ unexpected ... in block argument +end + +def foo + a {|...|} + ^~~ unexpected ... in block argument +end diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt index c2405a5c66..03e17683e4 100644 --- a/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt +++ b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt @@ -1,3 +1,13 @@ ->(...) {} - ^~~ unexpected ... when the parent method is not forwarding + ^~~ unexpected ... in lambda argument + +def foo(...) + ->(...) {} + ^~~ unexpected ... in lambda argument +end + +def foo + ->(...) {} + ^~~ unexpected ... in lambda argument +end From 20374ced51d31d10fe803d7e62c8af22c781f6fa Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 2 Mar 2026 11:49:29 -0500 Subject: [PATCH 071/289] Fix in handling in is a unique keyword because it can be the start of a clause or an infix keyword. We need to be explicitly sure that even though in _could_ close an expression context (the body of another in clause) that we are not also parsing an inline in. The exception is the case of a command call, which can never be the LHS of an expression, and so we must immediately exit. [Bug #21925] [Bug #21674] --- snapshots/case_in_in.txt | 81 ++++++++++++++++++++++++++++++ src/prism.c | 17 ++++--- test/prism/fixtures/case_in_in.txt | 4 ++ 3 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 snapshots/case_in_in.txt create mode 100644 test/prism/fixtures/case_in_in.txt diff --git a/snapshots/case_in_in.txt b/snapshots/case_in_in.txt new file mode 100644 index 0000000000..0fcedb0e89 --- /dev/null +++ b/snapshots/case_in_in.txt @@ -0,0 +1,81 @@ +@ ProgramNode (location: (1,0)-(4,3)) +├── flags: ∅ +├── locals: [:event] +└── statements: + @ StatementsNode (location: (1,0)-(4,3)) + ├── flags: ∅ + └── body: (length: 1) + └── @ CaseMatchNode (location: (1,0)-(4,3)) + ├── flags: newline + ├── predicate: + │ @ CallNode (location: (1,5)-(1,9)) + │ ├── flags: variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :args + │ ├── message_loc: (1,5)-(1,9) = "args" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── conditions: (length: 1) + │ └── @ InNode (location: (2,0)-(3,25)) + │ ├── flags: ∅ + │ ├── pattern: + │ │ @ ArrayPatternNode (location: (2,3)-(2,10)) + │ │ ├── flags: ∅ + │ │ ├── constant: ∅ + │ │ ├── requireds: (length: 1) + │ │ │ └── @ LocalVariableTargetNode (location: (2,4)-(2,9)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :event + │ │ │ └── depth: 0 + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── opening_loc: (2,3)-(2,4) = "[" + │ │ └── closing_loc: (2,9)-(2,10) = "]" + │ ├── statements: + │ │ @ StatementsNode (location: (3,2)-(3,25)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ MatchPredicateNode (location: (3,2)-(3,25)) + │ │ ├── flags: newline + │ │ ├── value: + │ │ │ @ CallNode (location: (3,2)-(3,15)) + │ │ │ ├── flags: ∅ + │ │ │ ├── receiver: + │ │ │ │ @ CallNode (location: (3,2)-(3,9)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :context + │ │ │ │ ├── message_loc: (3,2)-(3,9) = "context" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── call_operator_loc: (3,9)-(3,10) = "." + │ │ │ ├── name: :event + │ │ │ ├── message_loc: (3,10)-(3,15) = "event" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── pattern: + │ │ │ @ PinnedVariableNode (location: (3,19)-(3,25)) + │ │ │ ├── flags: ∅ + │ │ │ ├── variable: + │ │ │ │ @ LocalVariableReadNode (location: (3,20)-(3,25)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :event + │ │ │ │ └── depth: 0 + │ │ │ └── operator_loc: (3,19)-(3,20) = "^" + │ │ └── operator_loc: (3,16)-(3,18) = "in" + │ ├── in_loc: (2,0)-(2,2) = "in" + │ └── then_loc: ∅ + ├── else_clause: ∅ + ├── case_keyword_loc: (1,0)-(1,4) = "case" + └── end_keyword_loc: (4,0)-(4,3) = "end" diff --git a/src/prism.c b/src/prism.c index 3b61472cbc..2eb09675ad 100644 --- a/src/prism.c +++ b/src/prism.c @@ -21674,12 +21674,6 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc ) { node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1)); - if (context_terminator(parser->current_context->context, &parser->current)) { - // If this token terminates the current context, then we need to - // stop parsing the expression, as it has become a statement. - return node; - } - switch (PM_NODE_TYPE(node)) { case PM_MULTI_WRITE_NODE: // Multi-write nodes are statements, and cannot be followed by @@ -21792,6 +21786,17 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc break; } } + + if (context_terminator(parser->current_context->context, &parser->current)) { + pm_binding_powers_t next_binding_powers = pm_binding_powers[parser->current.type]; + if ( + !next_binding_powers.binary || + binding_power > next_binding_powers.left || + (PM_NODE_TYPE_P(node, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) node)) + ) { + return node; + } + } } return node; diff --git a/test/prism/fixtures/case_in_in.txt b/test/prism/fixtures/case_in_in.txt new file mode 100644 index 0000000000..a5f9e4ec41 --- /dev/null +++ b/test/prism/fixtures/case_in_in.txt @@ -0,0 +1,4 @@ +case args +in [event] + context.event in ^event +end From 6d97e764873577bd34bf31f2b2e266ec3654c821 Mon Sep 17 00:00:00 2001 From: Seong Yong-ju Date: Thu, 29 Jan 2026 17:45:30 +0900 Subject: [PATCH 072/289] feat: add `is_success` and `is_failure` methods for `ParseResult` Co-Authored-By: Claude Opus 4.5 --- rust/ruby-prism/src/parse_result/mod.rs | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index ab12f8be04..99fad68241 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -184,6 +184,20 @@ impl<'pr> ParseResult<'pr> { pub fn node(&self) -> Node<'_> { Node::new(self.parser, self.node.as_ptr()) } + + /// Returns true if there were no errors during parsing and false if there + /// were. + #[must_use] + pub fn is_success(&self) -> bool { + self.errors().next().is_none() + } + + /// Returns true if there were errors during parsing and false if there were + /// not. + #[must_use] + pub fn is_failure(&self) -> bool { + !self.is_success() + } } impl Drop for ParseResult<'_> { @@ -195,3 +209,22 @@ impl Drop for ParseResult<'_> { } } } + +#[cfg(test)] +mod tests { + use crate::parse; + + #[test] + fn test_is_success() { + let result = parse(b"1 + 1"); + assert!(result.is_success()); + assert!(!result.is_failure()); + } + + #[test] + fn test_is_failure() { + let result = parse(b"<>"); + assert!(result.is_failure()); + assert!(!result.is_success()); + } +} From 4e71dbfc7bd93adc1b9e57af927fdebbfd06b6bd Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 2 Mar 2026 12:25:27 -0500 Subject: [PATCH 073/289] Reject infix operators on command call on writes --- src/prism.c | 30 ++++++++++++++++++++++++--- test/prism/errors/command_call_in.txt | 2 ++ test/prism/errors/write_command.txt | 4 ++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 test/prism/errors/write_command.txt diff --git a/src/prism.c b/src/prism.c index 2eb09675ad..2603bf7adb 100644 --- a/src/prism.c +++ b/src/prism.c @@ -21605,6 +21605,26 @@ pm_call_node_command_p(const pm_call_node_t *node) { ); } +/** + * Determine if a given write node has a command call as its right-hand side. We + * need this because command calls as the values of writes cannot be extended by + * infix operators. + */ +static inline bool +pm_write_node_command_p(const pm_node_t *node) { + pm_node_t *value; + switch (PM_NODE_TYPE(node)) { + case PM_CLASS_VARIABLE_WRITE_NODE: value = ((pm_class_variable_write_node_t *) node)->value; break; + case PM_CONSTANT_PATH_WRITE_NODE: value = ((pm_constant_path_write_node_t *) node)->value; break; + case PM_CONSTANT_WRITE_NODE: value = ((pm_constant_write_node_t *) node)->value; break; + case PM_GLOBAL_VARIABLE_WRITE_NODE: value = ((pm_global_variable_write_node_t *) node)->value; break; + case PM_INSTANCE_VARIABLE_WRITE_NODE: value = ((pm_instance_variable_write_node_t *) node)->value; break; + case PM_LOCAL_VARIABLE_WRITE_NODE: value = ((pm_local_variable_write_node_t *) node)->value; break; + default: return false; + } + return PM_NODE_TYPE_P(value, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) value); +} + /** * Parse an expression at the given point of the parser using the given binding * power to parse subsequent chains. If this function finds a syntax error, it @@ -21689,9 +21709,13 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc case PM_INSTANCE_VARIABLE_WRITE_NODE: case PM_LOCAL_VARIABLE_WRITE_NODE: // These expressions are statements, by virtue of the right-hand - // side of their write being an implicit array. - if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { - return node; + // side of their write being an implicit array or a command call. + // This mirrors parse.y's behavior where `lhs = command_call` + // reduces to stmt (not expr), preventing and/or from following. + if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { + if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) || pm_write_node_command_p(node)) { + return node; + } } break; case PM_CALL_NODE: diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt index 2fdcf09738..e9e8e82d3a 100644 --- a/test/prism/errors/command_call_in.txt +++ b/test/prism/errors/command_call_in.txt @@ -2,4 +2,6 @@ foo 1 in a ^~ unexpected 'in', expecting end-of-input ^~ unexpected 'in', ignoring it a = foo 2 in b + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it diff --git a/test/prism/errors/write_command.txt b/test/prism/errors/write_command.txt new file mode 100644 index 0000000000..5024f8452a --- /dev/null +++ b/test/prism/errors/write_command.txt @@ -0,0 +1,4 @@ +a = b c and 1 + ^~~ unexpected 'and', expecting end-of-input + ^~~ unexpected 'and', ignoring it + From b38010c4202734d692a922b6db2014d9cb96ef67 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 2 Mar 2026 12:43:30 -0500 Subject: [PATCH 074/289] Require arguments to Source.for --- lib/prism/parse_result.rb | 18 +++++++++++----- rbi/generated/prism/dsl.rbi | 2 +- rbi/generated/prism/node.rbi | 31 ++++++++++++++-------------- rbi/generated/prism/parse_result.rbi | 12 +++++++++-- sig/generated/prism/dsl.rbs | 2 +- sig/generated/prism/node.rbs | 31 ++++++++++++++-------------- sig/generated/prism/parse_result.rbs | 16 ++++++++++---- templates/lib/prism/dsl.rb.erb | 6 +++--- templates/lib/prism/serialize.rb.erb | 8 +++---- 9 files changed, 74 insertions(+), 52 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 9825d559af..c6bb6e5f1f 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -19,9 +19,17 @@ class Source # be used instead of `new` and it will return either a `Source` or a # specialized and more performant `ASCIISource` if no multibyte characters # are present in the source code. - #-- - #: (String source, ?Integer start_line, ?Array[Integer] offsets) -> Source - def self.for(source, start_line = 1, offsets = []) + # + # Note that if you are calling this method manually, you will need to supply + # the start_line and offsets parameters. start_line is the line number that + # the source starts on, which is typically 1 but can be different if this + # source is a subset of a larger source or if this is an eval. offsets is an + # array of byte offsets for the start of each line in the source code, which + # can be calculated by iterating through the source code and recording the + # byte offset whenever a newline character is encountered. + #-- + #: (String source, Integer start_line, Array[Integer] offsets) -> Source + def self.for(source, start_line, offsets) if source.ascii_only? ASCIISource.new(source, start_line, offsets) elsif source.encoding == Encoding::BINARY @@ -55,8 +63,8 @@ def self.for(source, start_line = 1, offsets = []) # Create a new source object with the given source code. #-- - #: (String source, ?Integer start_line, ?Array[Integer] offsets) -> void - def initialize(source, start_line = 1, offsets = []) + #: (String source, Integer start_line, Array[Integer] offsets) -> void + def initialize(source, start_line, offsets) @source = source @start_line = start_line # set after parsing is done @offsets = offsets # set after parsing is done diff --git a/rbi/generated/prism/dsl.rbi b/rbi/generated/prism/dsl.rbi index 40eaccc727..d03b4f5a47 100644 --- a/rbi/generated/prism/dsl.rbi +++ b/rbi/generated/prism/dsl.rbi @@ -4,7 +4,7 @@ module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: # - # source = Prism::Source.for("[1]") + # source = Prism::Source.for("[1]", 1, []) # # Prism::ArrayNode.new( # source, diff --git a/rbi/generated/prism/node.rbi b/rbi/generated/prism/node.rbi index 1664fd88b7..324250b8c0 100644 --- a/rbi/generated/prism/node.rbi +++ b/rbi/generated/prism/node.rbi @@ -782,19 +782,19 @@ module Prism # Represents an array pattern in pattern matching. # # foo in 1, 2 - # ^^^^^^^^^^^ + # ^^^^ # # foo in [1, 2] - # ^^^^^^^^^^^^^ + # ^^^^^^ # # foo in *bar - # ^^^^^^^^^^^ + # ^^^^ # # foo in Bar[] - # ^^^^^^^^^^^^ + # ^^^^^ # # foo in Bar[1, 2, 3] - # ^^^^^^^^^^^^^^^^^^^ + # ^^^^^^^^^^^^ class ArrayPatternNode < Node # Initialize a new ArrayPatternNode node. sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } @@ -1229,7 +1229,7 @@ module Prism # Represents the else clause within the begin block. # # begin x; rescue y; else z; end - # ^^^^^^ + # ^^^^^^^^^^^ sig { returns(T.nilable(ElseNode)) } def else_clause; end @@ -1267,7 +1267,7 @@ module Prism # Represents a block argument using `&`. # # bar(&args) - # ^^^^^^^^^^ + # ^^^^^ class BlockArgumentNode < Node # Initialize a new BlockArgumentNode node. sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).void } @@ -1318,7 +1318,7 @@ module Prism # The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). # # foo(&args) - # ^^^^^ + # ^^^^ sig { returns(T.nilable(Node)) } def expression; end @@ -2594,7 +2594,7 @@ module Prism # Represents assigning to a local variable in pattern matching. # # foo => [bar => baz] - # ^^^^^^^^^^^^ + # ^^^^^^^^^^ class CapturePatternNode < Node # Initialize a new CapturePatternNode node. sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).void } @@ -2732,7 +2732,7 @@ module Prism # Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). # # case true; in false; end - # ^^^^ + # ^^^^ sig { returns(T.nilable(Node)) } def predicate; end @@ -2746,7 +2746,7 @@ module Prism # Represents the else clause of the case match. # # case true; in false; else; end - # ^^^^ + # ^^^^^^^^^ sig { returns(T.nilable(ElseNode)) } def else_clause; end @@ -2856,7 +2856,7 @@ module Prism # Represents the else clause of the case statement. # # case true; when false; else; end - # ^^^^ + # ^^^^^^^^^ sig { returns(T.nilable(ElseNode)) } def else_clause; end @@ -2988,9 +2988,8 @@ module Prism # Represents the body of the class. # - # class Foo - # foo - # ^^^ + # class Foo; bar; end + # ^^^ sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } def body; end @@ -13546,7 +13545,7 @@ module Prism # The else clause of the unless expression, if present. # # unless cond then bar else baz end - # ^^^^^^^^ + # ^^^^^^^^^^^^ sig { returns(T.nilable(ElseNode)) } def else_clause; end diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi index 6501e3cfaf..7629e0a1cb 100644 --- a/rbi/generated/prism/parse_result.rbi +++ b/rbi/generated/prism/parse_result.rbi @@ -9,8 +9,16 @@ module Prism # be used instead of `new` and it will return either a `Source` or a # specialized and more performant `ASCIISource` if no multibyte characters # are present in the source code. + # + # Note that if you are calling this method manually, you will need to supply + # the start_line and offsets parameters. start_line is the line number that + # the source starts on, which is typically 1 but can be different if this + # source is a subset of a larger source or if this is an eval. offsets is an + # array of byte offsets for the start of each line in the source code, which + # can be calculated by iterating through the source code and recording the + # byte offset whenever a newline character is encountered. sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).returns(Source) } - def self.for(source, start_line = T.unsafe(nil), offsets = T.unsafe(nil)); end + def self.for(source, start_line, offsets); end # The source code that this source object represents. sig { returns(String) } @@ -26,7 +34,7 @@ module Prism # Create a new source object with the given source code. sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).void } - def initialize(source, start_line = T.unsafe(nil), offsets = T.unsafe(nil)); end + def initialize(source, start_line, offsets); end # Replace the value of start_line with the given value. sig { params(start_line: Integer).void } diff --git a/sig/generated/prism/dsl.rbs b/sig/generated/prism/dsl.rbs index 6b5e4bbc75..4b09efccd3 100644 --- a/sig/generated/prism/dsl.rbs +++ b/sig/generated/prism/dsl.rbs @@ -4,7 +4,7 @@ module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: # - # source = Prism::Source.for("[1]") + # source = Prism::Source.for("[1]", 1, []) # # Prism::ArrayNode.new( # source, diff --git a/sig/generated/prism/node.rbs b/sig/generated/prism/node.rbs index bb42a24caf..94b8967bd4 100644 --- a/sig/generated/prism/node.rbs +++ b/sig/generated/prism/node.rbs @@ -1051,19 +1051,19 @@ module Prism # Represents an array pattern in pattern matching. # # foo in 1, 2 - # ^^^^^^^^^^^ + # ^^^^ # # foo in [1, 2] - # ^^^^^^^^^^^^^ + # ^^^^^^ # # foo in *bar - # ^^^^^^^^^^^ + # ^^^^ # # foo in Bar[] - # ^^^^^^^^^^^^ + # ^^^^^ # # foo in Bar[1, 2, 3] - # ^^^^^^^^^^^^^^^^^^^ + # ^^^^^^^^^^^^ class ArrayPatternNode < Node @closing_loc: Location? @@ -1688,7 +1688,7 @@ module Prism # Represents the else clause within the begin block. # # begin x; rescue y; else z; end - # ^^^^^^ + # ^^^^^^^^^^^ # -- # : () -> ElseNode? def else_clause: () -> ElseNode? @@ -1746,7 +1746,7 @@ module Prism # Represents a block argument using `&`. # # bar(&args) - # ^^^^^^^^^^ + # ^^^^^ class BlockArgumentNode < Node @operator_loc: Location @@ -1816,7 +1816,7 @@ module Prism # The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). # # foo(&args) - # ^^^^^ + # ^^^^ # -- # : () -> Prism::node? def expression: () -> Prism::node? @@ -3721,7 +3721,7 @@ module Prism # Represents assigning to a local variable in pattern matching. # # foo => [bar => baz] - # ^^^^^^^^^^^^ + # ^^^^^^^^^^ class CapturePatternNode < Node @operator_loc: Location @@ -3921,7 +3921,7 @@ module Prism # Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). # # case true; in false; end - # ^^^^ + # ^^^^ # -- # : () -> Prism::node? def predicate: () -> Prism::node? @@ -3943,7 +3943,7 @@ module Prism # Represents the else clause of the case match. # # case true; in false; else; end - # ^^^^ + # ^^^^^^^^^ # -- # : () -> ElseNode? def else_clause: () -> ElseNode? @@ -4109,7 +4109,7 @@ module Prism # Represents the else clause of the case statement. # # case true; when false; else; end - # ^^^^ + # ^^^^^^^^^ # -- # : () -> ElseNode? def else_clause: () -> ElseNode? @@ -4321,9 +4321,8 @@ module Prism # # Represents the body of the class. # - # class Foo - # foo - # ^^^ + # class Foo; bar; end + # ^^^ # -- # : () -> (StatementsNode | BeginNode)? def body: () -> (StatementsNode | BeginNode)? @@ -19843,7 +19842,7 @@ module Prism # The else clause of the unless expression, if present. # # unless cond then bar else baz end - # ^^^^^^^^ + # ^^^^^^^^^^^^ # -- # : () -> ElseNode? def else_clause: () -> ElseNode? diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs index 96b1665d06..ca8cb4bbfe 100644 --- a/sig/generated/prism/parse_result.rbs +++ b/sig/generated/prism/parse_result.rbs @@ -15,9 +15,17 @@ module Prism # be used instead of `new` and it will return either a `Source` or a # specialized and more performant `ASCIISource` if no multibyte characters # are present in the source code. + # + # Note that if you are calling this method manually, you will need to supply + # the start_line and offsets parameters. start_line is the line number that + # the source starts on, which is typically 1 but can be different if this + # source is a subset of a larger source or if this is an eval. offsets is an + # array of byte offsets for the start of each line in the source code, which + # can be calculated by iterating through the source code and recording the + # byte offset whenever a newline character is encountered. # -- - # : (String source, ?Integer start_line, ?Array[Integer] offsets) -> Source - def self.for: (String source, ?Integer start_line, ?Array[Integer] offsets) -> Source + # : (String source, Integer start_line, Array[Integer] offsets) -> Source + def self.for: (String source, Integer start_line, Array[Integer] offsets) -> Source # The source code that this source object represents. attr_reader source: String @@ -30,8 +38,8 @@ module Prism # Create a new source object with the given source code. # -- - # : (String source, ?Integer start_line, ?Array[Integer] offsets) -> void - def initialize: (String source, ?Integer start_line, ?Array[Integer] offsets) -> void + # : (String source, Integer start_line, Array[Integer] offsets) -> void + def initialize: (String source, Integer start_line, Array[Integer] offsets) -> void # Replace the value of start_line with the given value. # -- diff --git a/templates/lib/prism/dsl.rb.erb b/templates/lib/prism/dsl.rb.erb index a75b8b253e..6dcbbec100 100644 --- a/templates/lib/prism/dsl.rb.erb +++ b/templates/lib/prism/dsl.rb.erb @@ -5,7 +5,7 @@ module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: # - # source = Prism::Source.for("[1]") + # source = Prism::Source.for("[1]", 1, []) # # Prism::ArrayNode.new( # source, @@ -62,7 +62,7 @@ module Prism #-- #: (String string) -> Source def source(string) - Source.for(string) + Source.for(string, 1, []) end # Create a new Location object. @@ -136,7 +136,7 @@ module Prism #-- #: () -> Source def default_source - Source.for("") + Source.for("", 1, []) end # The default location object that gets attached to nodes if no location is diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index 433b520788..c336662f2c 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -27,7 +27,7 @@ module Prism #: (String input, String serialized, bool freeze) -> ParseResult def self.load_parse(input, serialized, freeze) input = input.dup - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) loader.load_header @@ -81,7 +81,7 @@ module Prism #-- #: (String input, String serialized, bool freeze) -> LexResult def self.load_lex(input, serialized, freeze) - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) tokens = loader.load_tokens @@ -127,7 +127,7 @@ module Prism #-- #: (String input, String serialized, bool freeze) -> Array[Comment] def self.load_parse_comments(input, serialized, freeze) - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) loader.load_header @@ -151,7 +151,7 @@ module Prism #-- #: (String input, String serialized, bool freeze) -> ParseLexResult def self.load_parse_lex(input, serialized, freeze) - source = Source.for(input) + source = Source.for(input, 1, []) loader = Loader.new(source, serialized) tokens = loader.load_tokens From 4896994d64a79503c8eb5e21d5c4d9e7900797cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:35:46 +0000 Subject: [PATCH 075/289] Bump the action-deps group with 2 updates Bumps the action-deps group with 2 updates: [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact). Updates `actions/upload-artifact` from 6 to 7 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) Updates `actions/download-artifact` from 7 to 8 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: action-deps - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major dependency-group: action-deps ... Signed-off-by: dependabot[bot] --- .github/workflows/java-wasm-bindings.yml | 2 +- .github/workflows/javascript-bindings.yml | 2 +- .github/workflows/main.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 679fb09a8b..d7fe81f171 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -45,7 +45,7 @@ jobs: run: mvn -B install working-directory: java-wasm - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: prism.wasm path: java-wasm/src/test/resources/prism.wasm diff --git a/.github/workflows/javascript-bindings.yml b/.github/workflows/javascript-bindings.yml index 6e7d51f282..3753ea2ce9 100644 --- a/.github/workflows/javascript-bindings.yml +++ b/.github/workflows/javascript-bindings.yml @@ -34,7 +34,7 @@ jobs: - name: Build the project run: make wasm WASI_SDK_PATH=$(pwd)/wasi-sdk-25.0-x86_64-linux - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: prism.wasm path: javascript/src/prism.wasm diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 391dfdd91d..9ed312d4d5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -257,7 +257,7 @@ jobs: bundler-cache: true - run: bundle config --local frozen false - run: bundle exec rake build:dev - - uses: actions/upload-artifact@v6 + - uses: actions/upload-artifact@v7 with: name: gem-package path: pkg @@ -308,7 +308,7 @@ jobs: - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.target.ruby }} - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v8 with: name: gem-package path: pkg From c2479eff4760c18884afb01eaabc45a91bdc2053 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:34:18 +0000 Subject: [PATCH 076/289] Bump the java-deps group in /java-wasm with 3 updates Bumps the java-deps group in /java-wasm with 3 updates: [com.dylibso.chicory:bom](https://github.com/dylibso/chicory), com.dylibso.chicory:annotations-processor and [com.dylibso.chicory:chicory-compiler-maven-plugin](https://github.com/dylibso/chicory). Updates `com.dylibso.chicory:bom` from 1.6.1 to 1.7.2 - [Release notes](https://github.com/dylibso/chicory/releases) - [Commits](https://github.com/dylibso/chicory/compare/1.6.1...1.7.2) Updates `com.dylibso.chicory:annotations-processor` from 1.6.1 to 1.7.2 Updates `com.dylibso.chicory:chicory-compiler-maven-plugin` from 1.6.1 to 1.7.2 - [Release notes](https://github.com/dylibso/chicory/releases) - [Commits](https://github.com/dylibso/chicory/compare/1.6.1...1.7.2) Updates `com.dylibso.chicory:annotations-processor` from 1.6.1 to 1.7.2 Updates `com.dylibso.chicory:chicory-compiler-maven-plugin` from 1.6.1 to 1.7.2 - [Release notes](https://github.com/dylibso/chicory/releases) - [Commits](https://github.com/dylibso/chicory/compare/1.6.1...1.7.2) --- updated-dependencies: - dependency-name: com.dylibso.chicory:bom dependency-version: 1.7.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: java-deps - dependency-name: com.dylibso.chicory:annotations-processor dependency-version: 1.7.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: java-deps - dependency-name: com.dylibso.chicory:chicory-compiler-maven-plugin dependency-version: 1.7.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: java-deps - dependency-name: com.dylibso.chicory:annotations-processor dependency-version: 1.7.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: java-deps - dependency-name: com.dylibso.chicory:chicory-compiler-maven-plugin dependency-version: 1.7.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: java-deps ... Signed-off-by: dependabot[bot] --- java-wasm/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index b37e86090d..ea94a82130 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -15,7 +15,7 @@ 21 21 - 1.6.1 + 1.7.2 6.0.3 From c5882ce2bc1a4a9ca7eddd43cb37cb45a1f530f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:41:25 +0000 Subject: [PATCH 077/289] Bump rbi Bumps the ruby-deps group with 1 update in the /gemfiles/typecheck directory: [rbi](https://github.com/Shopify/rbi). Updates `rbi` from 0.3.7 to 0.3.9 - [Release notes](https://github.com/Shopify/rbi/releases) - [Commits](https://github.com/Shopify/rbi/compare/v0.3.7...v0.3.9) --- updated-dependencies: - dependency-name: rbi dependency-version: 0.3.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ruby-deps ... Signed-off-by: dependabot[bot] --- gemfiles/typecheck/Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gemfiles/typecheck/Gemfile.lock b/gemfiles/typecheck/Gemfile.lock index 4460d320e9..a5363e44fb 100644 --- a/gemfiles/typecheck/Gemfile.lock +++ b/gemfiles/typecheck/Gemfile.lock @@ -42,7 +42,7 @@ GEM ast (~> 2.4.1) racc power_assert (3.0.1) - prism (1.7.0) + prism (1.9.0) racc (1.8.1) rainbow (3.1.1) rake (13.3.1) @@ -51,7 +51,7 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rbi (0.3.7) + rbi (0.3.9) prism (~> 1.0) rbs (>= 3.4.4) rbs (3.10.3) From 6701ffe0f540a42fdaea9031749158b6c6d47b9d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 2 Mar 2026 14:10:45 -0500 Subject: [PATCH 078/289] Prism::ParseResult#continuable? An API to determine if more input could fix the existing syntax errors. --- lib/prism/parse_result.rb | 72 ++++++++++++++++++++++++++++ rbi/generated/prism/parse_result.rbi | 29 +++++++++++ sig/generated/prism/parse_result.rbs | 30 ++++++++++++ test/prism/errors_test.rb | 35 ++++++++++++++ 4 files changed, 166 insertions(+) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index c6bb6e5f1f..4898fdd435 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -938,6 +938,78 @@ def failure? !success? end + # Returns true if the parsed source is an incomplete expression that could + # become valid with additional input. This is useful for REPL contexts (such + # as IRB) where the user may be entering a multi-line expression one line at + # a time and the implementation needs to determine whether to wait for more + # input or to evaluate what has been entered so far. + # + # Concretely, this returns true when every error present is caused by the + # parser reaching the end of the input before a construct was closed (e.g. + # an unclosed string, array, block, or keyword), and returns false when any + # error is caused by a token that makes the input structurally invalid + # regardless of what might follow (e.g. a stray `end`, `]`, or `)` with no + # matching opener). + # + # Examples: + # + # Prism.parse("1 + [").continuable? #=> true (unclosed array) + # Prism.parse("1 + ]").continuable? #=> false (stray ]) + # Prism.parse("tap do").continuable? #=> true (unclosed block) + # Prism.parse("end.tap do").continuable? #=> false (stray end) + # + #-- + #: () -> bool + def continuable? + return false if errors.empty? + + offset = source.source.bytesize + errors.all? { |error| CONTINUABLE.include?(error.type) || error.location.start_offset == offset } + end + + # The set of error types whose location the parser places at the opening + # token of an unclosed construct rather than at the end of the source. These + # errors always indicate incomplete input regardless of their byte position, + # so they are checked by type rather than by location. + #-- + #: Array[Symbol] + CONTINUABLE = %i[ + begin_term + begin_upcase_term + block_param_pipe_term + block_term_brace + block_term_end + case_missing_conditions + case_term + class_term + conditional_term + conditional_term_else + def_term + embdoc_term + end_upcase_term + for_term + hash_term + heredoc_term + lambda_term_brace + lambda_term_end + list_i_lower_term + list_i_upper_term + list_w_lower_term + list_w_upper_term + module_term + regexp_term + rescue_term + string_interpolated_term + string_literal_eof + symbol_term_dynamic + symbol_term_interpolated + until_term + while_term + xstring_term + ].freeze + + private_constant :CONTINUABLE + # Create a code units cache for the given encoding. #-- #: (Encoding encoding) -> _CodeUnitsCache diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi index 7629e0a1cb..51297530c3 100644 --- a/rbi/generated/prism/parse_result.rbi +++ b/rbi/generated/prism/parse_result.rbi @@ -579,6 +579,35 @@ module Prism sig { returns(T::Boolean) } def failure?; end + # Returns true if the parsed source is an incomplete expression that could + # become valid with additional input. This is useful for REPL contexts (such + # as IRB) where the user may be entering a multi-line expression one line at + # a time and the implementation needs to determine whether to wait for more + # input or to evaluate what has been entered so far. + # + # Concretely, this returns true when every error present is caused by the + # parser reaching the end of the input before a construct was closed (e.g. + # an unclosed string, array, block, or keyword), and returns false when any + # error is caused by a token that makes the input structurally invalid + # regardless of what might follow (e.g. a stray `end`, `]`, or `)` with no + # matching opener). + # + # Examples: + # + # Prism.parse("1 + [").continuable? #=> true (unclosed array) + # Prism.parse("1 + ]").continuable? #=> false (stray ]) + # Prism.parse("tap do").continuable? #=> true (unclosed block) + # Prism.parse("end.tap do").continuable? #=> false (stray end) + # + sig { returns(T::Boolean) } + def continuable?; end + + # The set of error types whose location the parser places at the opening + # token of an unclosed construct rather than at the end of the source. These + # errors always indicate incomplete input regardless of their byte position, + # so they are checked by type rather than by location. + CONTINUABLE = T.let(nil, T.untyped) + # Create a code units cache for the given encoding. sig { params(encoding: Encoding).returns(T.untyped) } def code_units_cache(encoding); end diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs index ca8cb4bbfe..af25241fdb 100644 --- a/sig/generated/prism/parse_result.rbs +++ b/sig/generated/prism/parse_result.rbs @@ -669,6 +669,36 @@ module Prism # : () -> bool def failure?: () -> bool + # Returns true if the parsed source is an incomplete expression that could + # become valid with additional input. This is useful for REPL contexts (such + # as IRB) where the user may be entering a multi-line expression one line at + # a time and the implementation needs to determine whether to wait for more + # input or to evaluate what has been entered so far. + # + # Concretely, this returns true when every error present is caused by the + # parser reaching the end of the input before a construct was closed (e.g. + # an unclosed string, array, block, or keyword), and returns false when any + # error is caused by a token that makes the input structurally invalid + # regardless of what might follow (e.g. a stray `end`, `]`, or `)` with no + # matching opener). + # + # Examples: + # + # Prism.parse("1 + [").continuable? #=> true (unclosed array) + # Prism.parse("1 + ]").continuable? #=> false (stray ]) + # Prism.parse("tap do").continuable? #=> true (unclosed block) + # Prism.parse("end.tap do").continuable? #=> false (stray end) + # + # -- + # : () -> bool + def continuable?: () -> bool + + # The set of error types whose location the parser places at the opening + # token of an unclosed construct rather than at the end of the source. These + # errors always indicate incomplete input regardless of their byte position, + # so they are checked by type rather than by location. + CONTINUABLE: untyped + # Create a code units cache for the given encoding. # -- # : (Encoding encoding) -> _CodeUnitsCache diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 27610e89d3..898f4afb45 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -109,6 +109,41 @@ def test_unclosed_heredoc_and_interpolation assert_nil(statement.parts[0].statements) end + def test_continuable + # Valid input is not continuable (nothing to continue). + refute_predicate Prism.parse("1 + 1"), :continuable? + refute_predicate Prism.parse(""), :continuable? + + # Stray closing tokens make input non-continuable regardless of what + # follows (matches the feature-request examples exactly). + refute_predicate Prism.parse("1 + ]"), :continuable? + refute_predicate Prism.parse("end.tap do"), :continuable? + + # Unclosed constructs are continuable. + assert_predicate Prism.parse("1 + ["), :continuable? + assert_predicate Prism.parse("tap do"), :continuable? + + # Unclosed keywords. + assert_predicate Prism.parse("def foo"), :continuable? + assert_predicate Prism.parse("class Foo"), :continuable? + assert_predicate Prism.parse("module Foo"), :continuable? + assert_predicate Prism.parse("if true"), :continuable? + assert_predicate Prism.parse("while true"), :continuable? + assert_predicate Prism.parse("begin"), :continuable? + assert_predicate Prism.parse("for x in [1]"), :continuable? + + # Unclosed delimiters. + assert_predicate Prism.parse("{"), :continuable? + assert_predicate Prism.parse("foo("), :continuable? + assert_predicate Prism.parse('"hello'), :continuable? + assert_predicate Prism.parse("'hello"), :continuable? + assert_predicate Prism.parse("<<~HEREDOC\nhello"), :continuable? + + # A mix: stray end plus an unclosed block is not continuable because the + # stray end cannot be fixed by appending more input. + refute_predicate Prism.parse("end\ntap do"), :continuable? + end + private def assert_errors(filepath, version) From 0f47e183356bb8e2ba3923741f8233259a594e22 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 2 Mar 2026 15:24:46 -0500 Subject: [PATCH 079/289] Fix up endless method definition with do/end [Bug #21714] --- config.yml | 1 + src/prism.c | 14 ++++++++++++++ templates/src/diagnostic.c.erb | 1 + test/prism/errors/def_endless_do.txt | 3 +++ 4 files changed, 19 insertions(+) create mode 100644 test/prism/errors/def_endless_do.txt diff --git a/config.yml b/config.yml index dbf0c9e1e1..d8a10bc113 100644 --- a/config.yml +++ b/config.yml @@ -64,6 +64,7 @@ errors: - DEF_ENDLESS - DEF_ENDLESS_PARAMETERS - DEF_ENDLESS_SETTER + - DEF_ENDLESS_DO_BLOCK - DEF_NAME - DEF_PARAMS_TERM - DEF_PARAMS_TERM_PAREN diff --git a/src/prism.c b/src/prism.c index 2603bf7adb..c644c94753 100644 --- a/src/prism.c +++ b/src/prism.c @@ -18998,6 +18998,20 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_command_call, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); + // In an endless method definition, the body is not allowed to + // be a command with a do..end block. + if (PM_NODE_TYPE_P(statement, PM_CALL_NODE)) { + pm_call_node_t *call = (pm_call_node_t *) statement; + + if (call->arguments != NULL && call->block != NULL && PM_NODE_TYPE_P(call->block, PM_BLOCK_NODE)) { + pm_block_node_t *block = (pm_block_node_t *) call->block; + + if (parser->start[block->opening_loc.start] != '{') { + pm_parser_err_node(parser, call->block, PM_ERR_DEF_ENDLESS_DO_BLOCK); + } + } + } + if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { context_push(parser, PM_CONTEXT_RESCUE_MODIFIER); diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index c943c3afb9..d717dc1e16 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -148,6 +148,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_ENDLESS_PARAMETERS] = { "could not parse the endless method parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_DEF_ENDLESS_DO_BLOCK] = { "unexpected `do` for block in an endless method definition", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "unexpected %s; expected a `)` to close the parameters", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors/def_endless_do.txt b/test/prism/errors/def_endless_do.txt new file mode 100644 index 0000000000..4d786638a6 --- /dev/null +++ b/test/prism/errors/def_endless_do.txt @@ -0,0 +1,3 @@ +def a = a b do 1 end + ^~~~~~~~ unexpected `do` for block in an endless method definition + From 02c944c055be51090b7cbc1bb02b7a4a866ea58e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 3 Mar 2026 08:16:42 -0500 Subject: [PATCH 080/289] Fix modifier rescue pattern matching [Bug #21713] --- src/prism.c | 13 +++++++++++++ ..._predicate_after_rescue_with_dot_method_call.txt | 1 + .../match_predicate_after_rescue_with_opreator.txt | 1 + ...h_required_after_rescue_with_dot_method_call.txt | 1 + .../match_required_after_rescue_with_opreator.txt | 1 + test/prism/errors/rescue_pattern.txt | 4 ++++ 6 files changed, 21 insertions(+) create mode 100644 test/prism/errors/rescue_pattern.txt diff --git a/src/prism.c b/src/prism.c index c644c94753..ebd86b01fe 100644 --- a/src/prism.c +++ b/src/prism.c @@ -21740,6 +21740,19 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc return node; } break; + case PM_RESCUE_MODIFIER_NODE: + // A rescue modifier whose handler is a one-liner pattern match + // (=> or in) produces a statement. That means it cannot be + // extended by operators above the modifier level. + if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { + pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; + pm_node_t *rescue_expression = cast->rescue_expression; + + if (PM_NODE_TYPE_P(rescue_expression, PM_MATCH_REQUIRED_NODE) || PM_NODE_TYPE_P(rescue_expression, PM_MATCH_PREDICATE_NODE)) { + return node; + } + } + break; default: break; } diff --git a/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt b/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt index fead8aaf23..f599dc476b 100644 --- a/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt +++ b/test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt @@ -1,3 +1,4 @@ 'a' rescue 2 in 3.upcase ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it diff --git a/test/prism/errors/match_predicate_after_rescue_with_opreator.txt b/test/prism/errors/match_predicate_after_rescue_with_opreator.txt index b2363a544d..44a4ba8488 100644 --- a/test/prism/errors/match_predicate_after_rescue_with_opreator.txt +++ b/test/prism/errors/match_predicate_after_rescue_with_opreator.txt @@ -1,3 +1,4 @@ 1 rescue 2 in 3 << 4 ^~ unexpected <<, expecting end-of-input + ^~ unexpected <<, ignoring it diff --git a/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt b/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt index d72d72ce60..abcfaf094d 100644 --- a/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt +++ b/test/prism/errors/match_required_after_rescue_with_dot_method_call.txt @@ -1,3 +1,4 @@ 1 rescue 2 => 3.inspect ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it diff --git a/test/prism/errors/match_required_after_rescue_with_opreator.txt b/test/prism/errors/match_required_after_rescue_with_opreator.txt index 903e2ccc8e..5e6387ca4d 100644 --- a/test/prism/errors/match_required_after_rescue_with_opreator.txt +++ b/test/prism/errors/match_required_after_rescue_with_opreator.txt @@ -1,3 +1,4 @@ 1 rescue 2 => 3 ** 4 ^~ unexpected '**', expecting end-of-input + ^~ unexpected '**', ignoring it diff --git a/test/prism/errors/rescue_pattern.txt b/test/prism/errors/rescue_pattern.txt new file mode 100644 index 0000000000..c85feb27bd --- /dev/null +++ b/test/prism/errors/rescue_pattern.txt @@ -0,0 +1,4 @@ +a rescue b => c in d + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + From 03993421f2029e38c392660db3f3bb395dcb7c34 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:49:25 +0100 Subject: [PATCH 081/289] Revert "Reject infix operators on command call on writes" (#3960) This reverts commit 4e71dbfc7bd93adc1b9e57af927fdebbfd06b6bd. And also add a regression test. Seems like currently prism parses these the same that parse.y does. --- snapshots/write_command_operator.txt | 84 +++++++++++++++++++ src/prism.c | 30 +------ test/prism/errors/command_call_in.txt | 2 - test/prism/errors/write_command.txt | 4 - .../prism/fixtures/write_command_operator.txt | 3 + 5 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 snapshots/write_command_operator.txt delete mode 100644 test/prism/errors/write_command.txt create mode 100644 test/prism/fixtures/write_command_operator.txt diff --git a/snapshots/write_command_operator.txt b/snapshots/write_command_operator.txt new file mode 100644 index 0000000000..f1d92729ed --- /dev/null +++ b/snapshots/write_command_operator.txt @@ -0,0 +1,84 @@ +@ ProgramNode (location: (1,0)-(3,24)) +├── flags: ∅ +├── locals: [:foo] +└── statements: + @ StatementsNode (location: (1,0)-(3,24)) + ├── flags: ∅ + └── body: (length: 2) + ├── @ OrNode (location: (1,0)-(1,27)) + │ ├── flags: newline + │ ├── left: + │ │ @ LocalVariableWriteNode (location: (1,0)-(1,17)) + │ │ ├── flags: ∅ + │ │ ├── name: :foo + │ │ ├── depth: 0 + │ │ ├── name_loc: (1,0)-(1,3) = "foo" + │ │ ├── value: + │ │ │ @ CallNode (location: (1,6)-(1,17)) + │ │ │ ├── flags: ∅ + │ │ │ ├── receiver: + │ │ │ │ @ IntegerNode (location: (1,6)-(1,9)) + │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ └── value: 123 + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :| + │ │ │ ├── message_loc: (1,10)-(1,11) = "|" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (1,12)-(1,17)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ StringNode (location: (1,12)-(1,17)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: (1,12)-(1,13) = "'" + │ │ │ │ ├── content_loc: (1,13)-(1,16) = "456" + │ │ │ │ ├── closing_loc: (1,16)-(1,17) = "'" + │ │ │ │ └── unescaped: "456" + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ └── operator_loc: (1,4)-(1,5) = "=" + │ ├── right: + │ │ @ ReturnNode (location: (1,21)-(1,27)) + │ │ ├── flags: ∅ + │ │ ├── keyword_loc: (1,21)-(1,27) = "return" + │ │ └── arguments: ∅ + │ └── operator_loc: (1,18)-(1,20) = "or" + └── @ MatchPredicateNode (location: (3,0)-(3,24)) + ├── flags: newline + ├── value: + │ @ LocalVariableWriteNode (location: (3,0)-(3,17)) + │ ├── flags: ∅ + │ ├── name: :foo + │ ├── depth: 0 + │ ├── name_loc: (3,0)-(3,3) = "foo" + │ ├── value: + │ │ @ CallNode (location: (3,6)-(3,17)) + │ │ ├── flags: ∅ + │ │ ├── receiver: + │ │ │ @ IntegerNode (location: (3,6)-(3,9)) + │ │ │ ├── flags: static_literal, decimal + │ │ │ └── value: 123 + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :| + │ │ ├── message_loc: (3,10)-(3,11) = "|" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (3,12)-(3,17)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ StringNode (location: (3,12)-(3,17)) + │ │ │ ├── flags: ∅ + │ │ │ ├── opening_loc: (3,12)-(3,13) = "'" + │ │ │ ├── content_loc: (3,13)-(3,16) = "456" + │ │ │ ├── closing_loc: (3,16)-(3,17) = "'" + │ │ │ └── unescaped: "456" + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ └── operator_loc: (3,4)-(3,5) = "=" + ├── pattern: + │ @ ConstantReadNode (location: (3,21)-(3,24)) + │ ├── flags: ∅ + │ └── name: :BAR + └── operator_loc: (3,18)-(3,20) = "in" diff --git a/src/prism.c b/src/prism.c index ebd86b01fe..a131f37912 100644 --- a/src/prism.c +++ b/src/prism.c @@ -21619,26 +21619,6 @@ pm_call_node_command_p(const pm_call_node_t *node) { ); } -/** - * Determine if a given write node has a command call as its right-hand side. We - * need this because command calls as the values of writes cannot be extended by - * infix operators. - */ -static inline bool -pm_write_node_command_p(const pm_node_t *node) { - pm_node_t *value; - switch (PM_NODE_TYPE(node)) { - case PM_CLASS_VARIABLE_WRITE_NODE: value = ((pm_class_variable_write_node_t *) node)->value; break; - case PM_CONSTANT_PATH_WRITE_NODE: value = ((pm_constant_path_write_node_t *) node)->value; break; - case PM_CONSTANT_WRITE_NODE: value = ((pm_constant_write_node_t *) node)->value; break; - case PM_GLOBAL_VARIABLE_WRITE_NODE: value = ((pm_global_variable_write_node_t *) node)->value; break; - case PM_INSTANCE_VARIABLE_WRITE_NODE: value = ((pm_instance_variable_write_node_t *) node)->value; break; - case PM_LOCAL_VARIABLE_WRITE_NODE: value = ((pm_local_variable_write_node_t *) node)->value; break; - default: return false; - } - return PM_NODE_TYPE_P(value, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) value); -} - /** * Parse an expression at the given point of the parser using the given binding * power to parse subsequent chains. If this function finds a syntax error, it @@ -21723,13 +21703,9 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc case PM_INSTANCE_VARIABLE_WRITE_NODE: case PM_LOCAL_VARIABLE_WRITE_NODE: // These expressions are statements, by virtue of the right-hand - // side of their write being an implicit array or a command call. - // This mirrors parse.y's behavior where `lhs = command_call` - // reduces to stmt (not expr), preventing and/or from following. - if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { - if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) || pm_write_node_command_p(node)) { - return node; - } + // side of their write being an implicit array. + if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { + return node; } break; case PM_CALL_NODE: diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt index e9e8e82d3a..2fdcf09738 100644 --- a/test/prism/errors/command_call_in.txt +++ b/test/prism/errors/command_call_in.txt @@ -2,6 +2,4 @@ foo 1 in a ^~ unexpected 'in', expecting end-of-input ^~ unexpected 'in', ignoring it a = foo 2 in b - ^~ unexpected 'in', expecting end-of-input - ^~ unexpected 'in', ignoring it diff --git a/test/prism/errors/write_command.txt b/test/prism/errors/write_command.txt deleted file mode 100644 index 5024f8452a..0000000000 --- a/test/prism/errors/write_command.txt +++ /dev/null @@ -1,4 +0,0 @@ -a = b c and 1 - ^~~ unexpected 'and', expecting end-of-input - ^~~ unexpected 'and', ignoring it - diff --git a/test/prism/fixtures/write_command_operator.txt b/test/prism/fixtures/write_command_operator.txt new file mode 100644 index 0000000000..d719d24f87 --- /dev/null +++ b/test/prism/fixtures/write_command_operator.txt @@ -0,0 +1,3 @@ +foo = 123 | '456' or return + +foo = 123 | '456' in BAR From f5f2219b29548c1c42565646099eabb71255fc7e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 4 Mar 2026 21:04:25 -0500 Subject: [PATCH 082/289] Add an MCP server for more efficient agents --- bin/mcp | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100755 bin/mcp diff --git a/bin/mcp b/bin/mcp new file mode 100755 index 0000000000..1833d2f70b --- /dev/null +++ b/bin/mcp @@ -0,0 +1,188 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# This script is a server that can be run on your local machine, typically given +# to an LLM to reduce token usage and standardize interactions. It listens for +# JSON-RPC requests on stdin, processes them using the defined tools, and writes +# responses to stdout. +# +# To test out the server locally, it is easiest to pipe requests directly into +# stdin and then format JSON responses with a tool like `jq` for readability. +# Here are some example requests you can make to the server: +# +# echo '{"jsonrpc":"2.0","id":"1","method":"ping"}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"2","method":"tools/list"}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"rake","arguments":{"target":"compile"}}}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"c_function","arguments":{"filepath":"src/prism.c","function_name":"pm_parser_init"}}}' | bin/mcp | jq +# echo '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"ruby_method","arguments":{"filepath":"lib/prism.rb","method_name":"load"}}}' | bin/mcp | jq +# + +def silence_output + original_stdout = $stdout.dup + original_stderr = $stderr.dup + + File.open(File::NULL, "w") do |null| + $stdout.reopen(null) + $stderr.reopen(null) + yield + end +ensure + $stdout.reopen(original_stdout) + $stderr.reopen(original_stderr) +end + +require "bundler/inline" +gemfile do + source "https://rubygems.org" + gem "mcp" + gem "open3" + gem "prism", path: File.expand_path("..", __dir__) + + silence_output do + gem "ffi-clang" + require "ffi/clang" + end +end + +class RakeTool < MCP::Tool + tool_name "rake" + description "Run rake on a specific target." + + input_schema( + properties: { + target: { type: "string", enum: ["clean", "compile", "test"], description: "The rake target to build." } + }, + required: ["target"] + ) + output_schema( + properties: { + success: { type: "boolean" }, + stderr: { type: "string" } + }, + required: ["success"] + ) + + def self.call(server_context:, target:) + _, stderr, status = + Dir.chdir(File.expand_path("..", __dir__)) do + Open3.capture3("bundle", "exec", "rake", target) + end + + result = + if status.success? + { success: true } + else + { success: false, stderr: stderr.strip } + end + + output_schema.validate_result(result) + MCP::Tool::Response.new([{ type: "text", text: result.to_json }], structured_content: result) + end +end + +class CFunctionTool < MCP::Tool + tool_name "c_function" + description "Extracts a C function from a source file." + + input_schema( + properties: { + filepath: { type: "string", description: "Path to the C source file." }, + function_name: { type: "string", description: "The name of the function to extract." } + }, + required: ["filepath", "function_name"] + ) + output_schema( + properties: { + body: { type: "string" } + }, + required: ["body"] + ) + + class << self + def call(server_context:, filepath:, function_name:) + if !File.readable?(filepath) + MCP::Tool::Response.new([MCP::Content::Text.new("Invalid filepath").to_h], error: true) + elsif !(body = find(filepath, function_name)) + MCP::Tool::Response.new([MCP::Content::Text.new("Function not found").to_h], error: true) + else + result = { body: body } + output_schema.validate_result(result) + + MCP::Tool::Response.new([{ type: "text", text: result.to_json }], structured_content: result) + end + end + + private + + def extract(cursor) + location = cursor.definition.location + return unless (filepath = location.file) + + extent = cursor.extent + start_offset = extent.start.offset + File.open(filepath, "rb") do |file| + file.pread(extent.end.offset - start_offset, start_offset) + end + end + + def find(filepath, function_name) + translation_unit = FFI::Clang::Index.new.parse_translation_unit(filepath) + translation_unit.cursor.find { |cursor, _| break extract(cursor) if cursor.declaration? && cursor.spelling == function_name } + end + end +end + +class RubyMethodTool < MCP::Tool + tool_name "ruby_method" + description "Extracts a Ruby method from a source file." + + input_schema( + properties: { + filepath: { type: "string", description: "Path to the Ruby source file." }, + method_name: { type: "string", description: "The name of the method to extract." } + }, + required: ["filepath", "method_name"] + ) + output_schema( + properties: { + body: { type: "string" } + }, + required: ["body"] + ) + + class << self + def call(server_context:, filepath:, method_name:) + if !File.readable?(filepath) + MCP::Tool::Response.new([MCP::Content::Text.new("Invalid filepath").to_h], error: true) + elsif !(result = Prism.parse_file(filepath)).success? + MCP::Tool::Response.new([MCP::Content::Text.new("Failed to parse file").to_h], error: true) + elsif !(body = find(result.value, method_name)) + MCP::Tool::Response.new([MCP::Content::Text.new("Method not found").to_h], error: true) + else + result = { body: body } + output_schema.validate_result(result) + + MCP::Tool::Response.new([{ type: "text", text: result.to_json }], structured_content: result) + end + end + + private + + def find(node, method_name) + name = method_name.to_sym + node.breadth_first_search do |child| + break child.slice if child.is_a?(Prism::DefNode) && child.name == name + end + end + end +end + +tools = [ + RakeTool, + CFunctionTool, + RubyMethodTool +] + +server = MCP::Server.new(name: "Prism", tools: tools) +transport = MCP::Server::Transports::StdioTransport.new(server) +transport.open From 88cfd264a41e45421e1ca9b344d6f634ea94dadb Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 5 Mar 2026 09:22:35 -0500 Subject: [PATCH 083/289] Arena allocations Move the whole AST into a bump allocator since it has the same lifetime. --- cpp/test.cpp | 5 +- ext/prism/extension.c | 41 +- fuzz/regexp.c | 4 +- include/prism.h | 24 +- include/prism/defines.h | 12 + include/prism/node.h | 29 +- include/prism/parser.h | 4 + include/prism/util/pm_arena.h | 89 ++++ include/prism/util/pm_constant_pool.h | 18 +- prism.gemspec | 2 + rust/ruby-prism-sys/build/main.rs | 2 +- rust/ruby-prism-sys/src/lib.rs | 1 + rust/ruby-prism-sys/tests/node_tests.rs | 6 +- rust/ruby-prism-sys/tests/parser_tests.rs | 20 +- rust/ruby-prism/src/lib.rs | 7 +- rust/ruby-prism/src/parse_result/mod.rs | 9 +- src/prism.c | 560 ++++++++++------------ src/util/pm_arena.c | 105 ++++ src/util/pm_constant_pool.c | 41 +- templates/src/node.c.erb | 139 ++---- templates/src/serialize.c.erb | 12 +- 21 files changed, 594 insertions(+), 536 deletions(-) create mode 100644 include/prism/util/pm_arena.h create mode 100644 src/util/pm_arena.c diff --git a/cpp/test.cpp b/cpp/test.cpp index af993c9fca..3e41b270e9 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -5,8 +5,9 @@ extern "C" { #include int main() { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, reinterpret_cast("1 + 2"), 5, NULL); + pm_parser_init(&arena, &parser, reinterpret_cast("1 + 2"), 5, NULL); pm_node_t *root = pm_parse(&parser); pm_buffer_t buffer = { 0 }; @@ -17,8 +18,8 @@ int main() { std::cout << buffer.value << std::endl; pm_buffer_free(&buffer); - pm_node_destroy(&parser, root); pm_parser_free(&parser); + pm_arena_free(&arena); return 0; } diff --git a/ext/prism/extension.c b/ext/prism/extension.c index fcbc1e6c24..7c90e48845 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -374,16 +374,17 @@ dump_input(pm_string_t *input, const pm_options_t *options) { rb_raise(rb_eNoMemError, "failed to allocate memory"); } + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(&parser); pm_serialize(&parser, node, &buffer); VALUE result = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer)); - pm_node_destroy(&parser, node); pm_buffer_free(&buffer); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } @@ -736,8 +737,9 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) { */ static VALUE parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nodes) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback); VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input)); @@ -789,8 +791,8 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, options->freeze); } - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } @@ -848,8 +850,9 @@ lex_file(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(&parser); rb_encoding *encoding = rb_enc_find(parser.encoding->name); @@ -862,8 +865,8 @@ parse_input(pm_string_t *input, const pm_options_t *options) { rb_obj_freeze(source); } - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } @@ -965,12 +968,13 @@ parse_file(int argc, VALUE *argv, VALUE self) { */ static void profile_input(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); - pm_node_destroy(&parser, node); + pm_parse(&parser); pm_parser_free(&parser); + pm_arena_free(&arena); } /** @@ -1065,19 +1069,20 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_options_t options = { 0 }; extract_options(&options, Qnil, keywords); + pm_arena_t arena = { 0 }; pm_parser_t parser; pm_buffer_t buffer; - pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); + pm_node_t *node = pm_parse_stream(&arena, &parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); rb_encoding *encoding = rb_enc_find(parser.encoding->name); VALUE source = pm_source_new(&parser, encoding, options.freeze); VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze); VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze); - pm_node_destroy(&parser, node); pm_buffer_free(&buffer); pm_parser_free(&parser); + pm_arena_free(&arena); return result; } @@ -1087,17 +1092,18 @@ parse_stream(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input_comments(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); + pm_parse(&parser); rb_encoding *encoding = rb_enc_find(parser.encoding->name); VALUE source = pm_source_new(&parser, encoding, options->freeze); VALUE comments = parser_comments(&parser, source, options->freeze); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); return comments; } @@ -1209,14 +1215,15 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input_success_p(pm_string_t *input, const pm_options_t *options) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); - pm_node_destroy(&parser, node); + pm_parse(&parser); VALUE result = parser.error_list.size == 0 ? Qtrue : Qfalse; pm_parser_free(&parser); + pm_arena_free(&arena); return result; } diff --git a/fuzz/regexp.c b/fuzz/regexp.c index 3837d74d57..f1a02dedc2 100644 --- a/fuzz/regexp.c +++ b/fuzz/regexp.c @@ -12,10 +12,12 @@ regexp_error_callback(const uint8_t *start, const uint8_t *end, const char *mess void harness(const uint8_t *input, size_t size) { + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, input, size, NULL); + pm_parser_init(&arena, &parser, input, size, NULL); pm_regexp_parse(&parser, input, size, false, regexp_name_callback, NULL, regexp_error_callback, NULL); pm_parser_free(&parser); + pm_arena_free(&arena); } diff --git a/include/prism.h b/include/prism.h index a71ccfef36..76733b8aaf 100644 --- a/include/prism.h +++ b/include/prism.h @@ -11,6 +11,7 @@ extern "C" { #endif #include "prism/defines.h" +#include "prism/util/pm_arena.h" #include "prism/util/pm_buffer.h" #include "prism/util/pm_char.h" #include "prism/util/pm_integer.h" @@ -52,8 +53,11 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void); /** * Initialize a parser with the given start and end pointers. * - * The resulting parser must eventually be freed with `pm_parser_free()`. + * The resulting parser must eventually be freed with `pm_parser_free()`. The + * arena is caller-owned and must outlive the parser — `pm_parser_free()` does + * not free the arena. * + * @param arena The arena to use for all AST-lifetime allocations. * @param parser The parser to initialize. * @param source The source to parse. * @param size The size of the source. @@ -62,7 +66,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void); * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); +PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); /** * Register a callback that will be called whenever prism changes the encoding @@ -114,6 +118,7 @@ typedef int (pm_parse_stream_feof_t)(void *stream); /** * Parse a stream of Ruby source and return the tree. * + * @param arena The arena to use for all AST-lifetime allocations. * @param parser The parser to use. * @param buffer The buffer to use. * @param stream The stream to parse. @@ -124,7 +129,7 @@ typedef int (pm_parse_stream_feof_t)(void *stream); * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); // We optionally support serializing to a binary string. For systems that don't // want or need this functionality, it can be turned off with the @@ -333,24 +338,26 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * In order to parse Ruby code, the structures and functions that you're going * to want to use and be aware of are: * + * * `pm_arena_t` - the arena allocator for AST-lifetime memory * * `pm_parser_t` - the main parser structure * * `pm_parser_init()` - initialize a parser * * `pm_parse()` - parse and return the root node - * * `pm_node_destroy()` - deallocate the root node returned by `pm_parse()` * * `pm_parser_free()` - free the internal memory of the parser + * * `pm_arena_free()` - free all AST-lifetime memory * * Putting all of this together would look something like: * * ```c * void parse(const uint8_t *source, size_t length) { + * pm_arena_t arena = { 0 }; * pm_parser_t parser; - * pm_parser_init(&parser, source, length, NULL); + * pm_parser_init(&arena, &parser, source, length, NULL); * * pm_node_t *root = pm_parse(&parser); * printf("PARSED!\n"); * - * pm_node_destroy(&parser, root); * pm_parser_free(&parser); + * pm_arena_free(&arena); * } * ``` * @@ -391,8 +398,9 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * * ```c * void prettyprint(const uint8_t *source, size_t length) { + * pm_arena_t arena = { 0 }; * pm_parser_t parser; - * pm_parser_init(&parser, source, length, NULL); + * pm_parser_init(&arena, &parser, source, length, NULL); * * pm_node_t *root = pm_parse(&parser); * pm_buffer_t buffer = { 0 }; @@ -401,8 +409,8 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * printf("%*.s\n", (int) buffer.length, buffer.value); * * pm_buffer_free(&buffer); - * pm_node_destroy(&parser, root); * pm_parser_free(&parser); + * pm_arena_free(&arena); * } * ``` */ diff --git a/include/prism/defines.h b/include/prism/defines.h index 1c4e5fa053..c48a600b21 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -278,6 +278,18 @@ #define PRISM_FALLTHROUGH #endif +/** + * A macro for defining a flexible array member. C99 supports `data[]`, GCC + * supports `data[0]` as an extension, and older compilers require `data[1]`. + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + #define PM_FLEX_ARY_LEN /* data[] */ +#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) + #define PM_FLEX_ARY_LEN 0 /* data[0] */ +#else + #define PM_FLEX_ARY_LEN 1 /* data[1] */ +#endif + /** * We need to align nodes in the AST to a pointer boundary so that it can be * safely cast to different node types. Use PRISM_ALIGNAS/PRISM_ALIGNOF to diff --git a/include/prism/node.h b/include/prism/node.h index e8686a327c..253f890055 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -20,41 +20,29 @@ /** * Append a new node onto the end of the node list. * + * @param arena The arena to allocate from. * @param list The list to append to. * @param node The node to append. */ -void pm_node_list_append(pm_node_list_t *list, pm_node_t *node); +void pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); /** * Prepend a new node onto the beginning of the node list. * + * @param arena The arena to allocate from. * @param list The list to prepend to. * @param node The node to prepend. */ -void pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node); +void pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); /** * Concatenate the given node list onto the end of the other node list. * + * @param arena The arena to allocate from. * @param list The list to concatenate onto. * @param other The list to concatenate. */ -void pm_node_list_concat(pm_node_list_t *list, pm_node_list_t *other); - -/** - * Free the internal memory associated with the given node list. - * - * @param list The list to free. - */ -void pm_node_list_free(pm_node_list_t *list); - -/** - * Deallocate a node and all of its children. - * - * @param parser The parser that owns the node. - * @param node The node to deallocate. - */ -PRISM_EXPORTED_FUNCTION void pm_node_destroy(pm_parser_t *parser, struct pm_node *node); +void pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other); /** * Returns a string representation of the given node type. @@ -93,9 +81,10 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * const char *source = "1 + 2; 3 + 4"; * size_t size = strlen(source); * + * pm_arena_t arena = { 0 }; * pm_parser_t parser; * pm_options_t options = { 0 }; - * pm_parser_init(&parser, (const uint8_t *) source, size, &options); + * pm_parser_init(&arena, &parser, (const uint8_t *) source, size, &options); * * size_t indent = 0; * pm_node_t *node = pm_parse(&parser); @@ -103,8 +92,8 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * size_t *data = &indent; * pm_visit_node(node, visit, data); * - * pm_node_destroy(&parser, node); * pm_parser_free(&parser); + * pm_arena_free(&arena); * return EXIT_SUCCESS; * } * ``` diff --git a/include/prism/parser.h b/include/prism/parser.h index b4e3038439..c76fba58cf 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -11,6 +11,7 @@ #include "prism/encoding.h" #include "prism/options.h" #include "prism/static_literals.h" +#include "prism/util/pm_arena.h" #include "prism/util/pm_constant_pool.h" #include "prism/util/pm_list.h" #include "prism/util/pm_line_offset_list.h" @@ -635,6 +636,9 @@ typedef uint32_t pm_state_stack_t; * it's considering. */ struct pm_parser { + /** The arena used for all AST-lifetime allocations. Caller-owned. */ + pm_arena_t *arena; + /** * The next node identifier that will be assigned. This is a unique * identifier used to track nodes such that the syntax tree can be dropped diff --git a/include/prism/util/pm_arena.h b/include/prism/util/pm_arena.h new file mode 100644 index 0000000000..f376d13459 --- /dev/null +++ b/include/prism/util/pm_arena.h @@ -0,0 +1,89 @@ +/** + * @file pm_arena.h + * + * A bump allocator for the prism parser. + */ +#ifndef PRISM_ARENA_H +#define PRISM_ARENA_H + +#include "prism/defines.h" + +#include +#include +#include +#include + +/** + * A single block of memory in the arena. Blocks are linked via prev pointers so + * they can be freed by walking the chain. + */ +typedef struct pm_arena_block { + /** The previous block in the chain (for freeing). */ + struct pm_arena_block *prev; + + /** The total usable bytes in data[]. */ + size_t capacity; + + /** The number of bytes consumed so far. */ + size_t used; + + /** The block's data. */ + char data[PM_FLEX_ARY_LEN]; +} pm_arena_block_t; + +/** + * A bump allocator. Allocations are made by bumping a pointer within the + * current block. When a block is full, a new block is allocated and linked to + * the previous one. All blocks are freed at once by walking the chain. + */ +typedef struct { + /** The active block (allocate from here). */ + pm_arena_block_t *current; + + /** The number of blocks allocated. */ + size_t block_count; +} pm_arena_t; + +/** + * Allocate memory from the arena. The returned memory is NOT zeroed. This + * function is infallible — it aborts on allocation failure. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated memory. + */ +void * pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment); + +/** + * Allocate zero-initialized memory from the arena. This function is infallible + * — it aborts on allocation failure. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated, zero-initialized memory. + */ +void * pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment); + +/** + * Allocate memory from the arena and copy the given data into it. This is a + * convenience wrapper around pm_arena_alloc + memcpy. + * + * @param arena The arena to allocate from. + * @param src The source data to copy. + * @param size The number of bytes to allocate and copy. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated copy. + */ +void * pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment); + +/** + * Free all blocks in the arena. After this call, all pointers returned by + * pm_arena_alloc and pm_arena_zalloc are invalid. + * + * @param arena The arena to free. + */ +PRISM_EXPORTED_FUNCTION void pm_arena_free(pm_arena_t *arena); + +#endif diff --git a/include/prism/util/pm_constant_pool.h b/include/prism/util/pm_constant_pool.h index 6df23f8f50..1d4922a661 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/util/pm_constant_pool.h @@ -11,6 +11,7 @@ #define PRISM_CONSTANT_POOL_H #include "prism/defines.h" +#include "prism/util/pm_arena.h" #include #include @@ -54,20 +55,20 @@ void pm_constant_id_list_init(pm_constant_id_list_t *list); /** * Initialize a list of constant ids with a given capacity. * + * @param arena The arena to allocate from. * @param list The list to initialize. * @param capacity The initial capacity of the list. */ -void pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity); +void pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity); /** - * Append a constant id to a list of constant ids. Returns false if any - * potential reallocations fail. + * Append a constant id to a list of constant ids. * + * @param arena The arena to allocate from. * @param list The list to append to. * @param id The id to append. - * @return Whether the append succeeded. */ -bool pm_constant_id_list_append(pm_constant_id_list_t *list, pm_constant_id_t id); +void pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id); /** * Insert a constant id into a list of constant ids at the specified index. @@ -87,13 +88,6 @@ void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_co */ bool pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id); -/** - * Free the memory associated with a list of constant ids. - * - * @param list The list to free. - */ -void pm_constant_id_list_free(pm_constant_id_list_t *list); - /** * The type of bucket in the constant pool hash map. This determines how the * bucket should be freed. diff --git a/prism.gemspec b/prism.gemspec index ca2db717ba..74d5412731 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -58,6 +58,7 @@ Gem::Specification.new do |spec| "include/prism/prettyprint.h", "include/prism/regexp.h", "include/prism/static_literals.h", + "include/prism/util/pm_arena.h", "include/prism/util/pm_buffer.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", @@ -167,6 +168,7 @@ Gem::Specification.new do |spec| "src/serialize.c", "src/static_literals.c", "src/token_type.c", + "src/util/pm_arena.c", "src/util/pm_buffer.c", "src/util/pm_char.c", "src/util/pm_constant_pool.c", diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index b403747ed8..30da93ae6c 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -129,9 +129,9 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .rustified_non_exhaustive_enum(r"pm_\w+_flags") .rustified_non_exhaustive_enum("pm_node_type") // Functions + .allowlist_function("pm_arena_free") .allowlist_function("pm_list_empty_p") .allowlist_function("pm_list_free") - .allowlist_function("pm_node_destroy") .allowlist_function("pm_parse") .allowlist_function("pm_parser_free") .allowlist_function("pm_parser_init") diff --git a/rust/ruby-prism-sys/src/lib.rs b/rust/ruby-prism-sys/src/lib.rs index 8d4c979f5d..7d200124fa 100644 --- a/rust/ruby-prism-sys/src/lib.rs +++ b/rust/ruby-prism-sys/src/lib.rs @@ -27,6 +27,7 @@ #[allow(unused_qualifications)] #[allow(clippy::missing_const_for_fn)] #[allow(clippy::use_self)] +#[allow(trivial_casts)] mod bindings { // In `build.rs`, we use `bindgen` to generate bindings based on C headers // and `libprism`. Here is where we pull in those bindings and make diff --git a/rust/ruby-prism-sys/tests/node_tests.rs b/rust/ruby-prism-sys/tests/node_tests.rs index 87b6c2a337..7c7c13629c 100644 --- a/rust/ruby-prism-sys/tests/node_tests.rs +++ b/rust/ruby-prism-sys/tests/node_tests.rs @@ -1,15 +1,17 @@ use std::{ffi::CString, mem::MaybeUninit}; -use ruby_prism_sys::{pm_node_destroy, pm_node_type}; +use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_node_type}; use ruby_prism_sys::{pm_parse, pm_parser_free, pm_parser_init, pm_parser_t}; #[test] fn node_test() { + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); let code = CString::new("class Foo; end").unwrap(); unsafe { pm_parser_init( + arena.as_mut_ptr(), parser.as_mut_ptr(), code.as_ptr().cast::(), code.as_bytes().len(), @@ -21,7 +23,7 @@ fn node_test() { assert_eq!((*parsed_node).type_, pm_node_type::PM_PROGRAM_NODE as u16); - pm_node_destroy(parser, parsed_node); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism-sys/tests/parser_tests.rs b/rust/ruby-prism-sys/tests/parser_tests.rs index 6ce3a3b980..d6f827d144 100644 --- a/rust/ruby-prism-sys/tests/parser_tests.rs +++ b/rust/ruby-prism-sys/tests/parser_tests.rs @@ -5,8 +5,8 @@ use std::{ }; use ruby_prism_sys::{ - pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_node_destroy, pm_parse, pm_parser_free, pm_parser_init, - pm_parser_t, + pm_arena_free, pm_arena_t, pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_parse, pm_parser_free, + pm_parser_init, pm_parser_t, }; fn ruby_file_contents() -> (CString, usize) { @@ -22,30 +22,34 @@ fn ruby_file_contents() -> (CString, usize) { fn init_test() { let (ruby_file_contents, len) = ruby_file_contents(); let source = ruby_file_contents.as_ptr().cast::(); + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); unsafe { - pm_parser_init(parser.as_mut_ptr(), source, len, std::ptr::null()); + pm_parser_init(arena.as_mut_ptr(), parser.as_mut_ptr(), source, len, std::ptr::null()); let parser = parser.assume_init_mut(); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } #[test] fn comments_test() { let source = CString::new("# Meow!").unwrap(); + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); unsafe { pm_parser_init( + arena.as_mut_ptr(), parser.as_mut_ptr(), source.as_ptr().cast::(), source.as_bytes().len(), std::ptr::null(), ); let parser = parser.assume_init_mut(); - let node = pm_parse(parser); + let _node = pm_parse(parser); let comment_list = &parser.comment_list; let comment = comment_list.head as *const pm_comment_t; @@ -58,25 +62,27 @@ fn comments_test() { }; assert_eq!(location, 0..7); - pm_node_destroy(parser, node); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } #[test] fn diagnostics_test() { let source = CString::new("class Foo;").unwrap(); + let mut arena = MaybeUninit::::zeroed(); let mut parser = MaybeUninit::::uninit(); unsafe { pm_parser_init( + arena.as_mut_ptr(), parser.as_mut_ptr(), source.as_ptr().cast::(), source.as_bytes().len(), std::ptr::null(), ); let parser = parser.assume_init_mut(); - let node = pm_parse(parser); + let _node = pm_parse(parser); let error_list = &parser.error_list; assert!(!error_list.head.is_null()); @@ -95,7 +101,7 @@ fn diagnostics_test() { }; assert_eq!(location, 10..10); - pm_node_destroy(parser, node); pm_parser_free(parser); + pm_arena_free(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index f628056b3e..37a14c80ec 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -23,7 +23,7 @@ pub use self::bindings::*; pub use self::node::{ConstantId, ConstantList, ConstantListIter, Integer, NodeList, NodeListIter}; pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnostics, Location, MagicComment, MagicComments, ParseResult}; -use ruby_prism_sys::{pm_parse, pm_parser_init, pm_parser_t}; +use ruby_prism_sys::{pm_arena_t, pm_parse, pm_parser_init, pm_parser_t}; /// Parses the given source string and returns a parse result. /// @@ -34,10 +34,11 @@ use ruby_prism_sys::{pm_parse, pm_parser_init, pm_parser_t}; #[must_use] pub fn parse(source: &[u8]) -> ParseResult<'_> { unsafe { + let mut arena = Box::new(MaybeUninit::::zeroed().assume_init()); let uninit = Box::new(MaybeUninit::::uninit()); let uninit = Box::into_raw(uninit); - pm_parser_init((*uninit).as_mut_ptr(), source.as_ptr(), source.len(), std::ptr::null()); + pm_parser_init(arena.as_mut(), (*uninit).as_mut_ptr(), source.as_ptr(), source.len(), std::ptr::null()); let parser = (*uninit).assume_init_mut(); let parser = NonNull::new_unchecked(parser); @@ -45,7 +46,7 @@ pub fn parse(source: &[u8]) -> ParseResult<'_> { let node = pm_parse(parser.as_ptr()); let node = NonNull::new_unchecked(node); - ParseResult::new(source, parser, node) + ParseResult::new(source, arena, parser, node) } } diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index 99fad68241..d186ced7ec 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -8,7 +8,7 @@ mod diagnostics; use std::ptr::NonNull; -use ruby_prism_sys::{pm_comment_t, pm_diagnostic_t, pm_location_t, pm_magic_comment_t, pm_node_destroy, pm_node_t, pm_parser_free, pm_parser_t}; +use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_free, pm_parser_t}; pub use self::comments::{Comment, CommentType, Comments, MagicComment, MagicComments}; pub use self::diagnostics::{Diagnostic, Diagnostics}; @@ -89,13 +89,14 @@ impl std::fmt::Debug for Location<'_> { #[derive(Debug)] pub struct ParseResult<'pr> { source: &'pr [u8], + arena: Box, parser: NonNull, node: NonNull, } impl<'pr> ParseResult<'pr> { - pub(crate) const unsafe fn new(source: &'pr [u8], parser: NonNull, node: NonNull) -> Self { - ParseResult { source, parser, node } + pub(crate) const unsafe fn new(source: &'pr [u8], arena: Box, parser: NonNull, node: NonNull) -> Self { + ParseResult { source, arena, parser, node } } /// Returns the source string that was parsed. @@ -203,9 +204,9 @@ impl<'pr> ParseResult<'pr> { impl Drop for ParseResult<'_> { fn drop(&mut self) { unsafe { - pm_node_destroy(self.parser.as_ptr(), self.node.as_ptr()); pm_parser_free(self.parser.as_ptr()); drop(Box::from_raw(self.parser.as_ptr())); + pm_arena_free(self.arena.as_mut()); } } } diff --git a/src/prism.c b/src/prism.c index a131f37912..e10a7710af 100644 --- a/src/prism.c +++ b/src/prism.c @@ -983,7 +983,7 @@ pm_locals_reads(pm_locals_t *locals, pm_constant_id_t name) { */ static void pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, pm_constant_id_list_t *list, bool toplevel) { - pm_constant_id_list_init_capacity(list, locals->size); + pm_constant_id_list_init_capacity(parser->arena, list, locals->size); // If we're still below the threshold for switching to a hash, then we only // need to loop over the locals until we hit the size because the locals are @@ -2005,20 +2005,20 @@ static size_t pm_statements_node_body_length(pm_statements_node_t *node); /** - * This function is here to allow us a place to extend in the future when we - * implement our own arena allocation. + * Move an integer's values array into the arena. If the integer has heap- + * allocated values, copy them to the arena and free the original. */ -static inline void * -pm_node_alloc(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) { - void *memory = xcalloc(1, size); - if (memory == NULL) { - fprintf(stderr, "Failed to allocate %d bytes\n", (int) size); - abort(); +static inline void +pm_integer_arena_move(pm_arena_t *arena, pm_integer_t *integer) { + if (integer->values != NULL) { + size_t byte_size = integer->length * sizeof(uint32_t); + uint32_t *old_values = integer->values; + integer->values = (uint32_t *) pm_arena_memdup(arena, old_values, byte_size, PRISM_ALIGNOF(uint32_t)); + xfree(old_values); } - return memory; } -#define PM_NODE_ALLOC(parser_, type_) (type_ *) pm_node_alloc(parser_, sizeof(type_)) +#define PM_NODE_ALLOC(parser_, type_) (type_ *) pm_arena_zalloc((parser_)->arena, sizeof(type_), PRISM_ALIGNOF(type_)) #define PM_NODE_INIT(parser_, type_, flags_, location_) (pm_node_t) { \ .type = (type_), \ .flags = (flags_), \ @@ -2139,7 +2139,7 @@ pm_arguments_node_size(pm_arguments_node_t *node) { * Append an argument to an arguments node. */ static void -pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argument) { +pm_arguments_node_arguments_append(pm_arena_t *arena, pm_arguments_node_t *node, pm_node_t *argument) { if (pm_arguments_node_size(node) == 0) { PM_NODE_START_SET_NODE(node, argument); } @@ -2148,7 +2148,7 @@ pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argumen PM_NODE_LENGTH_SET_NODE(node, argument); } - pm_node_list_append(&node->arguments, argument); + pm_node_list_append(arena, &node->arguments, argument); if (PM_NODE_TYPE_P(argument, PM_SPLAT_NODE)) { if (PM_NODE_FLAG_P(node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) { @@ -2189,12 +2189,12 @@ pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) { * Append an argument to an array node. */ static inline void -pm_array_node_elements_append(pm_array_node_t *node, pm_node_t *element) { +pm_array_node_elements_append(pm_arena_t *arena, pm_array_node_t *node, pm_node_t *element) { if (!node->elements.size && !node->opening_loc.length) { PM_NODE_START_SET_NODE(node, element); } - pm_node_list_append(&node->elements, element); + pm_node_list_append(arena, &node->elements, element); PM_NODE_LENGTH_SET_NODE(node, element); // If the element is not a static literal, then the array is not a static @@ -2246,9 +2246,9 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node node->rest = child; found_rest = true; } else if (found_rest) { - pm_node_list_append(&node->posts, child); + pm_node_list_append(parser->arena, &node->posts, child); } else { - pm_node_list_append(&node->requireds, child); + pm_node_list_append(parser->arena, &node->requireds, child); } } @@ -2318,8 +2318,8 @@ pm_array_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *openin } static inline void -pm_array_pattern_node_requireds_append(pm_array_pattern_node_t *node, pm_node_t *inner) { - pm_node_list_append(&node->requireds, inner); +pm_array_pattern_node_requireds_append(pm_arena_t *arena, pm_array_pattern_node_t *node, pm_node_t *inner) { + pm_node_list_append(arena, &node->requireds, inner); } /** @@ -2583,8 +2583,8 @@ pm_block_local_variable_node_create(pm_parser_t *parser, const pm_token_t *name) * Append a new block-local variable to a BlockParametersNode node. */ static void -pm_block_parameters_node_append_local(pm_block_parameters_node_t *node, const pm_block_local_variable_node_t *local) { - pm_node_list_append(&node->locals, UP(local)); +pm_block_parameters_node_append_local(pm_arena_t *arena, pm_block_parameters_node_t *node, const pm_block_local_variable_node_t *local) { + pm_node_list_append(arena, &node->locals, UP(local)); if (PM_NODE_LENGTH(node) == 0) { PM_NODE_START_SET_NODE(node, local); @@ -2704,7 +2704,7 @@ pm_call_node_binary_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t node->message_loc = TOK2LOC(parser, operator); pm_arguments_node_t *arguments = pm_arguments_node_create(parser); - pm_arguments_node_arguments_append(arguments, argument); + pm_arguments_node_arguments_append(parser->arena, arguments, argument); node->arguments = arguments; node->name = pm_parser_constant_id_token(parser, operator); @@ -2953,10 +2953,8 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3007,10 +3005,8 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons .value = value }; - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3037,10 +3033,8 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3068,10 +3062,8 @@ pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, .value = value }; - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3098,10 +3090,8 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3129,10 +3119,8 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const .value = value }; - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3161,10 +3149,8 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { node->call_operator_loc = target->base.location; } - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3189,10 +3175,8 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { .block = (pm_block_argument_node_t *) target->block, }; - // Here we're going to free the target, since it is no longer necessary. - // However, we don't want to call `pm_node_destroy` because we want to keep - // around all of its children since we just reused them. - xfree_sized(target, sizeof(pm_call_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -3237,10 +3221,10 @@ pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node * Append a new condition to a CaseNode node. */ static void -pm_case_node_condition_append(pm_case_node_t *node, pm_node_t *condition) { +pm_case_node_condition_append(pm_arena_t *arena, pm_case_node_t *node, pm_node_t *condition) { assert(PM_NODE_TYPE_P(condition, PM_WHEN_NODE)); - pm_node_list_append(&node->conditions, condition); + pm_node_list_append(arena, &node->conditions, condition); PM_NODE_LENGTH_SET_NODE(node, condition); } @@ -3285,10 +3269,10 @@ pm_case_match_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, p * Append a new condition to a CaseMatchNode node. */ static void -pm_case_match_node_condition_append(pm_case_match_node_t *node, pm_node_t *condition) { +pm_case_match_node_condition_append(pm_arena_t *arena, pm_case_match_node_t *node, pm_node_t *condition) { assert(PM_NODE_TYPE_P(condition, PM_IN_NODE)); - pm_node_list_append(&node->conditions, condition); + pm_node_list_append(arena, &node->conditions, condition); PM_NODE_LENGTH_SET_NODE(node, condition); } @@ -3856,7 +3840,7 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { // much more efficient, as we could instead resize the node list to only point // to 1...-1. for (size_t index = 1; index < nodes->size - 1; index++) { - pm_node_list_append(&node->requireds, nodes->nodes[index]); + pm_node_list_append(parser->arena, &node->requireds, nodes->nodes[index]); } return node; @@ -4021,6 +4005,8 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) { xfree_sized(digits, length); pm_integers_reduce(&node->numerator, &node->denominator); + pm_integer_arena_move(parser->arena, &node->numerator); + pm_integer_arena_move(parser->arena, &node->denominator); return node; } @@ -4180,7 +4166,7 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme .closing_loc = { 0 } }; - pm_node_list_concat(&node->elements, elements); + pm_node_list_concat(parser->arena, &node->elements, elements); return node; } @@ -4350,8 +4336,8 @@ pm_hash_node_create(pm_parser_t *parser, const pm_token_t *opening) { * Append a new element to a hash node. */ static inline void -pm_hash_node_elements_append(pm_hash_node_t *hash, pm_node_t *element) { - pm_node_list_append(&hash->elements, element); +pm_hash_node_elements_append(pm_arena_t *arena, pm_hash_node_t *hash, pm_node_t *element) { + pm_node_list_append(arena, &hash->elements, element); bool static_literal = PM_NODE_TYPE_P(element, PM_ASSOC_NODE); if (static_literal) { @@ -4534,6 +4520,7 @@ pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token } pm_integer_parse(&node->value, integer_base, token->start, token->end); + pm_integer_arena_move(parser->arena, &node->value); return node; } @@ -4583,6 +4570,7 @@ pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const } pm_integer_parse(&node->numerator, integer_base, token->start, token->end - 1); + pm_integer_arena_move(parser->arena, &node->numerator); return node; } @@ -4736,7 +4724,7 @@ pm_instance_variable_write_node_create(pm_parser_t *parser, pm_instance_variable * literals. */ static void -pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *part) { +pm_interpolated_node_append(pm_arena_t *arena, pm_node_t *node, pm_node_list_t *parts, pm_node_t *part) { switch (PM_NODE_TYPE(part)) { case PM_STRING_NODE: pm_node_flag_set(part, PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN); @@ -4771,7 +4759,7 @@ pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *p break; } - pm_node_list_append(parts, part); + pm_node_list_append(arena, parts, part); } /** @@ -4792,7 +4780,7 @@ pm_interpolated_regular_expression_node_create(pm_parser_t *parser, const pm_tok } static inline void -pm_interpolated_regular_expression_node_append(pm_interpolated_regular_expression_node_t *node, pm_node_t *part) { +pm_interpolated_regular_expression_node_append(pm_arena_t *arena, pm_interpolated_regular_expression_node_t *node, pm_node_t *part) { if (PM_NODE_START(node) > PM_NODE_START(part)) { PM_NODE_START_SET_NODE(node, part); } @@ -4800,7 +4788,7 @@ pm_interpolated_regular_expression_node_append(pm_interpolated_regular_expressio PM_NODE_LENGTH_SET_NODE(node, part); } - pm_interpolated_node_append(UP(node), &node->parts, part); + pm_interpolated_node_append(arena, UP(node), &node->parts, part); } static inline void @@ -4834,7 +4822,7 @@ pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_inte * which could potentially use a chilled string otherwise. */ static inline void -pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_t *part) { +pm_interpolated_string_node_append(pm_arena_t *arena, pm_interpolated_string_node_t *node, pm_node_t *part) { #define CLEAR_FLAGS(node) \ node->base.flags = (pm_node_flags_t) (FL(node) & ~(PM_NODE_FLAG_STATIC_LITERAL | PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE)) @@ -4919,7 +4907,7 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_ break; } - pm_node_list_append(&node->parts, part); + pm_node_list_append(arena, &node->parts, part); #undef CLEAR_FLAGS #undef MUTABLE_FLAGS @@ -4955,7 +4943,7 @@ pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *openin if (parts != NULL) { pm_node_t *part; PM_NODE_LIST_FOREACH(parts, index, part) { - pm_interpolated_string_node_append(node, part); + pm_interpolated_string_node_append(parser->arena, node, part); } } @@ -4972,12 +4960,12 @@ pm_interpolated_string_node_closing_set(const pm_parser_t *parser, pm_interpolat } static void -pm_interpolated_symbol_node_append(pm_interpolated_symbol_node_t *node, pm_node_t *part) { +pm_interpolated_symbol_node_append(pm_arena_t *arena, pm_interpolated_symbol_node_t *node, pm_node_t *part) { if (node->parts.size == 0 && node->opening_loc.length == 0) { PM_NODE_START_SET_NODE(node, part); } - pm_interpolated_node_append(UP(node), &node->parts, part); + pm_interpolated_node_append(arena, UP(node), &node->parts, part); if (PM_NODE_END(part) > PM_NODE_END(node)) { PM_NODE_LENGTH_SET_NODE(node, part); @@ -5010,7 +4998,7 @@ pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *openin if (parts != NULL) { pm_node_t *part; PM_NODE_LIST_FOREACH(parts, index, part) { - pm_interpolated_symbol_node_append(node, part); + pm_interpolated_symbol_node_append(parser->arena, node, part); } } @@ -5035,8 +5023,8 @@ pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *openi } static inline void -pm_interpolated_xstring_node_append(pm_interpolated_x_string_node_t *node, pm_node_t *part) { - pm_interpolated_node_append(UP(node), &node->parts, part); +pm_interpolated_xstring_node_append(pm_arena_t *arena, pm_interpolated_x_string_node_t *node, pm_node_t *part) { + pm_interpolated_node_append(arena, UP(node), &node->parts, part); PM_NODE_LENGTH_SET_NODE(node, part); } @@ -5093,14 +5081,14 @@ pm_keyword_hash_node_create(pm_parser_t *parser) { * Append an element to a KeywordHashNode node. */ static void -pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *element) { +pm_keyword_hash_node_elements_append(pm_arena_t *arena, pm_keyword_hash_node_t *hash, pm_node_t *element) { // If the element being added is not an AssocNode or does not have a symbol // key, then we want to turn the SYMBOL_KEYS flag off. if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE) || !PM_NODE_TYPE_P(((pm_assoc_node_t *) element)->key, PM_SYMBOL_NODE)) { pm_node_flag_unset(UP(hash), PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS); } - pm_node_list_append(&hash->elements, element); + pm_node_list_append(arena, &hash->elements, element); if (PM_NODE_LENGTH(hash) == 0) { PM_NODE_START_SET_NODE(hash, element); } @@ -5458,19 +5446,19 @@ pm_multi_target_node_targets_append(pm_parser_t *parser, pm_multi_target_node_t node->rest = target; } else { pm_parser_err_node(parser, target, PM_ERR_MULTI_ASSIGN_MULTI_SPLATS); - pm_node_list_append(&node->rights, target); + pm_node_list_append(parser->arena, &node->rights, target); } } else if (PM_NODE_TYPE_P(target, PM_IMPLICIT_REST_NODE)) { if (node->rest == NULL) { node->rest = target; } else { PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, &parser->current, PM_ERR_MULTI_ASSIGN_UNEXPECTED_REST); - pm_node_list_append(&node->rights, target); + pm_node_list_append(parser->arena, &node->rights, target); } } else if (node->rest == NULL) { - pm_node_list_append(&node->lefts, target); + pm_node_list_append(parser->arena, &node->lefts, target); } else { - pm_node_list_append(&node->rights, target); + pm_node_list_append(parser->arena, &node->rights, target); } if (PM_NODE_LENGTH(node) == 0 || (PM_NODE_START(node) > PM_NODE_START(target))) { @@ -5520,9 +5508,8 @@ pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, .value = value }; - // Explicitly do not call pm_node_destroy here because we want to keep - // around all of the information within the MultiWriteNode node. - xfree_sized(target, sizeof(pm_multi_target_node_t)); + // The target is no longer necessary because we've reused its children. + // It is arena-allocated so no explicit free is needed. return node; } @@ -5751,27 +5738,27 @@ pm_parameters_node_location_set(pm_parameters_node_t *params, pm_node_t *param) * Append a required parameter to a ParametersNode node. */ static void -pm_parameters_node_requireds_append(pm_parameters_node_t *params, pm_node_t *param) { +pm_parameters_node_requireds_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_node_t *param) { pm_parameters_node_location_set(params, param); - pm_node_list_append(¶ms->requireds, param); + pm_node_list_append(arena, ¶ms->requireds, param); } /** * Append an optional parameter to a ParametersNode node. */ static void -pm_parameters_node_optionals_append(pm_parameters_node_t *params, pm_optional_parameter_node_t *param) { +pm_parameters_node_optionals_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_optional_parameter_node_t *param) { pm_parameters_node_location_set(params, UP(param)); - pm_node_list_append(¶ms->optionals, UP(param)); + pm_node_list_append(arena, ¶ms->optionals, UP(param)); } /** * Append a post optional arguments parameter to a ParametersNode node. */ static void -pm_parameters_node_posts_append(pm_parameters_node_t *params, pm_node_t *param) { +pm_parameters_node_posts_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_node_t *param) { pm_parameters_node_location_set(params, param); - pm_node_list_append(¶ms->posts, param); + pm_node_list_append(arena, ¶ms->posts, param); } /** @@ -5787,9 +5774,9 @@ pm_parameters_node_rest_set(pm_parameters_node_t *params, pm_node_t *param) { * Append a keyword parameter to a ParametersNode node. */ static void -pm_parameters_node_keywords_append(pm_parameters_node_t *params, pm_node_t *param) { +pm_parameters_node_keywords_append(pm_arena_t *arena, pm_parameters_node_t *params, pm_node_t *param) { pm_parameters_node_location_set(params, param); - pm_node_list_append(¶ms->keywords, param); + pm_node_list_append(arena, ¶ms->keywords, param); } /** @@ -6088,8 +6075,8 @@ pm_rescue_node_subsequent_set(pm_rescue_node_t *node, pm_rescue_node_t *subseque * Append an exception node to a rescue node, and update the location. */ static void -pm_rescue_node_exceptions_append(pm_rescue_node_t *node, pm_node_t *exception) { - pm_node_list_append(&node->exceptions, exception); +pm_rescue_node_exceptions_append(pm_arena_t *arena, pm_rescue_node_t *node, pm_node_t *exception) { + pm_node_list_append(arena, &node->exceptions, exception); PM_NODE_LENGTH_SET_NODE(node, exception); } @@ -6325,7 +6312,7 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, } } - pm_node_list_append(&node->body, statement); + pm_node_list_append(parser->arena, &node->body, statement); if (newline) pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); } @@ -6333,9 +6320,9 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, * Prepend a new node to the given StatementsNode node's body. */ static void -pm_statements_node_body_prepend(pm_statements_node_t *node, pm_node_t *statement) { +pm_statements_node_body_prepend(pm_arena_t *arena, pm_statements_node_t *node, pm_node_t *statement) { pm_statements_node_body_update(node, statement); - pm_node_list_prepend(&node->body, statement); + pm_node_list_prepend(arena, &node->body, statement); pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); } @@ -6749,10 +6736,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_node_flag_set(UP(new_node), parse_symbol_encoding(parser, &content, &node->unescaped, true)); - // We are explicitly _not_ using pm_node_destroy here because we don't want - // to trash the unescaped string. We could instead copy the string if we - // know that it is owned, but we're taking the fast path for now. - xfree_sized(node, sizeof(pm_string_node_t)); + // The old node is arena-allocated so no explicit free is needed. return new_node; } @@ -6782,10 +6766,7 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { .unescaped = node->unescaped }; - // We are explicitly _not_ using pm_node_destroy here because we don't want - // to trash the unescaped string. We could instead copy the string if we - // know that it is owned, but we're taking the fast path for now. - xfree_sized(node, sizeof(pm_symbol_node_t)); + // The old node is arena-allocated so no explicit free is needed. return new_node; } @@ -6840,9 +6821,9 @@ pm_undef_node_create(pm_parser_t *parser, const pm_token_t *token) { * Append a name to an undef node. */ static void -pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) { +pm_undef_node_append(pm_arena_t *arena, pm_undef_node_t *node, pm_node_t *name) { PM_NODE_LENGTH_SET_NODE(node, name); - pm_node_list_append(&node->names, name); + pm_node_list_append(arena, &node->names, name); } /** @@ -6984,9 +6965,9 @@ pm_when_node_create(pm_parser_t *parser, const pm_token_t *keyword) { * Append a new condition to a when node. */ static void -pm_when_node_conditions_append(pm_when_node_t *node, pm_node_t *condition) { +pm_when_node_conditions_append(pm_arena_t *arena, pm_when_node_t *node, pm_node_t *condition) { PM_NODE_LENGTH_SET_NODE(node, condition); - pm_node_list_append(&node->conditions, condition); + pm_node_list_append(arena, &node->conditions, condition); } /** @@ -7247,7 +7228,6 @@ pm_parser_scope_pop(pm_parser_t *parser) { pm_scope_t *scope = parser->current_scope; parser->current_scope = scope->previous; pm_locals_free(&scope->locals); - pm_node_list_free(&scope->implicit_parameters); xfree_sized(scope, sizeof(pm_scope_t)); } @@ -9284,7 +9264,11 @@ lex_question_mark(pm_parser_t *parser) { pm_buffer_init_capacity(&buffer, 3); escape_read(parser, &buffer, NULL, PM_ESCAPE_FLAG_SINGLE); - pm_string_owned_init(&parser->current_string, (uint8_t *) buffer.value, buffer.length); + + // Copy buffer data into the arena and free the heap buffer. + void *arena_data = pm_arena_memdup(parser->arena, buffer.value, buffer.length, PRISM_ALIGNOF(uint8_t)); + pm_string_constant_init(&parser->current_string, (const char *) arena_data, buffer.length); + pm_buffer_free(&buffer); return PM_TOKEN_CHARACTER_LITERAL; } else { @@ -9614,12 +9598,16 @@ pm_slice_ascii_only_p(const uint8_t *value, size_t length) { */ static inline void pm_token_buffer_copy(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { - pm_string_owned_init(&parser->current_string, (uint8_t *) pm_buffer_value(&token_buffer->buffer), pm_buffer_length(&token_buffer->buffer)); + // Copy buffer data into the arena and free the heap buffer. + size_t len = pm_buffer_length(&token_buffer->buffer); + void *arena_data = pm_arena_memdup(parser->arena, pm_buffer_value(&token_buffer->buffer), len, PRISM_ALIGNOF(uint8_t)); + pm_string_constant_init(&parser->current_string, (const char *) arena_data, len); + pm_buffer_free(&token_buffer->buffer); } static inline void pm_regexp_token_buffer_copy(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { - pm_string_owned_init(&parser->current_string, (uint8_t *) pm_buffer_value(&token_buffer->base.buffer), pm_buffer_length(&token_buffer->base.buffer)); + pm_token_buffer_copy(parser, &token_buffer->base); parser->current_regular_expression_ascii_only = pm_slice_ascii_only_p((const uint8_t *) pm_buffer_value(&token_buffer->regexp_buffer), pm_buffer_length(&token_buffer->regexp_buffer)); pm_buffer_free(&token_buffer->regexp_buffer); } @@ -12734,7 +12722,6 @@ parse_unwriteable_target(pm_parser_t *parser, pm_node_t *target) { pm_constant_id_t name = pm_parser_constant_id_raw(parser, parser->start + PM_NODE_START(target), parser->start + PM_NODE_END(target)); pm_local_variable_target_node_t *result = pm_local_variable_target_node_create(parser, &target->location, name, 0); - pm_node_destroy(parser, target); return UP(result); } @@ -12813,7 +12800,6 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p pm_node_t *node = UP(pm_local_variable_target_node_create(parser, &target->location, name, 0)); pm_node_unreference(parser, target); - pm_node_destroy(parser, target); return node; } @@ -12864,7 +12850,6 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_p // =, so we know it's a local variable write. pm_location_t message_loc = call->message_loc; pm_constant_id_t name = pm_parser_local_add_location(parser, &message_loc, 0); - pm_node_destroy(parser, target); return UP(pm_local_variable_target_node_create(parser, &message_loc, name, 0)); } @@ -12939,11 +12924,9 @@ static pm_node_t * parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_node_t *value) { switch (PM_NODE_TYPE(target)) { case PM_MISSING_NODE: - pm_node_destroy(parser, value); return target; case PM_CLASS_VARIABLE_READ_NODE: { pm_class_variable_write_node_t *node = pm_class_variable_write_node_create(parser, (pm_class_variable_read_node_t *) target, operator, value); - pm_node_destroy(parser, target); return UP(node); } case PM_CONSTANT_PATH_NODE: { @@ -12962,7 +12945,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_IN_METHOD); } - pm_node_destroy(parser, target); return parse_shareable_constant_write(parser, node); } case PM_BACK_REFERENCE_READ_NODE: @@ -12971,7 +12953,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod PRISM_FALLTHROUGH case PM_GLOBAL_VARIABLE_READ_NODE: { pm_global_variable_write_node_t *node = pm_global_variable_write_node_create(parser, target, operator, value); - pm_node_destroy(parser, target); return UP(node); } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -12989,7 +12970,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod } pm_locals_unread(&scope->locals, name); - pm_node_destroy(parser, target); return UP(pm_local_variable_write_node_create(parser, name, depth, value, &location, operator)); } @@ -12998,13 +12978,11 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_node_t *node = UP(pm_local_variable_write_node_create(parser, name, 0, value, &target->location, operator)); pm_node_unreference(parser, target); - pm_node_destroy(parser, target); return node; } case PM_INSTANCE_VARIABLE_READ_NODE: { pm_node_t *write_node = UP(pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value)); - pm_node_destroy(parser, target); return write_node; } case PM_MULTI_TARGET_NODE: @@ -13049,7 +13027,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_refute_numbered_parameter(parser, message_loc.start, message_loc.length); pm_parser_local_add_location(parser, &message_loc, 0); - pm_node_destroy(parser, target); pm_constant_id_t constant_id = pm_parser_constant_id_raw(parser, parser->start + PM_LOCATION_START(&message_loc), parser->start + PM_LOCATION_END(&message_loc)); target = UP(pm_local_variable_write_node_create(parser, constant_id, 0, value, &message_loc, operator)); @@ -13071,7 +13048,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod pm_arguments_node_t *arguments = pm_arguments_node_create(parser); call->arguments = arguments; - pm_arguments_node_arguments_append(arguments, value); + pm_arguments_node_arguments_append(parser->arena, arguments, value); PM_NODE_LENGTH_SET_NODE(call, arguments); call->equal_loc = TOK2LOC(parser, operator); @@ -13090,7 +13067,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod call->arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(call->arguments, value); + pm_arguments_node_arguments_append(parser->arena, call->arguments, value); PM_NODE_LENGTH_SET_NODE(target, value); // Replace the name with "[]=". @@ -13115,7 +13092,6 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod // any implicit parameters from the list of implicit parameters for // the current scope. pm_node_unreference(parser, value); - pm_node_destroy(parser, value); } PRISM_FALLTHROUGH default: @@ -13149,7 +13125,6 @@ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t pm_constant_id_t name = pm_parser_local_add_location(parser, &target->location, 1); pm_local_variable_write_node_t *result = pm_local_variable_write_node_create(parser, name, 0, value, &target->location, equals); - pm_node_destroy(parser, target); return UP(result); } @@ -13472,9 +13447,9 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod } if (PM_NODE_TYPE_P(node, PM_HASH_NODE)) { - pm_hash_node_elements_append((pm_hash_node_t *) node, element); + pm_hash_node_elements_append(parser->arena, (pm_hash_node_t *) node, element); } else { - pm_keyword_hash_node_elements_append((pm_keyword_hash_node_t *) node, element); + pm_keyword_hash_node_elements_append(parser->arena, (pm_keyword_hash_node_t *) node, element); } // If there's no comma after the element, then we're done. @@ -13528,7 +13503,7 @@ parse_arguments_append(pm_parser_t *parser, pm_arguments_t *arguments, pm_node_t arguments->arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(arguments->arguments, argument); + pm_arguments_node_arguments_append(parser->arena, arguments->arguments, argument); } /** @@ -13697,7 +13672,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); argument = UP(pm_assoc_node_create(parser, argument, NTOK2PTR(operator), value)); - pm_keyword_hash_node_elements_append(bare_hash, argument); + pm_keyword_hash_node_elements_append(parser->arena, bare_hash, argument); argument = UP(bare_hash); // Then parse more if we have a comma @@ -13930,7 +13905,7 @@ parse_parameters_handle_trailing_comma( pm_parameters_node_rest_set(params, param); } else { pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI); - pm_parameters_node_posts_append(params, UP(param)); + pm_parameters_node_posts_append(parser->arena, params, UP(param)); } } else { // foo do |*bar,|; end @@ -13974,9 +13949,9 @@ parse_parameters( pm_node_t *param = UP(parse_required_destructured_parameter(parser)); if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) { - pm_parameters_node_requireds_append(params, param); + pm_parameters_node_requireds_append(parser->arena, params, param); } else { - pm_parameters_node_posts_append(params, param); + pm_parameters_node_posts_append(parser->arena, params, param); } break; } @@ -14012,7 +13987,7 @@ parse_parameters( pm_parameters_node_block_set(params, param); } else { pm_parser_err_node(parser, param, PM_ERR_PARAMETER_BLOCK_MULTI); - pm_parameters_node_posts_append(params, param); + pm_parameters_node_posts_append(parser->arena, params, param); } break; @@ -14032,7 +14007,7 @@ parse_parameters( // If we already have a keyword rest parameter, then we replace it with the // forwarding parameter and move the keyword rest parameter to the posts list. pm_node_t *keyword_rest = params->keyword_rest; - pm_parameters_node_posts_append(params, keyword_rest); + pm_parameters_node_posts_append(parser->arena, params, keyword_rest); if (succeeded) pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_FWD); params->keyword_rest = NULL; } @@ -14093,7 +14068,7 @@ parse_parameters( if (repeated) { pm_node_flag_set_repeated_parameter(UP(param)); } - pm_parameters_node_optionals_append(params, param); + pm_parameters_node_optionals_append(parser->arena, params, param); // If the value of the parameter increased the number of // reads of that parameter, then we need to warn that we @@ -14116,13 +14091,13 @@ parse_parameters( if (repeated) { pm_node_flag_set_repeated_parameter(UP(param)); } - pm_parameters_node_requireds_append(params, UP(param)); + pm_parameters_node_requireds_append(parser->arena, params, UP(param)); } else { pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name); if (repeated) { pm_node_flag_set_repeated_parameter(UP(param)); } - pm_parameters_node_posts_append(params, UP(param)); + pm_parameters_node_posts_append(parser->arena, params, UP(param)); } break; @@ -14158,7 +14133,7 @@ parse_parameters( pm_node_flag_set_repeated_parameter(param); } - pm_parameters_node_keywords_append(params, param); + pm_parameters_node_keywords_append(parser->arena, params, param); break; } case PM_TOKEN_SEMICOLON: @@ -14175,7 +14150,7 @@ parse_parameters( pm_node_flag_set_repeated_parameter(param); } - pm_parameters_node_keywords_append(params, param); + pm_parameters_node_keywords_append(parser->arena, params, param); break; } default: { @@ -14204,7 +14179,7 @@ parse_parameters( } context_pop(parser); - pm_parameters_node_keywords_append(params, param); + pm_parameters_node_keywords_append(parser->arena, params, param); // If parsing the value of the parameter resulted in error recovery, // then we can put a missing node in its place and stop parsing the @@ -14245,7 +14220,7 @@ parse_parameters( pm_parameters_node_rest_set(params, param); } else { pm_parser_err_node(parser, param, PM_ERR_PARAMETER_SPLAT_MULTI); - pm_parameters_node_posts_append(params, param); + pm_parameters_node_posts_append(parser->arena, params, param); } break; @@ -14287,7 +14262,7 @@ parse_parameters( pm_parameters_node_keyword_rest_set(params, param); } else { pm_parser_err_node(parser, param, PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI); - pm_parameters_node_posts_append(params, param); + pm_parameters_node_posts_append(parser->arena, params, param); } break; @@ -14327,7 +14302,6 @@ parse_parameters( // If we don't have any parameters, return `NULL` instead of an empty `ParametersNode`. if (PM_NODE_START(params) == PM_NODE_END(params)) { - pm_node_destroy(parser, UP(params)); return NULL; } @@ -14486,7 +14460,7 @@ parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_ do { pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_RESCUE_EXPRESSION, (uint16_t) (depth + 1)); - pm_rescue_node_exceptions_append(rescue, expression); + pm_rescue_node_exceptions_append(parser->arena, rescue, expression); // If we hit a newline, then this is the end of the rescue expression. We // can continue on to parse the statements. @@ -14725,7 +14699,7 @@ parse_block_parameters( pm_block_local_variable_node_t *local = pm_block_local_variable_node_create(parser, &parser->previous); if (repeated) pm_node_flag_set_repeated_parameter(UP(local)); - pm_block_parameters_node_append_local(block_parameters, local); + pm_block_parameters_node_append_local(parser->arena, block_parameters, local); } while (accept1(parser, PM_TOKEN_COMMA)); } } @@ -14972,7 +14946,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept if (arguments->arguments == NULL) { arguments->arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(arguments->arguments, arguments->block); + pm_arguments_node_arguments_append(parser->arena, arguments->arguments, arguments->block); } arguments->block = UP(block); } @@ -15116,7 +15090,7 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node) { // block exit to the list of exits for the expression, and // the node parsing will handle validating it instead. assert(parser->current_block_exits != NULL); - pm_node_list_append(parser->current_block_exits, node); + pm_node_list_append(parser->arena, parser->current_block_exits, node); return; case PM_CONTEXT_BEGIN_ELSE: case PM_CONTEXT_BEGIN_ENSURE: @@ -15207,7 +15181,7 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) { // However, they could still become valid in a higher level context if // there is another list above this one. In this case we'll push all of // the block exits up to the previous list. - pm_node_list_concat(previous_block_exits, parser->current_block_exits); + pm_node_list_concat(parser->arena, previous_block_exits, parser->current_block_exits); parser->current_block_exits = previous_block_exits; } else { // If we did not match a trailing while/until and this was the last @@ -15365,8 +15339,6 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return parent; } @@ -15681,11 +15653,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s } pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening); - if (part) pm_interpolated_symbol_node_append(symbol, part); + if (part) pm_interpolated_symbol_node_append(parser->arena, symbol, part); while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_interpolated_symbol_node_append(symbol, part); + pm_interpolated_symbol_node_append(parser->arena, symbol, part); } } @@ -15720,10 +15692,10 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s if (match1(parser, PM_TOKEN_STRING_CONTENT)) { pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening); pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &content, NULL, &unescaped)); - pm_interpolated_symbol_node_append(symbol, part); + pm_interpolated_symbol_node_append(parser->arena, symbol, part); part = UP(pm_string_node_create_unescaped(parser, NULL, &parser->current, NULL, &parser->current_string)); - pm_interpolated_symbol_node_append(symbol, part); + pm_interpolated_symbol_node_append(parser->arena, symbol, part); if (next_state != PM_LEX_STATE_NONE) { lex_state_set(parser, next_state); @@ -15862,12 +15834,12 @@ parse_variable(pm_parser_t *parser) { } pm_node_t *node = UP(pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false)); - pm_node_list_append(¤t_scope->implicit_parameters, node); + pm_node_list_append(parser->arena, ¤t_scope->implicit_parameters, node); return node; } else if ((parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) && pm_token_is_it(parser->previous.start, parser->previous.end)) { pm_node_t *node = UP(pm_it_local_variable_read_node_create(parser, &parser->previous)); - pm_node_list_append(¤t_scope->implicit_parameters, node); + pm_node_list_append(parser->arena, ¤t_scope->implicit_parameters, node); return node; } @@ -15923,16 +15895,25 @@ parse_method_definition_name(pm_parser_t *parser) { } static void -parse_heredoc_dedent_string(pm_string_t *string, size_t common_whitespace) { - // Get a reference to the string struct that is being held by the string - // node. This is the value we're going to actually manipulate. - pm_string_ensure_owned(string); +parse_heredoc_dedent_string(pm_arena_t *arena, pm_string_t *string, size_t common_whitespace) { + // Make a writable copy in the arena if the string isn't already writable. + // We keep a mutable pointer to the arena memory so we can memmove into it + // below without casting away const from the string's source field. + uint8_t *writable; + + if (string->type != PM_STRING_OWNED) { + size_t length = pm_string_length(string); + writable = (uint8_t *) pm_arena_memdup(arena, pm_string_source(string), length, PRISM_ALIGNOF(uint8_t)); + pm_string_constant_init(string, (const char *) writable, length); + } else { + writable = (uint8_t *) string->source; + } // Now get the bounds of the existing string. We'll use this as a // destination to move bytes into. We'll also use it for bounds checking // since we don't require that these strings be null terminated. size_t dest_length = pm_string_length(string); - const uint8_t *source_cursor = (uint8_t *) string->source; + const uint8_t *source_cursor = writable; const uint8_t *source_end = source_cursor + dest_length; // We're going to move bytes backward in the string when we get leading @@ -15956,7 +15937,7 @@ parse_heredoc_dedent_string(pm_string_t *string, size_t common_whitespace) { dest_length--; } - memmove((uint8_t *) string->source, source_cursor, (size_t) (source_end - source_cursor)); + memmove(writable, source_cursor, (size_t) (source_end - source_cursor)); string->length = dest_length; } @@ -15999,11 +15980,10 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w pm_string_node_t *string_node = ((pm_string_node_t *) node); if (dedent_next) { - parse_heredoc_dedent_string(&string_node->unescaped, common_whitespace); + parse_heredoc_dedent_string(parser->arena, &string_node->unescaped, common_whitespace); } if (heredoc_dedent_discard_string_node(parser, string_node)) { - pm_node_destroy(parser, node); } else { nodes->nodes[write_index++] = node; } @@ -16092,18 +16072,16 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 if (match1(parser, PM_TOKEN_STRING_CONTENT)) { pm_node_list_t parts = { 0 }; pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &content, NULL, &unescaped)); - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); do { part = UP(pm_string_node_create_current_string(parser, NULL, &parser->current, NULL)); - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); parser_lex(parser); } while (match1(parser, PM_TOKEN_STRING_CONTENT)); expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous)); - - pm_node_list_free(&parts); } else if (accept1(parser, PM_TOKEN_LABEL_END)) { node = UP(pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true))); if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL); @@ -16152,11 +16130,11 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 pm_node_list_t parts = { 0 }; pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &parser->previous, NULL, &unescaped)); pm_node_flag_set(part, parse_unescaped_encoding(parser)); - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); } } @@ -16170,8 +16148,6 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous)); } - - pm_node_list_free(&parts); } } else { // If we get here, then the first part of the string is not plain @@ -16182,7 +16158,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); } } @@ -16196,8 +16172,6 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM); node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous)); } - - pm_node_list_free(&parts); } if (current == NULL) { @@ -16228,11 +16202,11 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 concating = true; pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(container, current); + pm_interpolated_string_node_append(parser->arena, container, current); current = UP(container); } - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, node); } } @@ -16259,7 +16233,7 @@ parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_c if (pm_constant_id_list_includes(captures, capture)) { pm_parser_err(parser, location->start, location->length, PM_ERR_PATTERN_CAPTURE_DUPLICATE); } else { - pm_constant_id_list_append(captures, capture); + pm_constant_id_list_append(parser->arena, captures, capture); } } @@ -16379,7 +16353,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures // attaching its constant. In this case we'll create an array pattern and // attach our constant to it. pm_array_pattern_node_t *pattern_node = pm_array_pattern_node_constant_create(parser, node, &opening, &closing); - pm_array_pattern_node_requireds_append(pattern_node, inner); + pm_array_pattern_node_requireds_append(parser->arena, pattern_node, inner); return UP(pattern_node); } @@ -16557,7 +16531,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node } pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, NULL, value)); - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); break; } } @@ -16572,7 +16546,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node pm_node_t *value = UP(pm_missing_node_create(parser, PM_NODE_START(first_node), PM_NODE_LENGTH(first_node))); pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, NULL, value)); - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); break; } } @@ -16596,7 +16570,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node rest = assoc; } else { pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST); - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); } } else { pm_node_t *key; @@ -16637,12 +16611,12 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST); } - pm_node_list_append(&assocs, assoc); + pm_node_list_append(parser->arena, &assocs, assoc); } } pm_hash_pattern_node_t *node = pm_hash_pattern_node_node_list_create(parser, &assocs, rest); - xfree_sized(assocs.nodes, assocs.capacity * sizeof(pm_node_t *)); + // assocs.nodes is arena-allocated; no explicit free needed. pm_static_literals_free(&keys); return node; @@ -16724,7 +16698,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm } pm_array_pattern_node_t *node = pm_array_pattern_node_empty_create(parser, &opening, &closing); - pm_array_pattern_node_requireds_append(node, inner); + pm_array_pattern_node_requireds_append(parser->arena, node, inner); return UP(node); } case PM_TOKEN_BRACE_LEFT: { @@ -16809,7 +16783,6 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm pm_missing_node_t *missing_node = pm_missing_node_create(parser, PM_NODE_START(node), PM_NODE_LENGTH(node)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return UP(missing_node); } @@ -17121,14 +17094,14 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag // or a find pattern. We need to parse all of the patterns, put them // into a big list, and then determine which type of node we have. pm_node_list_t nodes = { 0 }; - pm_node_list_append(&nodes, node); + pm_node_list_append(parser->arena, &nodes, node); // Gather up all of the patterns into the list. while (accept1(parser, PM_TOKEN_COMMA)) { // Break early here in case we have a trailing comma. if (match7(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_SEMICOLON, PM_TOKEN_KEYWORD_AND, PM_TOKEN_KEYWORD_OR)) { node = UP(pm_implicit_rest_node_create(parser, &parser->previous)); - pm_node_list_append(&nodes, node); + pm_node_list_append(parser->arena, &nodes, node); trailing_rest = true; break; } @@ -17148,7 +17121,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag node = parse_pattern_primitives(parser, captures, NULL, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); } - pm_node_list_append(&nodes, node); + pm_node_list_append(parser->arena, &nodes, node); } // If the first pattern and the last pattern are rest patterns, then we @@ -17169,7 +17142,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag } } - xfree_sized(nodes.nodes, nodes.capacity * sizeof(pm_node_t *)); + // nodes.nodes is arena-allocated; no explicit free needed. } else if (leading_rest) { // Otherwise, if we parsed a single splat pattern, then we know we have // an array pattern, so we can go ahead and create that node. @@ -17587,7 +17560,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); pm_node_t *assoc = UP(pm_assoc_node_create(parser, element, NTOK2PTR(operator), value)); - pm_keyword_hash_node_elements_append(hash, assoc); + pm_keyword_hash_node_elements_append(parser->arena, hash, assoc); element = UP(hash); if (accept1(parser, PM_TOKEN_COMMA) && !match1(parser, PM_TOKEN_BRACKET_RIGHT)) { @@ -17599,7 +17572,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } - pm_array_node_elements_append(array, element); + pm_array_node_elements_append(parser->arena, array, element); if (PM_NODE_TYPE_P(element, PM_MISSING_NODE)) break; } @@ -17637,10 +17610,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // we have an empty parentheses node, and we can immediately return. if (match2(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_EOF)) { expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN); - pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, flags)); } @@ -17683,9 +17653,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_accepts_block_stack_pop(parser); - pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE) || PM_NODE_TYPE_P(statement, PM_SPLAT_NODE)) { // If we have a single statement and are ending on a right @@ -17821,8 +17789,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - pm_void_statements_check(parser, statements, true); return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags)); } @@ -18064,7 +18030,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } - pm_node_destroy(parser, node); return UP(fcall); } } @@ -18129,7 +18094,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (lex_mode.indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) { - parse_heredoc_dedent_string(&cast->unescaped, common_whitespace); + parse_heredoc_dedent_string(parser->arena, &cast->unescaped, common_whitespace); } node = UP(cast); @@ -18139,11 +18104,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // so we'll need to create an interpolated string node to hold // them all. pm_node_list_t parts = { 0 }; - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); while (!match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_node_list_append(&parts, part); + pm_node_list_append(parser->arena, &parts, part); } } @@ -18160,7 +18125,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b node = UP(cast); } else { pm_interpolated_string_node_t *cast = pm_interpolated_string_node_create(parser, &opening, &parts, &opening); - pm_node_list_free(&parts); expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length); pm_interpolated_string_node_closing_set(parser, cast, &parser->previous); @@ -18289,10 +18253,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match1(parser, PM_TOKEN_KEYWORD_END)) { parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, false); parser_lex(parser); - pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS); return UP(pm_case_node_create(parser, &case_keyword, predicate, &parser->previous)); } @@ -18321,12 +18282,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); pm_splat_node_t *splat_node = pm_splat_node_create(parser, &operator, expression); - pm_when_node_conditions_append(when_node, UP(splat_node)); + pm_when_node_conditions_append(parser->arena, when_node, UP(splat_node)); if (PM_NODE_TYPE_P(expression, PM_MISSING_NODE)) break; } else { pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN, (uint16_t) (depth + 1)); - pm_when_node_conditions_append(when_node, condition); + pm_when_node_conditions_append(parser->arena, when_node, condition); // If we found a missing node, then this is a syntax // error and we should stop looping. @@ -18360,7 +18321,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } - pm_case_node_condition_append(case_node, UP(when_node)); + pm_case_node_condition_append(parser->arena, case_node, UP(when_node)); } // If we didn't parse any conditions (in or when) then we need @@ -18399,7 +18360,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; - pm_constant_id_list_free(&captures); // Since we're in the top-level of the case-in node we need // to check for guard clauses in the form of `if` or @@ -18439,7 +18399,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // Now that we have the full pattern and statements, we can // create the node and attach it to the case node. pm_node_t *condition = UP(pm_in_node_create(parser, pattern, statements, &in_keyword, NTOK2PTR(then_keyword))); - pm_case_match_node_condition_append(case_node, condition); + pm_case_match_node_condition_append(parser->arena, case_node, condition); } // If we didn't parse any conditions (in or when) then we need @@ -18479,8 +18439,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return node; } case PM_TOKEN_KEYWORD_BEGIN: { @@ -18507,10 +18465,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b PM_NODE_LENGTH_SET_TOKEN(parser, begin_node, &parser->previous); pm_begin_node_end_keyword_set(parser, begin_node, &parser->previous); - pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(begin_node); } case PM_TOKEN_KEYWORD_BEGIN_UPCASE: { @@ -18535,8 +18490,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } flush_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->previous)); } case PM_TOKEN_KEYWORD_BREAK: @@ -18616,7 +18569,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (arguments.block != NULL) { pm_parser_err_node(parser, arguments.block, PM_ERR_UNEXPECTED_BLOCK_ARGUMENT); pm_node_unreference(parser, arguments.block); - pm_node_destroy(parser, arguments.block); arguments.block = NULL; } @@ -18667,8 +18619,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_do_loop_stack_pop(parser); flush_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous)); } @@ -18732,8 +18682,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, NTOK2PTR(inheritance_operator), superclass, statements, &parser->previous)); } case PM_TOKEN_KEYWORD_DEF: { @@ -19069,7 +19017,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_constant_id_t name_id = pm_parser_constant_id_raw(parser, name.start, parse_operator_symbol_name(&name)); flush_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); return UP(pm_def_node_create( parser, @@ -19229,9 +19176,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *name = parse_undef_argument(parser, (uint16_t) (depth + 1)); if (PM_NODE_TYPE_P(name, PM_MISSING_NODE)) { - pm_node_destroy(parser, name); } else { - pm_undef_node_append(undef, name); + pm_undef_node_append(parser->arena, undef, name); while (match1(parser, PM_TOKEN_COMMA)) { lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM); @@ -19239,11 +19185,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b name = parse_undef_argument(parser, (uint16_t) (depth + 1)); if (PM_NODE_TYPE_P(name, PM_MISSING_NODE)) { - pm_node_destroy(parser, name); break; } - pm_undef_node_append(undef, name); + pm_undef_node_append(parser->arena, undef, name); } } @@ -19314,7 +19259,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // the name of the module, then we'll handle that here. if (PM_NODE_TYPE_P(constant_path, PM_MISSING_NODE)) { pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); pm_token_t missing = (pm_token_t) { .type = 0, .start = parser->previous.end, .end = parser->previous.end }; return UP(pm_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing)); @@ -19363,7 +19307,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); return UP(pm_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->previous)); } @@ -19478,7 +19421,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) { pm_node_t *string = UP(pm_string_node_create_current_string(parser, NULL, &parser->current, NULL)); parser_lex(parser); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) { pm_symbol_node_t *cast = (pm_symbol_node_t *) current; pm_token_t content = { .type = PM_TOKEN_STRING_CONTENT, .start = parser->start + cast->value_loc.start, .end = parser->start + cast->value_loc.start + cast->value_loc.length }; @@ -19487,10 +19430,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); - pm_interpolated_symbol_node_append(interpolated, first_string); - pm_interpolated_symbol_node_append(interpolated, second_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, first_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, second_string); - xfree_sized(current, sizeof(pm_symbol_node_t)); + // current is arena-allocated so no explicit free is needed. current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19498,7 +19441,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } else { expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_I_LOWER_ELEMENT); @@ -19534,7 +19477,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else { // If we hit a separator after we've hit content, then we need to // append that content to the list and reset the current node. - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } @@ -19555,7 +19498,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *string = UP(pm_string_node_create_current_string(parser, NULL, &parser->current, NULL)); parser_lex(parser); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) { // If we hit string content and the current node is a symbol node, // then we need to convert the current node into an interpolated @@ -19572,10 +19515,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); - pm_interpolated_symbol_node_append(interpolated, first_string); - pm_interpolated_symbol_node_append(interpolated, second_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, first_string); + pm_interpolated_symbol_node_append(parser->arena, interpolated, second_string); - xfree_sized(current, sizeof(pm_symbol_node_t)); + // current is arena-allocated so no explicit free is needed. current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19597,7 +19540,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current)); - pm_interpolated_symbol_node_append(interpolated, current); + pm_interpolated_symbol_node_append(parser->arena, interpolated, current); PM_NODE_START_SET_NODE(interpolated, current); start_location_set = true; current = UP(interpolated); @@ -19607,7 +19550,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, part); if (!start_location_set) { PM_NODE_START_SET_NODE(current, part); } @@ -19628,7 +19571,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, NULL, NULL, NULL); current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current)); - pm_interpolated_symbol_node_append(interpolated, current); + pm_interpolated_symbol_node_append(parser->arena, interpolated, current); PM_NODE_START_SET_NODE(interpolated, current); start_location_set = true; current = UP(interpolated); @@ -19640,7 +19583,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part); + pm_interpolated_symbol_node_append(parser->arena, (pm_interpolated_symbol_node_t *) current, part); if (!start_location_set) { PM_NODE_START_SET_NODE(current, part); } @@ -19655,7 +19598,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we have a current node, then we need to append it to the list. if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); } pm_token_t closing = parser->current; @@ -19688,11 +19631,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (current == NULL) { current = string; } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) { - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, string); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) { pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); - pm_interpolated_string_node_append(interpolated, string); + pm_interpolated_string_node_append(parser->arena, interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, string); current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19701,7 +19644,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } else { expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_W_LOWER_ELEMENT); @@ -19742,7 +19685,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we hit a separator after we've hit content, // then we need to append that content to the list // and reset the current node. - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); current = NULL; } @@ -19764,15 +19707,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we hit string content and the current node is // an interpolated string, then we need to append // the string content to the list of child nodes. - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, string); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) { // If we hit string content and the current node is // a string node, then we need to convert the // current node into an interpolated string and add // the string content to the list of child nodes. pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); - pm_interpolated_string_node_append(interpolated, string); + pm_interpolated_string_node_append(parser->arena, interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, string); current = UP(interpolated); } else { assert(false && "unreachable"); @@ -19793,7 +19736,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // current into an interpolated string and add the // string node to the list of parts. pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, current); current = UP(interpolated); } else { // If we hit an embedded variable and the current @@ -19802,7 +19745,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, part); break; } case PM_TOKEN_EMBEXPR_BEGIN: { @@ -19818,7 +19761,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // current into an interpolated string and add the // string node to the list of parts. pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, NULL, NULL, NULL); - pm_interpolated_string_node_append(interpolated, current); + pm_interpolated_string_node_append(parser->arena, interpolated, current); current = UP(interpolated); } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) { // If we hit an embedded expression and the current @@ -19829,7 +19772,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1)); - pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part); + pm_interpolated_string_node_append(parser->arena, (pm_interpolated_string_node_t *) current, part); break; } default: @@ -19841,7 +19784,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we have a current node, then we need to append it to the list. if (current) { - pm_array_node_elements_append(array, current); + pm_array_node_elements_append(parser->arena, array, current); } pm_token_t closing = parser->current; @@ -19919,7 +19862,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_flag_set(part, PM_STRING_FLAGS_FORCED_BINARY_ENCODING); } - pm_interpolated_regular_expression_node_append(interpolated, part); + pm_interpolated_regular_expression_node_append(parser->arena, interpolated, part); } else { // If the first part of the body of the regular expression is not a // string content, then we have interpolation and we need to create an @@ -19932,7 +19875,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *part; while (!match2(parser, PM_TOKEN_REGEXP_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_interpolated_regular_expression_node_append(interpolated, part); + pm_interpolated_regular_expression_node_append(parser->arena, interpolated, part); } } @@ -19995,7 +19938,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *part = UP(pm_string_node_create_unescaped(parser, NULL, &parser->previous, NULL, &unescaped)); pm_node_flag_set(part, parse_unescaped_encoding(parser)); - pm_interpolated_xstring_node_append(node, part); + pm_interpolated_xstring_node_append(parser->arena, node, part); } else { // If the first part of the body of the string is not a string // content, then we have interpolation and we need to create an @@ -20006,7 +19949,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *part; while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) { - pm_interpolated_xstring_node_append(node, part); + pm_interpolated_xstring_node_append(parser->arena, node, part); } } @@ -20340,13 +20283,13 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding single_value = false; pm_array_node_t *array = pm_array_node_create(parser, NULL); - pm_array_node_elements_append(array, value); + pm_array_node_elements_append(parser->arena, array, value); value = UP(array); while (accept1(parser, PM_TOKEN_COMMA)) { pm_node_t *element = parse_starred_expression(parser, binding_power, false, PM_ERR_ARRAY_ELEMENT, (uint16_t) (depth + 1)); - pm_array_node_elements_append(array, element); + pm_array_node_elements_append(parser->arena, array, element); if (PM_NODE_TYPE_P(element, PM_MISSING_NODE)) break; parse_assignment_value_local(parser, element); @@ -20393,14 +20336,12 @@ parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const if (call_node->arguments != NULL) { pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_ARGUMENTS); pm_node_unreference(parser, UP(call_node->arguments)); - pm_node_destroy(parser, UP(call_node->arguments)); call_node->arguments = NULL; } if (call_node->block != NULL) { pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_BLOCK); pm_node_unreference(parser, UP(call_node->block)); - pm_node_destroy(parser, UP(call_node->block)); call_node->block = NULL; } } @@ -20614,7 +20555,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { // Add this name to the list of constants if it is valid, not duplicated, // and not a keyword. if (name != 0 && !pm_constant_id_list_includes(names, name)) { - pm_constant_id_list_append(names, name); + pm_constant_id_list_append(parser->arena, names, name); int depth; if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) { @@ -20639,7 +20580,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { // Next, create the local variable target and add it to the list of // targets for the match. pm_node_t *target = UP(pm_local_variable_target_node_create(parser, &TOK2LOC(parser, &((pm_token_t) { .type = 0, .start = start, .end = end })), name, depth == -1 ? 0 : (uint32_t) depth)); - pm_node_list_append(&callback_data->match->targets, target); + pm_node_list_append(parser->arena, &callback_data->match->targets, target); } pm_buffer_free(&unescaped); @@ -20666,7 +20607,6 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t * }; pm_regexp_parse(parser, pm_string_source(content), pm_string_length(content), extended_mode, parse_regular_expression_named_capture, &callback_data, parse_regular_expression_error, &error_data); - pm_constant_id_list_free(&callback_data.names); if (callback_data.match != NULL) { return UP(callback_data.match); @@ -20752,7 +20692,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_and_write_node_create(parser, node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_CLASS_VARIABLE_READ_NODE: { @@ -20761,7 +20700,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_CONSTANT_PATH_NODE: { @@ -20778,7 +20716,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return parse_shareable_constant_write(parser, write); } case PM_INSTANCE_VARIABLE_READ_NODE: { @@ -20787,7 +20724,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_IT_LOCAL_VARIABLE_READ_NODE: { @@ -20798,7 +20734,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return result; } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -20813,7 +20748,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth)); - pm_node_destroy(parser, node); return result; } case PM_CALL_NODE: { @@ -20830,7 +20764,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); - pm_node_destroy(parser, UP(cast)); return result; } @@ -20884,7 +20817,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_or_write_node_create(parser, node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_CLASS_VARIABLE_READ_NODE: { @@ -20893,7 +20825,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_CONSTANT_PATH_NODE: { @@ -20910,7 +20841,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return parse_shareable_constant_write(parser, write); } case PM_INSTANCE_VARIABLE_READ_NODE: { @@ -20919,7 +20849,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_IT_LOCAL_VARIABLE_READ_NODE: { @@ -20930,7 +20859,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return result; } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -20945,7 +20873,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth)); - pm_node_destroy(parser, node); return result; } case PM_CALL_NODE: { @@ -20962,7 +20889,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); - pm_node_destroy(parser, UP(cast)); return result; } @@ -21026,7 +20952,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_operator_write_node_create(parser, node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_CLASS_VARIABLE_READ_NODE: { @@ -21035,7 +20960,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_CONSTANT_PATH_NODE: { @@ -21052,7 +20976,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return parse_shareable_constant_write(parser, write); } case PM_INSTANCE_VARIABLE_READ_NODE: { @@ -21061,7 +20984,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); - pm_node_destroy(parser, node); return result; } case PM_IT_LOCAL_VARIABLE_READ_NODE: { @@ -21072,7 +20994,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); - pm_node_destroy(parser, node); return result; } case PM_LOCAL_VARIABLE_READ_NODE: { @@ -21087,7 +21008,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth)); - pm_node_destroy(parser, node); return result; } case PM_CALL_NODE: { @@ -21103,7 +21023,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); - pm_node_destroy(parser, UP(cast)); return result; } @@ -21418,8 +21337,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t context_pop(parser); pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression)); } @@ -21431,8 +21348,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t context_pop(parser); pop_block_exits(parser, previous_block_exits); - pm_node_list_free(¤t_block_exits); - return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression)); } case PM_TOKEN_COLON_COLON: { @@ -21554,7 +21469,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if (arguments.arguments == NULL) { arguments.arguments = pm_arguments_node_create(parser); } - pm_arguments_node_arguments_append(arguments.arguments, arguments.block); + pm_arguments_node_arguments_append(parser->arena, arguments.arguments, arguments.block); } arguments.block = UP(block); @@ -21575,7 +21490,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; - pm_constant_id_list_free(&captures); return UP(pm_match_predicate_node_create(parser, node, pattern, &operator)); } @@ -21592,7 +21506,6 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; - pm_constant_id_list_free(&captures); return UP(pm_match_required_node_create(parser, node, pattern, &operator)); } @@ -21842,6 +21755,7 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { pm_arguments_node_t *arguments = pm_arguments_node_create(parser); pm_arguments_node_arguments_append( + parser->arena, arguments, UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2))) ); @@ -21861,6 +21775,7 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { pm_arguments_node_t *arguments = pm_arguments_node_create(parser); pm_arguments_node_arguments_append( + parser->arena, arguments, UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$;", 2))) ); @@ -21874,25 +21789,26 @@ wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { UP(call) ); - pm_statements_node_body_prepend(statements, UP(write)); + pm_statements_node_body_prepend(parser->arena, statements, UP(write)); } pm_arguments_node_t *arguments = pm_arguments_node_create(parser); pm_arguments_node_arguments_append( + parser->arena, arguments, UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$/", 2))) ); if (PM_PARSER_COMMAND_LINE_OPTION_L(parser)) { pm_keyword_hash_node_t *keywords = pm_keyword_hash_node_create(parser); - pm_keyword_hash_node_elements_append(keywords, UP(pm_assoc_node_create( + pm_keyword_hash_node_elements_append(parser->arena, keywords, UP(pm_assoc_node_create( parser, UP(pm_symbol_node_synthesized_create(parser, "chomp")), NULL, UP(pm_true_node_synthesized_create(parser)) ))); - pm_arguments_node_arguments_append(arguments, UP(keywords)); + pm_arguments_node_arguments_append(parser->arena, arguments, UP(keywords)); pm_node_flag_set(UP(arguments), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS); } @@ -21947,8 +21863,6 @@ parse_program(pm_parser_t *parser) { flush_block_exits(parser, previous_block_exits); } - pm_node_list_free(¤t_block_exits); - // If this is an empty file, then we're still going to parse all of the // statements in order to gather up all of the comments and such. Here we'll // correct the location information. @@ -22031,10 +21945,12 @@ pm_parser_init_shebang(pm_parser_t *parser, const pm_options_t *options, const c * Initialize a parser with the given start and end pointers. */ PRISM_EXPORTED_FUNCTION void -pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options) { +pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options) { + assert(arena != NULL); assert(source != NULL); *parser = (pm_parser_t) { + .arena = arena, .node_id = 0, .lex_state = PM_LEX_STATE_BEG, .enclosure_nesting = 0, @@ -22421,20 +22337,20 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t * can stream stdin in to Ruby so we need to support a streaming API. */ PRISM_EXPORTED_FUNCTION pm_node_t * -pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { +pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { pm_buffer_init(buffer); bool eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); - pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); pm_node_t *node = pm_parse(parser); while (!eof && parser->error_list.size > 0) { - pm_node_destroy(parser, node); eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); pm_parser_free(parser); - pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + pm_arena_free(arena); + pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); node = pm_parse(parser); } @@ -22449,14 +22365,15 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); - pm_node_t *node = pm_parse(&parser); - pm_node_destroy(&parser, node); + pm_parse(&parser); bool result = parser.error_list.size == 0; pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); return result; @@ -22500,8 +22417,9 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); pm_node_t *node = pm_parse(&parser); @@ -22509,8 +22427,8 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons pm_serialize_content(&parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } @@ -22520,19 +22438,20 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons */ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) { + pm_arena_t arena = { 0 }; pm_parser_t parser; pm_options_t options = { 0 }; pm_options_read(&options, data); pm_buffer_t parser_buffer; - pm_node_t *node = pm_parse_stream(&parser, &parser_buffer, stream, stream_fgets, stream_feof, &options); + pm_node_t *node = pm_parse_stream(&arena, &parser, &parser_buffer, stream, stream_fgets, stream_feof, &options); pm_serialize_header(buffer); pm_serialize_content(&parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_node_destroy(&parser, node); pm_buffer_free(&parser_buffer); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } @@ -22544,17 +22463,18 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); - pm_node_t *node = pm_parse(&parser); + pm_parse(&parser); pm_serialize_header(buffer); pm_serialize_encoding(parser.encoding, buffer); pm_buffer_append_varsint(buffer, parser.start_line); pm_serialize_comment_list(&parser.comment_list, buffer); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } diff --git a/src/util/pm_arena.c b/src/util/pm_arena.c new file mode 100644 index 0000000000..a9b69b3c8d --- /dev/null +++ b/src/util/pm_arena.c @@ -0,0 +1,105 @@ +#include "prism/util/pm_arena.h" + +/** + * Compute the block allocation size using offsetof so it is correct regardless + * of PM_FLEX_ARY_LEN. + */ +#define PM_ARENA_BLOCK_SIZE(data_size) (offsetof(pm_arena_block_t, data) + (data_size)) + +/** Initial block data size: 8 KB. */ +#define PM_ARENA_INITIAL_SIZE 8192 + +/** Double the block size every this many blocks. */ +#define PM_ARENA_GROWTH_INTERVAL 8 + +/** Maximum block data size: 1 MB. */ +#define PM_ARENA_MAX_SIZE (1024 * 1024) + +/** + * Compute the data size for the next block. + */ +static size_t +pm_arena_next_block_size(const pm_arena_t *arena, size_t min_size) { + size_t size = PM_ARENA_INITIAL_SIZE; + + for (size_t i = PM_ARENA_GROWTH_INTERVAL; i <= arena->block_count; i += PM_ARENA_GROWTH_INTERVAL) { + if (size < PM_ARENA_MAX_SIZE) size *= 2; + } + + return size > min_size ? size : min_size; +} + +/** + * Allocate memory from the arena. The returned memory is NOT zeroed. This + * function is infallible — it aborts on allocation failure. + */ +void * +pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { + // Try current block. + if (arena->current != NULL) { + size_t used_aligned = (arena->current->used + alignment - 1) & ~(alignment - 1); + size_t needed = used_aligned + size; + + // Guard against overflow in the alignment or size arithmetic. + if (used_aligned >= arena->current->used && needed >= used_aligned && needed <= arena->current->capacity) { + arena->current->used = needed; + return arena->current->data + used_aligned; + } + } + + // Allocate new block via xmalloc — memory is NOT zeroed. + // New blocks from xmalloc are max-aligned, so data[] starts aligned for + // any C type. No padding needed at the start. + size_t block_data_size = pm_arena_next_block_size(arena, size); + pm_arena_block_t *block = (pm_arena_block_t *) xmalloc(PM_ARENA_BLOCK_SIZE(block_data_size)); + + if (block == NULL) { + fprintf(stderr, "prism: out of memory; aborting\n"); + abort(); + } + + block->capacity = block_data_size; + block->used = size; + block->prev = arena->current; + arena->current = block; + arena->block_count++; + + return block->data; +} + +/** + * Allocate zero-initialized memory from the arena. This function is infallible + * — it aborts on allocation failure. + */ +void * +pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { + void *ptr = pm_arena_alloc(arena, size, alignment); + memset(ptr, 0, size); + return ptr; +} + +/** + * Allocate memory from the arena and copy the given data into it. + */ +void * +pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { + void *dst = pm_arena_alloc(arena, size, alignment); + memcpy(dst, src, size); + return dst; +} + +/** + * Free all blocks in the arena. + */ +void +pm_arena_free(pm_arena_t *arena) { + pm_arena_block_t *block = arena->current; + + while (block != NULL) { + pm_arena_block_t *prev = block->prev; + xfree_sized(block, PM_ARENA_BLOCK_SIZE(block->capacity)); + block = prev; + } + + *arena = (pm_arena_t) { 0 }; +} diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index bde7f959ea..f7173dd062 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -1,4 +1,5 @@ #include "prism/util/pm_constant_pool.h" +#include "prism/util/pm_arena.h" /** * Initialize a list of constant ids. @@ -14,10 +15,9 @@ pm_constant_id_list_init(pm_constant_id_list_t *list) { * Initialize a list of constant ids with a given capacity. */ void -pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity) { +pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity) { if (capacity) { - list->ids = xcalloc(capacity, sizeof(pm_constant_id_t)); - if (list->ids == NULL) abort(); + list->ids = (pm_constant_id_t *) pm_arena_zalloc(arena, capacity * sizeof(pm_constant_id_t), PRISM_ALIGNOF(pm_constant_id_t)); } else { list->ids = NULL; } @@ -27,24 +27,23 @@ pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity) } /** - * Append a constant id to a list of constant ids. Returns false if any - * potential reallocations fail. + * Append a constant id to a list of constant ids. */ -bool -pm_constant_id_list_append(pm_constant_id_list_t *list, pm_constant_id_t id) { +void +pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id) { if (list->size >= list->capacity) { - const size_t original_capacity = list->capacity; - list->capacity = list->capacity == 0 ? 8 : list->capacity * 2; - list->ids = (pm_constant_id_t *) xrealloc_sized( - list->ids, - sizeof(pm_constant_id_t) * list->capacity, - sizeof(pm_constant_id_t) * original_capacity - ); - if (list->ids == NULL) return false; + size_t new_capacity = list->capacity == 0 ? 8 : list->capacity * 2; + pm_constant_id_t *new_ids = (pm_constant_id_t *) pm_arena_alloc(arena, sizeof(pm_constant_id_t) * new_capacity, PRISM_ALIGNOF(pm_constant_id_t)); + + if (list->size > 0) { + memcpy(new_ids, list->ids, list->size * sizeof(pm_constant_id_t)); + } + + list->ids = new_ids; + list->capacity = new_capacity; } list->ids[list->size++] = id; - return true; } /** @@ -70,16 +69,6 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) { return false; } -/** - * Free the memory associated with a list of constant ids. - */ -void -pm_constant_id_list_free(pm_constant_id_list_t *list) { - if (list->ids != NULL) { - xfree_sized(list->ids, list->capacity * sizeof(pm_constant_id_t)); - } -} - /** * A relatively simple hash function (djb2) that is used to hash strings. We are * optimizing here for simplicity and speed. diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index e42a8e5b70..5806742612 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -3,150 +3,73 @@ /** * Attempts to grow the node list to the next size. If there is already - * capacity in the list, this function does nothing. Otherwise it reallocates - * the list to be twice as large as it was before. If the reallocation fails, - * this function returns false, otherwise it returns true. + * capacity in the list, this function does nothing. Otherwise it allocates a + * new array from the arena (abandon-and-copy strategy) and copies the existing + * data into it. */ -static bool -pm_node_list_grow(pm_node_list_t *list, size_t size) { +static void +pm_node_list_grow(pm_arena_t *arena, pm_node_list_t *list, size_t size) { size_t requested_size = list->size + size; - // If the requested size caused overflow, return false. - if (requested_size < list->size) return false; + // Guard against overflow on the addition. + if (requested_size < list->size) abort(); - // If the requested size is within the existing capacity, return true. - if (requested_size < list->capacity) return true; + // If the requested size is within the existing capacity, return. + if (requested_size <= list->capacity) return; - // Otherwise, reallocate the list to be twice as large as it was before. + // Otherwise, compute the next capacity by doubling. size_t next_capacity = list->capacity == 0 ? 4 : list->capacity * 2; - // If multiplying by 2 caused overflow, return false. - if (next_capacity < list->capacity) return false; - - // If we didn't get enough by doubling, keep doubling until we do. + // Guard against overflow on the doubling. while (requested_size > next_capacity) { - size_t double_capacity = next_capacity * 2; - - // Ensure we didn't overflow by multiplying by 2. - if (double_capacity < next_capacity) return false; - next_capacity = double_capacity; + if (next_capacity == 0) abort(); + next_capacity *= 2; } - pm_node_t **nodes = (pm_node_t **) xrealloc_sized( - list->nodes, - sizeof(pm_node_t *) * next_capacity, - sizeof(pm_node_t *) * list->capacity - ); - if (nodes == NULL) return false; + // Allocate a new array from the arena (old array is abandoned). + pm_node_t **nodes = (pm_node_t **) pm_arena_alloc(arena, sizeof(pm_node_t *) * next_capacity, PRISM_ALIGNOF(pm_node_t *)); + + // Copy old data into the new array. + if (list->size > 0) { + memcpy(nodes, list->nodes, list->size * sizeof(pm_node_t *)); + } list->nodes = nodes; list->capacity = next_capacity; - return true; } /** * Append a new node onto the end of the node list. */ void -pm_node_list_append(pm_node_list_t *list, pm_node_t *node) { - if (pm_node_list_grow(list, 1)) { - list->nodes[list->size++] = node; - } +pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { + pm_node_list_grow(arena, list, 1); + list->nodes[list->size++] = node; } /** * Prepend a new node onto the beginning of the node list. */ void -pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node) { - if (pm_node_list_grow(list, 1)) { - memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *)); - list->nodes[0] = node; - list->size++; - } +pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { + pm_node_list_grow(arena, list, 1); + memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *)); + list->nodes[0] = node; + list->size++; } /** * Concatenate the given node list onto the end of the other node list. */ void -pm_node_list_concat(pm_node_list_t *list, pm_node_list_t *other) { - if (other->size > 0 && pm_node_list_grow(list, other->size)) { +pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other) { + if (other->size > 0) { + pm_node_list_grow(arena, list, other->size); memcpy(list->nodes + list->size, other->nodes, other->size * sizeof(pm_node_t *)); list->size += other->size; } } -/** - * Free the internal memory associated with the given node list. - */ -void -pm_node_list_free(pm_node_list_t *list) { - if (list->capacity > 0) { - xfree_sized(list->nodes, sizeof(pm_node_t *) * list->capacity); - *list = (pm_node_list_t) { 0 }; - } -} - -PRISM_EXPORTED_FUNCTION void -pm_node_destroy(pm_parser_t *parser, pm_node_t *node); - -/** - * Destroy the nodes that are contained within the given node list. - */ -static void -pm_node_list_destroy(pm_parser_t *parser, pm_node_list_t *list) { - pm_node_t *node; - PM_NODE_LIST_FOREACH(list, index, node) pm_node_destroy(parser, node); - pm_node_list_free(list); -} - -/** - * Deallocate the space for a pm_node_t. Similarly to pm_node_alloc, we're not - * using the parser argument, but it's there to allow for the future possibility - * of pre-allocating larger memory pools. - */ -PRISM_EXPORTED_FUNCTION void -pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { - switch (PM_NODE_TYPE(node)) { - <%- nodes.each do |node| -%> -#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" - case <%= node.type %>: { - <%- if node.fields.any? { |field| ![Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField].include?(field.class) } -%> - pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; - <%- end -%> - <%- node.fields.each do |field| -%> - <%- case field -%> - <%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField -%> - <%- when Prism::Template::NodeField -%> - pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>); - <%- when Prism::Template::OptionalNodeField -%> - if (cast-><%= field.name %> != NULL) { - pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>); - } - <%- when Prism::Template::StringField -%> - pm_string_free(&cast-><%= field.name %>); - <%- when Prism::Template::NodeListField -%> - pm_node_list_destroy(parser, &cast-><%= field.name %>); - <%- when Prism::Template::ConstantListField -%> - pm_constant_id_list_free(&cast-><%= field.name %>); - <%- when Prism::Template::IntegerField -%> - pm_integer_free(&cast-><%= field.name %>); - <%- else -%> - <%- raise -%> - <%- end -%> - <%- end -%> - xfree_sized(node, sizeof(pm_<%= node.human %>_t)); - break; - } - <%- end -%> -#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" - default: - assert(false && "unreachable"); - break; - } -} - /** * Returns a string representation of the given node type. */ diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 54a499d8bb..e58bb81f0a 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -350,8 +350,9 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); pm_lex_callback_t lex_callback = (pm_lex_callback_t) { .data = (void *) buffer, @@ -359,15 +360,15 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const }; parser.lex_callback = &lex_callback; - pm_node_t *node = pm_parse(&parser); + pm_parse(&parser); // Append 0 to mark end of tokens. pm_buffer_append_byte(buffer, 0); pm_serialize_metadata(&parser, buffer); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } @@ -380,8 +381,9 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_options_t options = { 0 }; pm_options_read(&options, data); + pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_parser_init(&parser, source, size, &options); + pm_parser_init(&arena, &parser, source, size, &options); pm_lex_callback_t lex_callback = (pm_lex_callback_t) { .data = (void *) buffer, @@ -394,8 +396,8 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_buffer_append_byte(buffer, 0); pm_serialize(&parser, node, buffer); - pm_node_destroy(&parser, node); pm_parser_free(&parser); + pm_arena_free(&arena); pm_options_free(&options); } From de78576a7fd0743163bebf34e751cbb117512b23 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 5 Mar 2026 21:27:48 +0100 Subject: [PATCH 084/289] Recompile when prism headers change * See https://github.com/ruby/prism/pull/3932#issuecomment-3915768654 --- ext/prism/extconf.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/prism/extconf.rb b/ext/prism/extconf.rb index ae1691c979..ea7cfe963e 100644 --- a/ext/prism/extconf.rb +++ b/ext/prism/extconf.rb @@ -122,6 +122,8 @@ def add_libprism_source(path) add_libprism_source("$(srcdir)/../../src") + add_libprism_source("$(srcdir)/../../src/util") +$headers += Dir["#{$srcdir}/../../include/**/*.h"] + # Finally, we'll create the `Makefile` that is going to be used to configure and # build the C extension. create_makefile("prism/prism") From 5a33460adc8be526a3c8bdfb8adac0e0f5cb4bc8 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 5 Mar 2026 21:42:44 +0100 Subject: [PATCH 085/289] Revert "Recompile when config.yml changes" * This reverts commit ffe8f7a6e236790858e089d10bbc91f9ef9de6cb. * No longer necessary as the Makefile depends on all *.c and *.h. --- ext/prism/depend | 2 -- prism.gemspec | 2 -- 2 files changed, 4 deletions(-) delete mode 100644 ext/prism/depend diff --git a/ext/prism/depend b/ext/prism/depend deleted file mode 100644 index ac0e7a9bb3..0000000000 --- a/ext/prism/depend +++ /dev/null @@ -1,2 +0,0 @@ -$(OBJS): $(HDRS) $(ruby_headers) -$(OBJS): $(srcdir)/../../config.yml diff --git a/prism.gemspec b/prism.gemspec index 74d5412731..b85eeab855 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -42,8 +42,6 @@ Gem::Specification.new do |spec| "docs/serialization.md", "docs/testing.md", "ext/prism/api_node.c", - "ext/prism/depend", - "ext/prism/extconf.rb", "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", From d4575f651a95b93645f9c6dc154b29eba4b7e1d6 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 5 Mar 2026 21:43:56 +0100 Subject: [PATCH 086/289] Include ext/prism/extconf.rb explicitly in prism.gemspec * For consistency. --- prism.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/prism.gemspec b/prism.gemspec index b85eeab855..ae5c56a45d 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -42,6 +42,7 @@ Gem::Specification.new do |spec| "docs/serialization.md", "docs/testing.md", "ext/prism/api_node.c", + "ext/prism/extconf.rb", "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", From 5d80bc5e1ace42b195a1e003781fa17c78dcee5f Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 5 Mar 2026 20:41:21 +0100 Subject: [PATCH 087/289] Correctly handle `and?` and similar on ruby 4.0 It gets confused for syntax introduced in https://bugs.ruby-lang.org/issues/20925 But it actually should be a plain method call. `!`/`?` are not valid as part of an identifier, methods however allow them as the last character. Fixes [Bug #21946] --- snapshots/4.0/leading_logical.txt | 72 ++++------ snapshots/and_or_with_suffix.txt | 139 ++++++++++++++++++++ src/prism.c | 21 ++- test/prism/fixtures/4.0/leading_logical.txt | 5 - test/prism/fixtures/and_or_with_suffix.txt | 17 +++ test/prism/ruby/ripper_test.rb | 7 + 6 files changed, 204 insertions(+), 57 deletions(-) create mode 100644 snapshots/and_or_with_suffix.txt create mode 100644 test/prism/fixtures/and_or_with_suffix.txt diff --git a/snapshots/4.0/leading_logical.txt b/snapshots/4.0/leading_logical.txt index 9e043a88ce..c8ecaa40ba 100644 --- a/snapshots/4.0/leading_logical.txt +++ b/snapshots/4.0/leading_logical.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(21,5)) +@ ProgramNode (location: (1,0)-(15,4)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(21,5)) + @ StatementsNode (location: (1,0)-(15,4)) ├── flags: ∅ - └── body: (length: 8) + └── body: (length: 4) ├── @ AndNode (location: (1,0)-(3,4)) │ ├── flags: newline │ ├── left: @@ -62,50 +62,22 @@ │ │ ├── flags: static_literal, decimal │ │ └── value: 3 │ └── operator_loc: (11,0)-(11,3) = "and" - ├── @ OrNode (location: (13,0)-(15,4)) - │ ├── flags: newline - │ ├── left: - │ │ @ OrNode (location: (13,0)-(14,4)) - │ │ ├── flags: ∅ - │ │ ├── left: - │ │ │ @ IntegerNode (location: (13,0)-(13,1)) - │ │ │ ├── flags: static_literal, decimal - │ │ │ └── value: 1 - │ │ ├── right: - │ │ │ @ IntegerNode (location: (14,3)-(14,4)) - │ │ │ ├── flags: static_literal, decimal - │ │ │ └── value: 2 - │ │ └── operator_loc: (14,0)-(14,2) = "or" - │ ├── right: - │ │ @ IntegerNode (location: (15,3)-(15,4)) - │ │ ├── flags: static_literal, decimal - │ │ └── value: 3 - │ └── operator_loc: (15,0)-(15,2) = "or" - ├── @ IntegerNode (location: (17,0)-(17,1)) - │ ├── flags: newline, static_literal, decimal - │ └── value: 1 - ├── @ CallNode (location: (18,0)-(18,6)) - │ ├── flags: newline, variable_call, ignore_visibility - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :andfoo - │ ├── message_loc: (18,0)-(18,6) = "andfoo" - │ ├── opening_loc: ∅ - │ ├── arguments: ∅ - │ ├── closing_loc: ∅ - │ ├── equal_loc: ∅ - │ └── block: ∅ - ├── @ IntegerNode (location: (20,0)-(20,1)) - │ ├── flags: newline, static_literal, decimal - │ └── value: 2 - └── @ CallNode (location: (21,0)-(21,5)) - ├── flags: newline, variable_call, ignore_visibility - ├── receiver: ∅ - ├── call_operator_loc: ∅ - ├── name: :orfoo - ├── message_loc: (21,0)-(21,5) = "orfoo" - ├── opening_loc: ∅ - ├── arguments: ∅ - ├── closing_loc: ∅ - ├── equal_loc: ∅ - └── block: ∅ + └── @ OrNode (location: (13,0)-(15,4)) + ├── flags: newline + ├── left: + │ @ OrNode (location: (13,0)-(14,4)) + │ ├── flags: ∅ + │ ├── left: + │ │ @ IntegerNode (location: (13,0)-(13,1)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 1 + │ ├── right: + │ │ @ IntegerNode (location: (14,3)-(14,4)) + │ │ ├── flags: static_literal, decimal + │ │ └── value: 2 + │ └── operator_loc: (14,0)-(14,2) = "or" + ├── right: + │ @ IntegerNode (location: (15,3)-(15,4)) + │ ├── flags: static_literal, decimal + │ └── value: 3 + └── operator_loc: (15,0)-(15,2) = "or" diff --git a/snapshots/and_or_with_suffix.txt b/snapshots/and_or_with_suffix.txt new file mode 100644 index 0000000000..593dee1766 --- /dev/null +++ b/snapshots/and_or_with_suffix.txt @@ -0,0 +1,139 @@ +@ ProgramNode (location: (1,0)-(17,5)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(17,5)) + ├── flags: ∅ + └── body: (length: 12) + ├── @ CallNode (location: (1,0)-(1,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (1,0)-(1,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (2,0)-(2,4)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :and? + │ ├── message_loc: (2,0)-(2,4) = "and?" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (4,0)-(4,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (4,0)-(4,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (5,0)-(5,3)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :or? + │ ├── message_loc: (5,0)-(5,3) = "or?" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (7,0)-(7,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (7,0)-(7,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (8,0)-(8,4)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :and! + │ ├── message_loc: (8,0)-(8,4) = "and!" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (10,0)-(10,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (10,0)-(10,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (11,0)-(11,3)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :or! + │ ├── message_loc: (11,0)-(11,3) = "or!" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (13,0)-(13,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (13,0)-(13,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (14,0)-(14,6)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :andbar + │ ├── message_loc: (14,0)-(14,6) = "andbar" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (16,0)-(16,3)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (16,0)-(16,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + └── @ CallNode (location: (17,0)-(17,5)) + ├── flags: newline, variable_call, ignore_visibility + ├── receiver: ∅ + ├── call_operator_loc: ∅ + ├── name: :orbar + ├── message_loc: (17,0)-(17,5) = "orbar" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + ├── equal_loc: ∅ + └── block: ∅ diff --git a/src/prism.c b/src/prism.c index e10a7710af..b6bc90ebd7 100644 --- a/src/prism.c +++ b/src/prism.c @@ -10034,8 +10034,21 @@ parser_lex(pm_parser_t *parser) { following && ( (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '&') || (peek_at(parser, following) == '|' && peek_at(parser, following + 1) == '|') || - (peek_at(parser, following) == 'a' && peek_at(parser, following + 1) == 'n' && peek_at(parser, following + 2) == 'd' && !char_is_identifier(parser, following + 3, parser->end - (following + 3))) || - (peek_at(parser, following) == 'o' && peek_at(parser, following + 1) == 'r' && !char_is_identifier(parser, following + 2, parser->end - (following + 2))) + ( + peek_at(parser, following) == 'a' && + peek_at(parser, following + 1) == 'n' && + peek_at(parser, following + 2) == 'd' && + peek_at(parser, next_content + 3) != '!' && + peek_at(parser, next_content + 3) != '?' && + !char_is_identifier(parser, following + 3, parser->end - (following + 3)) + ) || + ( + peek_at(parser, following) == 'o' && + peek_at(parser, following + 1) == 'r' && + peek_at(parser, next_content + 2) != '!' && + peek_at(parser, next_content + 2) != '?' && + !char_is_identifier(parser, following + 2, parser->end - (following + 2)) + ) ) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); @@ -10106,6 +10119,8 @@ parser_lex(pm_parser_t *parser) { peek_at(parser, next_content) == 'a' && peek_at(parser, next_content + 1) == 'n' && peek_at(parser, next_content + 2) == 'd' && + peek_at(parser, next_content + 3) != '!' && + peek_at(parser, next_content + 3) != '?' && !char_is_identifier(parser, next_content + 3, parser->end - (next_content + 3)) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); @@ -10122,6 +10137,8 @@ parser_lex(pm_parser_t *parser) { if ( peek_at(parser, next_content) == 'o' && peek_at(parser, next_content + 1) == 'r' && + peek_at(parser, next_content + 2) != '!' && + peek_at(parser, next_content + 2) != '?' && !char_is_identifier(parser, next_content + 2, parser->end - (next_content + 2)) ) { if (!lexed_comment) parser_lex_ignored_newline(parser); diff --git a/test/prism/fixtures/4.0/leading_logical.txt b/test/prism/fixtures/4.0/leading_logical.txt index feb5ee245c..ee87e00d4f 100644 --- a/test/prism/fixtures/4.0/leading_logical.txt +++ b/test/prism/fixtures/4.0/leading_logical.txt @@ -14,8 +14,3 @@ and 3 or 2 or 3 -1 -andfoo - -2 -orfoo diff --git a/test/prism/fixtures/and_or_with_suffix.txt b/test/prism/fixtures/and_or_with_suffix.txt new file mode 100644 index 0000000000..59ee4d0b88 --- /dev/null +++ b/test/prism/fixtures/and_or_with_suffix.txt @@ -0,0 +1,17 @@ +foo +and? + +foo +or? + +foo +and! + +foo +or! + +foo +andbar + +foo +orbar diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index ba01732bcb..92aa1ad0b3 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -37,6 +37,13 @@ class RipperTest < TestCase ] end + if RUBY_VERSION.start_with?("4.") + incorrect += [ + # https://bugs.ruby-lang.org/issues/21945 + "and_or_with_suffix.txt", + ] + end + # https://bugs.ruby-lang.org/issues/21669 incorrect << "4.1/void_value.txt" # https://bugs.ruby-lang.org/issues/19107 From b5486569791346bf5baefdd4a2fd464670528b7f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 5 Mar 2026 17:14:30 -0500 Subject: [PATCH 088/289] Template out node creation functions Only arena-aware not parser-aware. static inline inside of the header so we don't have to pay the lack of LTO cost just for these functions. Leaving parsing-specific logic inside prism.c, effectively wrapping every one of these functions. --- .gitignore | 1 + docs/configuration.md | 1 + prism.gemspec | 1 + src/prism.c | 3206 ++++++++++++------------ templates/include/prism/node_new.h.erb | 42 + templates/template.rb | 50 + 6 files changed, 1665 insertions(+), 1636 deletions(-) create mode 100644 templates/include/prism/node_new.h.erb diff --git a/.gitignore b/.gitignore index f649d2de44..b914ce4cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ out.svg /gemfiles/typecheck/bin/ /include/prism/ast.h /include/prism/diagnostic.h +/include/prism/node_new.h /javascript/node_modules/ /javascript/package-lock.json /javascript/src/deserialize.js diff --git a/docs/configuration.md b/docs/configuration.md index 97e01c8d82..30001b7db7 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -5,6 +5,7 @@ A lot of code in prism's repository is templated from a single configuration fil * `ext/prism/api_node.c` - for defining how to build Ruby objects for the nodes out of C structs * `include/prism/ast.h` - for defining the C structs that represent the nodes * `include/prism/diagnostic.h` - for defining the diagnostics +* `include/prism/node_new.h` - for defining the functions that create the nodes in C * `javascript/src/deserialize.js` - for defining how to deserialize the nodes in JavaScript * `javascript/src/nodes.js` - for defining the nodes in JavaScript * `java/org/ruby_lang/prism/AbstractNodeVisitor.java` - for defining the visitor interface for the nodes in Java diff --git a/prism.gemspec b/prism.gemspec index ae5c56a45d..d8b86c6fba 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -52,6 +52,7 @@ Gem::Specification.new do |spec| "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/node.h", + "include/prism/node_new.h", "include/prism/options.h", "include/prism/parser.h", "include/prism/prettyprint.h", diff --git a/src/prism.c b/src/prism.c index b6bc90ebd7..6f21c97bc3 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,4 +1,5 @@ #include "prism.h" +#include "prism/node_new.h" /** * The prism version and the serialization format. @@ -2018,26 +2019,17 @@ pm_integer_arena_move(pm_arena_t *arena, pm_integer_t *integer) { } } -#define PM_NODE_ALLOC(parser_, type_) (type_ *) pm_arena_zalloc((parser_)->arena, sizeof(type_), PRISM_ALIGNOF(type_)) -#define PM_NODE_INIT(parser_, type_, flags_, location_) (pm_node_t) { \ - .type = (type_), \ - .flags = (flags_), \ - .node_id = ++(parser_)->node_id, \ - .location = location_ \ -} - /** * Allocate a new MissingNode node. */ static pm_missing_node_t * pm_missing_node_create(pm_parser_t *parser, uint32_t start, uint32_t length) { - pm_missing_node_t *node = PM_NODE_ALLOC(parser, pm_missing_node_t); - - *node = (pm_missing_node_t) { - .base = PM_NODE_INIT(parser, PM_MISSING_NODE, 0, ((pm_location_t) { .start = start, .length = length })) - }; - - return node; + return pm_missing_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = length }) + ); } /** @@ -2046,16 +2038,16 @@ pm_missing_node_create(pm_parser_t *parser, uint32_t start, uint32_t length) { static pm_alias_global_variable_node_t * pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) { assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS); - pm_alias_global_variable_node_t *node = PM_NODE_ALLOC(parser, pm_alias_global_variable_node_t); - - *node = (pm_alias_global_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_ALIAS_GLOBAL_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name)), - .new_name = new_name, - .old_name = old_name, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_alias_global_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name), + new_name, + old_name, + TOK2LOC(parser, keyword) + ); } /** @@ -2064,16 +2056,16 @@ pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyw static pm_alias_method_node_t * pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) { assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS); - pm_alias_method_node_t *node = PM_NODE_ALLOC(parser, pm_alias_method_node_t); - - *node = (pm_alias_method_node_t) { - .base = PM_NODE_INIT(parser, PM_ALIAS_METHOD_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name)), - .new_name = new_name, - .old_name = old_name, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_alias_method_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, old_name), + new_name, + old_name, + TOK2LOC(parser, keyword) + ); } /** @@ -2081,16 +2073,15 @@ pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_n */ static pm_alternation_pattern_node_t * pm_alternation_pattern_node_create(pm_parser_t *parser, pm_node_t *left, pm_node_t *right, const pm_token_t *operator) { - pm_alternation_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_alternation_pattern_node_t); - - *node = (pm_alternation_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ALTERNATION_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_alternation_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -2100,16 +2091,15 @@ static pm_and_node_t * pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); - pm_and_node_t *node = PM_NODE_ALLOC(parser, pm_and_node_t); - - *node = (pm_and_node_t) { - .base = PM_NODE_INIT(parser, PM_AND_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .operator_loc = TOK2LOC(parser, operator), - .right = right - }; - - return node; + return pm_and_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -2117,14 +2107,13 @@ pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *opera */ static pm_arguments_node_t * pm_arguments_node_create(pm_parser_t *parser) { - pm_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_arguments_node_t); - - *node = (pm_arguments_node_t) { - .base = PM_NODE_INIT(parser, PM_ARGUMENTS_NODE, 0, PM_LOCATION_INIT_UNSET), - .arguments = { 0 } - }; - - return node; + return pm_arguments_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -2164,25 +2153,27 @@ pm_arguments_node_arguments_append(pm_arena_t *arena, pm_arguments_node_t *node, */ static pm_array_node_t * pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) { - pm_array_node_t *node = PM_NODE_ALLOC(parser, pm_array_node_t); - if (opening == NULL) { - *node = (pm_array_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_UNSET), - .opening_loc = { 0 }, - .closing_loc = { 0 }, - .elements = { 0 } - }; + return pm_array_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } else { - *node = (pm_array_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, opening), - .elements = { 0 } - }; + return pm_array_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, opening) + ); } - - return node; } /** @@ -2224,17 +2215,18 @@ pm_array_node_close_set(const pm_parser_t *parser, pm_array_node_t *node, const */ static pm_array_pattern_node_t * pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *nodes) { - pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(nodes->nodes[0], nodes->nodes[nodes->size - 1])), - .constant = NULL, - .rest = NULL, - .requireds = { 0 }, - .posts = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + pm_array_pattern_node_t *node = pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(nodes->nodes[0], nodes->nodes[nodes->size - 1]), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); // For now we're going to just copy over each pointer manually. This could be // much more efficient, as we could instead resize the node list. @@ -2260,19 +2252,18 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node */ static pm_array_pattern_node_t * pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) { - pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODE(rest)), - .constant = NULL, - .rest = rest, - .requireds = { 0 }, - .posts = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(rest), + NULL, + ((pm_node_list_t) { 0 }), + rest, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -2281,19 +2272,18 @@ pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) { */ static pm_array_pattern_node_t * pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant, const pm_token_t *opening, const pm_token_t *closing) { - pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_NODE_TOKEN(parser, constant, closing)), - .constant = constant, - .rest = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .requireds = { 0 }, - .posts = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE_TOKEN(parser, constant, closing), + constant, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -2302,19 +2292,18 @@ pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant, */ static pm_array_pattern_node_t * pm_array_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t); - - *node = (pm_array_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_ARRAY_PATTERN_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .constant = NULL, - .rest = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .requireds = { 0 }, - .posts = { 0 } - }; - - return node; + return pm_array_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } static inline void @@ -2327,7 +2316,6 @@ pm_array_pattern_node_requireds_append(pm_arena_t *arena, pm_array_pattern_node_ */ static pm_assoc_node_t * pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *operator, pm_node_t *value) { - pm_assoc_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_node_t); uint32_t end; if (value != NULL && PM_NODE_END(value) > PM_NODE_END(key)) { @@ -2355,14 +2343,15 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper flags = key->flags & value->flags & PM_NODE_FLAG_STATIC_LITERAL; } - *node = (pm_assoc_node_t) { - .base = PM_NODE_INIT(parser, PM_ASSOC_NODE, flags, ((pm_location_t) { .start = PM_NODE_START(key), .length = U32(end - PM_NODE_START(key)) })), - .key = key, - .operator_loc = NTOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_assoc_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = PM_NODE_START(key), .length = U32(end - PM_NODE_START(key)) }), + key, + value, + NTOK2LOC(parser, operator) + ); } /** @@ -2371,15 +2360,15 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper static pm_assoc_splat_node_t * pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token_t *operator) { assert(operator->type == PM_TOKEN_USTAR_STAR); - pm_assoc_splat_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_splat_node_t); - - *node = (pm_assoc_splat_node_t) { - .base = PM_NODE_INIT(parser, PM_ASSOC_SPLAT_NODE, 0, (value == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, value)), - .value = value, - .operator_loc = TOK2LOC(parser, operator) - }; - return node; + return pm_assoc_splat_node_new( + parser->arena, + ++parser->node_id, + 0, + (value == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, value), + value, + TOK2LOC(parser, operator) + ); } /** @@ -2388,14 +2377,14 @@ pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token static pm_back_reference_read_node_t * pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_BACK_REFERENCE); - pm_back_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_back_reference_read_node_t); - - *node = (pm_back_reference_read_node_t) { - .base = PM_NODE_INIT(parser, PM_BACK_REFERENCE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - return node; + return pm_back_reference_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -2403,19 +2392,21 @@ pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) */ static pm_begin_node_t * pm_begin_node_create(pm_parser_t *parser, const pm_token_t *begin_keyword, pm_statements_node_t *statements) { - pm_begin_node_t *node = PM_NODE_ALLOC(parser, pm_begin_node_t); - uint32_t start = begin_keyword == NULL ? 0 : PM_TOKEN_START(parser, begin_keyword); uint32_t end = statements == NULL ? (begin_keyword == NULL ? 0 : PM_TOKEN_END(parser, begin_keyword)) : PM_NODE_END(statements); - *node = (pm_begin_node_t) { - .base = PM_NODE_INIT(parser, PM_BEGIN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .begin_keyword_loc = NTOK2LOC(parser, begin_keyword), - .statements = statements, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_begin_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, begin_keyword), + statements, + NULL, + NULL, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -2470,15 +2461,15 @@ pm_begin_node_end_keyword_set(const pm_parser_t *parser, pm_begin_node_t *node, static pm_block_argument_node_t * pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) { assert(operator->type == PM_TOKEN_UAMPERSAND); - pm_block_argument_node_t *node = PM_NODE_ALLOC(parser, pm_block_argument_node_t); - *node = (pm_block_argument_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_ARGUMENT_NODE, 0, (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression)), - .expression = expression, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_block_argument_node_new( + parser->arena, + ++parser->node_id, + 0, + (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression), + expression, + TOK2LOC(parser, operator) + ); } /** @@ -2486,18 +2477,17 @@ pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, p */ static pm_block_node_t * pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *opening, pm_node_t *parameters, pm_node_t *body, const pm_token_t *closing) { - pm_block_node_t *node = PM_NODE_ALLOC(parser, pm_block_node_t); - - *node = (pm_block_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .locals = *locals, - .parameters = parameters, - .body = body, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_block_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + *locals, + parameters, + body, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -2506,16 +2496,16 @@ pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p static pm_block_parameter_node_t * pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator) { assert(operator->type == PM_TOKEN_UAMPERSAND || operator->type == PM_TOKEN_AMPERSAND); - pm_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameter_node_t); - *node = (pm_block_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_block_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -2523,8 +2513,6 @@ pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, cons */ static pm_block_parameters_node_t * pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *parameters, const pm_token_t *opening) { - pm_block_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameters_node_t); - uint32_t start; if (opening != NULL) { start = PM_TOKEN_START(parser, opening); @@ -2543,15 +2531,16 @@ pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *param end = 0; } - *node = (pm_block_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETERS_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .parameters = parameters, - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = { 0 }, - .locals = { 0 } - }; - - return node; + return pm_block_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + parameters, + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, opening), + ((pm_location_t) { 0 }) + ); } /** @@ -2569,14 +2558,13 @@ pm_block_parameters_node_closing_set(const pm_parser_t *parser, pm_block_paramet */ static pm_block_local_variable_node_t * pm_block_local_variable_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_block_local_variable_node_t *node = PM_NODE_ALLOC(parser, pm_block_local_variable_node_t); - - *node = (pm_block_local_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_BLOCK_LOCAL_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_block_local_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -2599,15 +2587,15 @@ pm_block_parameters_node_append_local(pm_arena_t *arena, pm_block_parameters_nod static pm_break_node_t * pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_BREAK); - pm_break_node_t *node = PM_NODE_ALLOC(parser, pm_break_node_t); - - *node = (pm_break_node_t) { - .base = PM_NODE_INIT(parser, PM_BREAK_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .arguments = arguments, - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_break_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + arguments, + TOK2LOC(parser, keyword) + ); } // There are certain flags that we want to use internally but don't want to @@ -2626,22 +2614,21 @@ static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = ((PM_CALL_NODE_FLAGS_LAS */ static pm_call_node_t * pm_call_node_create(pm_parser_t *parser, pm_node_flags_t flags) { - pm_call_node_t *node = PM_NODE_ALLOC(parser, pm_call_node_t); - - *node = (pm_call_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_NODE, flags, PM_LOCATION_INIT_UNSET), - .receiver = NULL, - .call_operator_loc = { 0 }, - .message_loc = { 0 }, - .opening_loc = { 0 }, - .arguments = NULL, - .closing_loc = { 0 }, - .equal_loc = { 0 }, - .block = NULL, - .name = 0 - }; - - return node; + return pm_call_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_UNSET, + NULL, + ((pm_location_t) { 0 }), + 0, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + NULL, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + NULL + ); } /** @@ -2938,18 +2925,20 @@ static pm_call_and_write_node_t * pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_call_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_and_write_node_t); - - *node = (pm_call_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_AND_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_and_write_node_t *node = pm_call_and_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); @@ -2988,22 +2977,25 @@ pm_index_arguments_check(pm_parser_t *parser, const pm_arguments_node_t *argumen static pm_index_and_write_node_t * pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_index_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_and_write_node_t); pm_index_arguments_check(parser, target->arguments, target->block); assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); - *node = (pm_index_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_AND_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_index_and_write_node_t *node = pm_index_and_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + TOK2LOC(parser, operator), + value + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3017,19 +3009,21 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons static pm_call_operator_write_node_t * pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); - pm_call_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_operator_write_node_t); - - *node = (pm_call_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_OPERATOR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_operator_write_node_t *node = pm_call_operator_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); @@ -3044,23 +3038,25 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, */ static pm_index_operator_write_node_t * pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_index_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_operator_write_node_t); - pm_index_arguments_check(parser, target->arguments, target->block); assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); - *node = (pm_index_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_OPERATOR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_index_operator_write_node_t *node = pm_index_operator_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + TOK2LOC(parser, operator), + value + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3075,18 +3071,20 @@ static pm_call_or_write_node_t * pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(target->block == NULL); assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_call_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_or_write_node_t); - - *node = (pm_call_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_OR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .message_loc = target->message_loc, - .read_name = 0, - .write_name = target->name, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_call_or_write_node_t *node = pm_call_or_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->message_loc, + 0, + target->name, + TOK2LOC(parser, operator), + value + ); pm_call_write_read_name_init(parser, &node->read_name, &node->write_name); @@ -3102,22 +3100,25 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const static pm_index_or_write_node_t * pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_index_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_or_write_node_t); pm_index_arguments_check(parser, target->arguments, target->block); assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); - *node = (pm_index_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_OR_WRITE_NODE, FL(target), PM_LOCATION_INIT_NODES(target, value)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; + + pm_index_or_write_node_t *node = pm_index_or_write_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODES(target, value), + target->receiver, + target->call_operator_loc, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block, + TOK2LOC(parser, operator), + value + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3131,15 +3132,16 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const */ static pm_call_target_node_t * pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { - pm_call_target_node_t *node = PM_NODE_ALLOC(parser, pm_call_target_node_t); - - *node = (pm_call_target_node_t) { - .base = PM_NODE_INIT(parser, PM_CALL_TARGET_NODE, FL(target), PM_LOCATION_INIT_NODE(target)), - .receiver = target->receiver, - .call_operator_loc = target->call_operator_loc, - .name = target->name, - .message_loc = target->message_loc - }; + pm_call_target_node_t *node = pm_call_target_node_new( + parser->arena, + ++parser->node_id, + FL(target), + PM_LOCATION_INIT_NODE(target), + target->receiver, + target->call_operator_loc, + target->name, + target->message_loc + ); /* It is possible to get here where we have parsed an invalid syntax tree * where the call operator was not present. In that case we will have a @@ -3161,19 +3163,20 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { */ static pm_index_target_node_t * pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { - pm_index_target_node_t *node = PM_NODE_ALLOC(parser, pm_index_target_node_t); - pm_index_arguments_check(parser, target->arguments, target->block); assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE)); - *node = (pm_index_target_node_t) { - .base = PM_NODE_INIT(parser, PM_INDEX_TARGET_NODE, FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, PM_LOCATION_INIT_NODE(target)), - .receiver = target->receiver, - .opening_loc = target->opening_loc, - .arguments = target->arguments, - .closing_loc = target->closing_loc, - .block = (pm_block_argument_node_t *) target->block, - }; + pm_index_target_node_t *node = pm_index_target_node_new( + parser->arena, + ++parser->node_id, + FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, + PM_LOCATION_INIT_NODE(target), + target->receiver, + target->opening_loc, + target->arguments, + target->closing_loc, + (pm_block_argument_node_t *) target->block + ); // The target is no longer necessary because we've reused its children. // It is arena-allocated so no explicit free is needed. @@ -3186,16 +3189,15 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { */ static pm_capture_pattern_node_t * pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_variable_target_node_t *target, const pm_token_t *operator) { - pm_capture_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_capture_pattern_node_t); - - *node = (pm_capture_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_CAPTURE_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(value, target)), - .value = value, - .target = target, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_capture_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, target), + value, + target, + TOK2LOC(parser, operator) + ); } /** @@ -3203,18 +3205,17 @@ pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_v */ static pm_case_node_t * pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) { - pm_case_node_t *node = PM_NODE_ALLOC(parser, pm_case_node_t); - - *node = (pm_case_node_t) { - .base = PM_NODE_INIT(parser, PM_CASE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, case_keyword, end_keyword == NULL ? case_keyword : end_keyword)), - .predicate = predicate, - .else_clause = NULL, - .case_keyword_loc = TOK2LOC(parser, case_keyword), - .end_keyword_loc = NTOK2LOC(parser, end_keyword), - .conditions = { 0 } - }; - - return node; + return pm_case_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, case_keyword, end_keyword == NULL ? case_keyword : end_keyword), + predicate, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, case_keyword), + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3251,18 +3252,17 @@ pm_case_node_end_keyword_loc_set(const pm_parser_t *parser, pm_case_node_t *node */ static pm_case_match_node_t * pm_case_match_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate) { - pm_case_match_node_t *node = PM_NODE_ALLOC(parser, pm_case_match_node_t); - - *node = (pm_case_match_node_t) { - .base = PM_NODE_INIT(parser, PM_CASE_MATCH_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, case_keyword)), - .predicate = predicate, - .else_clause = NULL, - .case_keyword_loc = TOK2LOC(parser, case_keyword), - .end_keyword_loc = { 0 }, - .conditions = { 0 } - }; - - return node; + return pm_case_match_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, case_keyword), + predicate, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, case_keyword), + ((pm_location_t) { 0 }) + ); } /** @@ -3299,21 +3299,20 @@ pm_case_match_node_end_keyword_loc_set(const pm_parser_t *parser, pm_case_match_ */ static pm_class_node_t * pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, pm_node_t *constant_path, const pm_token_t *name, const pm_token_t *inheritance_operator, pm_node_t *superclass, pm_node_t *body, const pm_token_t *end_keyword) { - pm_class_node_t *node = PM_NODE_ALLOC(parser, pm_class_node_t); - - *node = (pm_class_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword)), - .locals = *locals, - .class_keyword_loc = TOK2LOC(parser, class_keyword), - .constant_path = constant_path, - .inheritance_operator_loc = NTOK2LOC(parser, inheritance_operator), - .superclass = superclass, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_class_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword), + *locals, + TOK2LOC(parser, class_keyword), + constant_path, + NTOK2LOC(parser, inheritance_operator), + superclass, + body, + TOK2LOC(parser, end_keyword), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -3322,17 +3321,17 @@ pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p static pm_class_variable_and_write_node_t * pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_class_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_and_write_node_t); - - *node = (pm_class_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_class_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3340,18 +3339,17 @@ pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_r */ static pm_class_variable_operator_write_node_t * pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_class_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_operator_write_node_t); - - *node = (pm_class_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_class_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3360,17 +3358,17 @@ pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_varia static pm_class_variable_or_write_node_t * pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_class_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_or_write_node_t); - - *node = (pm_class_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_class_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3379,14 +3377,14 @@ pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_re static pm_class_variable_read_node_t * pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_CLASS_VARIABLE); - pm_class_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_read_node_t); - - *node = (pm_class_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - return node; + return pm_class_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -3408,18 +3406,16 @@ pm_implicit_array_write_flags(const pm_node_t *node, pm_node_flags_t flags) { */ static pm_class_variable_write_node_t * pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) { - pm_class_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_class_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CLASS_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(read_node, value)), - .name = read_node->name, - .name_loc = read_node->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_class_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(read_node, value), + read_node->name, + read_node->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -3428,16 +3424,16 @@ pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_ static pm_constant_path_and_write_node_t * pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_constant_path_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_and_write_node_t); - - *node = (pm_constant_path_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_path_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3445,17 +3441,16 @@ pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_nod */ static pm_constant_path_operator_write_node_t * pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_path_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_operator_write_node_t); - - *node = (pm_constant_path_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_constant_path_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3464,16 +3459,16 @@ pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_pat static pm_constant_path_or_write_node_t * pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_constant_path_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_or_write_node_t); - - *node = (pm_constant_path_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_path_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3482,22 +3477,22 @@ pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node static pm_constant_path_node_t * pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_token_t *delimiter, const pm_token_t *name_token) { pm_assert_value_expression(parser, parent); - pm_constant_path_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_node_t); pm_constant_id_t name = PM_CONSTANT_ID_UNSET; if (name_token->type == PM_TOKEN_CONSTANT) { name = pm_parser_constant_id_token(parser, name_token); } - *node = (pm_constant_path_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_NODE, 0, (parent == NULL) ? PM_LOCATION_INIT_TOKENS(parser, delimiter, name_token) : PM_LOCATION_INIT_NODE_TOKEN(parser, parent, name_token)), - .parent = parent, - .name = name, - .delimiter_loc = TOK2LOC(parser, delimiter), - .name_loc = TOK2LOC(parser, name_token) - }; - - return node; + return pm_constant_path_node_new( + parser->arena, + ++parser->node_id, + 0, + (parent == NULL) ? PM_LOCATION_INIT_TOKENS(parser, delimiter, name_token) : PM_LOCATION_INIT_NODE_TOKEN(parser, parent, name_token), + parent, + name, + TOK2LOC(parser, delimiter), + TOK2LOC(parser, name_token) + ); } /** @@ -3505,17 +3500,15 @@ pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_to */ static pm_constant_path_write_node_t * pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_path_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_constant_path_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_PATH_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .target = target, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_constant_path_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target, + TOK2LOC(parser, operator), + value + ); } /** @@ -3524,17 +3517,17 @@ pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t static pm_constant_and_write_node_t * pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_constant_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_and_write_node_t); - - *node = (pm_constant_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3542,18 +3535,17 @@ pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t * */ static pm_constant_operator_write_node_t * pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_operator_write_node_t); - - *node = (pm_constant_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_constant_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -3562,17 +3554,17 @@ pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_nod static pm_constant_or_write_node_t * pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_constant_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_or_write_node_t); - - *node = (pm_constant_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_constant_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -3581,14 +3573,14 @@ pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *t static pm_constant_read_node_t * pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_CONSTANT || name->type == 0); - pm_constant_read_node_t *node = PM_NODE_ALLOC(parser, pm_constant_read_node_t); - - *node = (pm_constant_read_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - return node; + return pm_constant_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -3596,18 +3588,16 @@ pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) { */ static pm_constant_write_node_t * pm_constant_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_constant_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_constant_write_node_t) { - .base = PM_NODE_INIT(parser, PM_CONSTANT_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_constant_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -3673,29 +3663,28 @@ pm_def_node_create( const pm_token_t *equal, const pm_token_t *end_keyword ) { - pm_def_node_t *node = PM_NODE_ALLOC(parser, pm_def_node_t); - if (receiver != NULL) { pm_def_node_receiver_check(parser, receiver); } - *node = (pm_def_node_t) { - .base = PM_NODE_INIT(parser, PM_DEF_NODE, 0, (end_keyword == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, def_keyword, body) : PM_LOCATION_INIT_TOKENS(parser, def_keyword, end_keyword)), - .name = name, - .name_loc = TOK2LOC(parser, name_loc), - .receiver = receiver, - .parameters = parameters, - .body = body, - .locals = *locals, - .def_keyword_loc = TOK2LOC(parser, def_keyword), - .operator_loc = NTOK2LOC(parser, operator), - .lparen_loc = NTOK2LOC(parser, lparen), - .rparen_loc = NTOK2LOC(parser, rparen), - .equal_loc = NTOK2LOC(parser, equal), - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_def_node_new( + parser->arena, + ++parser->node_id, + 0, + (end_keyword == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, def_keyword, body) : PM_LOCATION_INIT_TOKENS(parser, def_keyword, end_keyword), + name, + TOK2LOC(parser, name_loc), + receiver, + parameters, + body, + *locals, + TOK2LOC(parser, def_keyword), + NTOK2LOC(parser, operator), + NTOK2LOC(parser, lparen), + NTOK2LOC(parser, rparen), + NTOK2LOC(parser, equal), + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3703,17 +3692,16 @@ pm_def_node_create( */ static pm_defined_node_t * pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t *value, const pm_token_t *rparen, const pm_token_t *keyword) { - pm_defined_node_t *node = PM_NODE_ALLOC(parser, pm_defined_node_t); - - *node = (pm_defined_node_t) { - .base = PM_NODE_INIT(parser, PM_DEFINED_NODE, 0, (rparen == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, value) : PM_LOCATION_INIT_TOKENS(parser, keyword, rparen)), - .lparen_loc = NTOK2LOC(parser, lparen), - .value = value, - .rparen_loc = NTOK2LOC(parser, rparen), - .keyword_loc = TOK2LOC(parser, keyword) - }; - - return node; + return pm_defined_node_new( + parser->arena, + ++parser->node_id, + 0, + (rparen == NULL) ? PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, value) : PM_LOCATION_INIT_TOKENS(parser, keyword, rparen), + NTOK2LOC(parser, lparen), + value, + NTOK2LOC(parser, rparen), + TOK2LOC(parser, keyword) + ); } /** @@ -3721,16 +3709,15 @@ pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t */ static pm_else_node_t * pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) { - pm_else_node_t *node = PM_NODE_ALLOC(parser, pm_else_node_t); - - *node = (pm_else_node_t) { - .base = PM_NODE_INIT(parser, PM_ELSE_NODE, 0, ((end_keyword == NULL) && (statements != NULL)) ? PM_LOCATION_INIT_TOKEN_NODE(parser, else_keyword, statements) : PM_LOCATION_INIT_TOKENS(parser, else_keyword, end_keyword)), - .else_keyword_loc = TOK2LOC(parser, else_keyword), - .statements = statements, - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_else_node_new( + parser->arena, + ++parser->node_id, + 0, + ((end_keyword == NULL) && (statements != NULL)) ? PM_LOCATION_INIT_TOKEN_NODE(parser, else_keyword, statements) : PM_LOCATION_INIT_TOKENS(parser, else_keyword, end_keyword), + TOK2LOC(parser, else_keyword), + statements, + NTOK2LOC(parser, end_keyword) + ); } /** @@ -3738,16 +3725,15 @@ pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_stat */ static pm_embedded_statements_node_t * pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_embedded_statements_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_statements_node_t); - - *node = (pm_embedded_statements_node_t) { - .base = PM_NODE_INIT(parser, PM_EMBEDDED_STATEMENTS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .statements = statements, - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_embedded_statements_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + statements, + TOK2LOC(parser, closing) + ); } /** @@ -3755,15 +3741,14 @@ pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *openin */ static pm_embedded_variable_node_t * pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) { - pm_embedded_variable_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_variable_node_t); - - *node = (pm_embedded_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_EMBEDDED_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable)), - .operator_loc = TOK2LOC(parser, operator), - .variable = variable - }; - - return node; + return pm_embedded_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable), + TOK2LOC(parser, operator), + variable + ); } /** @@ -3771,16 +3756,15 @@ pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator */ static pm_ensure_node_t * pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) { - pm_ensure_node_t *node = PM_NODE_ALLOC(parser, pm_ensure_node_t); - - *node = (pm_ensure_node_t) { - .base = PM_NODE_INIT(parser, PM_ENSURE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, ensure_keyword, end_keyword)), - .ensure_keyword_loc = TOK2LOC(parser, ensure_keyword), - .statements = statements, - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_ensure_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, ensure_keyword, end_keyword), + TOK2LOC(parser, ensure_keyword), + statements, + TOK2LOC(parser, end_keyword) + ); } /** @@ -3789,13 +3773,13 @@ pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_ static pm_false_node_t * pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_FALSE); - pm_false_node_t *node = PM_NODE_ALLOC(parser, pm_false_node_t); - *node = (pm_false_node_t) { - .base = PM_NODE_INIT(parser, PM_FALSE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_false_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -3804,8 +3788,6 @@ pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_find_pattern_node_t * pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { - pm_find_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_find_pattern_node_t); - pm_node_t *left = nodes->nodes[0]; assert(PM_NODE_TYPE_P(left, PM_SPLAT_NODE)); pm_splat_node_t *left_splat_node = (pm_splat_node_t *) left; @@ -3826,15 +3808,19 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { #else pm_node_t *right_splat_node = right; #endif - *node = (pm_find_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_FIND_PATTERN_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .constant = NULL, - .left = left_splat_node, - .right = right_splat_node, - .requireds = { 0 }, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + + pm_find_pattern_node_t *node = pm_find_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + NULL, + left_splat_node, + ((pm_node_list_t) { 0 }), + right_splat_node, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); // For now we're going to just copy over each pointer manually. This could be // much more efficient, as we could instead resize the node list to only point @@ -3926,14 +3912,14 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { static pm_float_node_t * pm_float_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT); - pm_float_node_t *node = PM_NODE_ALLOC(parser, pm_float_node_t); - *node = (pm_float_node_t) { - .base = PM_NODE_INIT(parser, PM_FLOAT_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .value = pm_double_parse(parser, token) - }; - - return node; + return pm_float_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_double_parse(parser, token) + ); } /** @@ -3943,17 +3929,17 @@ static pm_imaginary_node_t * pm_float_node_imaginary_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_float_node_create(parser, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_float_node_create(parser, &((pm_token_t) { .type = PM_TOKEN_FLOAT, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -3963,12 +3949,14 @@ static pm_rational_node_t * pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_RATIONAL); - pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t); - *node = (pm_rational_node_t) { - .base = PM_NODE_INIT(parser, PM_RATIONAL_NODE, PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numerator = { 0 }, - .denominator = { 0 } - }; + pm_rational_node_t *node = pm_rational_node_new( + parser->arena, + ++parser->node_id, + PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }), + ((pm_integer_t) { 0 }) + ); const uint8_t *start = token->start; const uint8_t *end = token->end - 1; // r @@ -4018,17 +4006,17 @@ static pm_imaginary_node_t * pm_float_node_rational_imaginary_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT_RATIONAL_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_float_node_rational_create(parser, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_float_node_rational_create(parser, &((pm_token_t) { .type = PM_TOKEN_FLOAT_RATIONAL, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4045,20 +4033,19 @@ pm_for_node_create( const pm_token_t *do_keyword, const pm_token_t *end_keyword ) { - pm_for_node_t *node = PM_NODE_ALLOC(parser, pm_for_node_t); - - *node = (pm_for_node_t) { - .base = PM_NODE_INIT(parser, PM_FOR_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, for_keyword, end_keyword)), - .index = index, - .collection = collection, - .statements = statements, - .for_keyword_loc = TOK2LOC(parser, for_keyword), - .in_keyword_loc = TOK2LOC(parser, in_keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_for_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, for_keyword, end_keyword), + index, + collection, + statements, + TOK2LOC(parser, for_keyword), + TOK2LOC(parser, in_keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, end_keyword) + ); } /** @@ -4067,13 +4054,13 @@ pm_for_node_create( static pm_forwarding_arguments_node_t * pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_UDOT_DOT_DOT); - pm_forwarding_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_arguments_node_t); - - *node = (pm_forwarding_arguments_node_t) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_ARGUMENTS_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_forwarding_arguments_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4082,13 +4069,13 @@ pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token static pm_forwarding_parameter_node_t * pm_forwarding_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_UDOT_DOT_DOT); - pm_forwarding_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_parameter_node_t); - - *node = (pm_forwarding_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_forwarding_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4098,19 +4085,19 @@ static pm_forwarding_super_node_t * pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm_arguments_t *arguments) { assert(arguments->block == NULL || PM_NODE_TYPE_P(arguments->block, PM_BLOCK_NODE)); assert(token->type == PM_TOKEN_KEYWORD_SUPER); - pm_forwarding_super_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_super_node_t); pm_block_node_t *block = NULL; if (arguments->block != NULL) { block = (pm_block_node_t *) arguments->block; } - *node = (pm_forwarding_super_node_t) { - .base = PM_NODE_INIT(parser, PM_FORWARDING_SUPER_NODE, 0, (block == NULL) ? PM_LOCATION_INIT_TOKEN(parser, token) : PM_LOCATION_INIT_TOKEN_NODE(parser, token, block)), - .block = block - }; - - return node; + return pm_forwarding_super_node_new( + parser->arena, + ++parser->node_id, + 0, + (block == NULL) ? PM_LOCATION_INIT_TOKEN(parser, token) : PM_LOCATION_INIT_TOKEN_NODE(parser, token, block), + block + ); } /** @@ -4119,18 +4106,17 @@ pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm */ static pm_hash_pattern_node_t * pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t); - - *node = (pm_hash_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .constant = NULL, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .elements = { 0 }, - .rest = NULL - }; - - return node; + return pm_hash_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + NULL, + ((pm_node_list_t) { 0 }), + NULL, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -4138,8 +4124,6 @@ pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening */ static pm_hash_pattern_node_t * pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *elements, pm_node_t *rest) { - pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t); - uint32_t start; uint32_t end; @@ -4157,14 +4141,17 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme end = PM_NODE_END(rest); } - *node = (pm_hash_pattern_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .constant = NULL, - .elements = { 0 }, - .rest = rest, - .opening_loc = { 0 }, - .closing_loc = { 0 } - }; + pm_hash_pattern_node_t *node = pm_hash_pattern_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NULL, + ((pm_node_list_t) { 0 }), + rest, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); pm_node_list_concat(parser->arena, &node->elements, elements); return node; @@ -4196,17 +4183,17 @@ pm_global_variable_write_name(pm_parser_t *parser, const pm_node_t *target) { static pm_global_variable_and_write_node_t * pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_global_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_and_write_node_t); - - *node = (pm_global_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_global_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4214,18 +4201,17 @@ pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_global_variable_operator_write_node_t * pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_global_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_operator_write_node_t); - - *node = (pm_global_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_global_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -4234,17 +4220,17 @@ pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *ta static pm_global_variable_or_write_node_t * pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_global_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_or_write_node_t); - - *node = (pm_global_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_global_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4252,14 +4238,13 @@ pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_global_variable_read_node_t * pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t); - - *node = (pm_global_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_global_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -4267,14 +4252,13 @@ pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) */ static pm_global_variable_read_node_t * pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name) { - pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t); - - *node = (pm_global_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_UNSET), - .name = name - }; - - return node; + return pm_global_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + name + ); } /** @@ -4282,18 +4266,16 @@ pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant */ static pm_global_variable_write_node_t * pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_global_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .name = pm_global_variable_write_name(parser, target), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_global_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + pm_global_variable_write_name(parser, target), + target->location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -4301,17 +4283,16 @@ pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, con */ static pm_global_variable_write_node_t * pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name, pm_node_t *value) { - pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t); - - *node = (pm_global_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, 0, PM_LOCATION_INIT_UNSET), - .name = name, - .name_loc = { 0 }, - .operator_loc = { 0 }, - .value = value - }; - - return node; + return pm_global_variable_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + name, + ((pm_location_t) { 0 }), + value, + ((pm_location_t) { 0 }) + ); } /** @@ -4320,16 +4301,16 @@ pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constan static pm_hash_node_t * pm_hash_node_create(pm_parser_t *parser, const pm_token_t *opening) { assert(opening != NULL); - pm_hash_node_t *node = PM_NODE_ALLOC(parser, pm_hash_node_t); - - *node = (pm_hash_node_t) { - .base = PM_NODE_INIT(parser, PM_HASH_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = { 0 }, - .elements = { 0 } - }; - return node; + return pm_hash_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -4371,7 +4352,6 @@ pm_if_node_create(pm_parser_t *parser, const pm_token_t *end_keyword ) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); uint32_t start = PM_TOKEN_START(parser, if_keyword); uint32_t end; @@ -4386,17 +4366,18 @@ pm_if_node_create(pm_parser_t *parser, end = PM_NODE_END(predicate); } - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .if_keyword_loc = TOK2LOC(parser, if_keyword), - .predicate = predicate, - .then_keyword_loc = NTOK2LOC(parser, then_keyword), - .statements = statements, - .subsequent = subsequent, - .end_keyword_loc = NTOK2LOC(parser, end_keyword) - }; - - return node; + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + TOK2LOC(parser, if_keyword), + predicate, + NTOK2LOC(parser, then_keyword), + statements, + subsequent, + NTOK2LOC(parser, end_keyword) + ); } /** @@ -4405,22 +4386,22 @@ pm_if_node_create(pm_parser_t *parser, static pm_if_node_t * pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *if_keyword, pm_node_t *predicate) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(statement, predicate)), - .if_keyword_loc = TOK2LOC(parser, if_keyword), - .predicate = predicate, - .then_keyword_loc = { 0 }, - .statements = statements, - .subsequent = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(statement, predicate), + TOK2LOC(parser, if_keyword), + predicate, + ((pm_location_t) { 0 }), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -4438,20 +4419,18 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to pm_statements_node_body_append(parser, else_statements, false_expression, true); pm_else_node_t *else_node = pm_else_node_create(parser, colon, else_statements, NULL); - pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t); - - *node = (pm_if_node_t) { - .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(predicate, false_expression)), - .if_keyword_loc = { 0 }, - .predicate = predicate, - .then_keyword_loc = TOK2LOC(parser, qmark), - .statements = if_statements, - .subsequent = UP(else_node), - .end_keyword_loc = { 0 } - }; - - return node; - + return pm_if_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(predicate, false_expression), + ((pm_location_t) { 0 }), + predicate, + TOK2LOC(parser, qmark), + if_statements, + UP(else_node), + ((pm_location_t) { 0 }) + ); } static inline void @@ -4471,14 +4450,13 @@ pm_else_node_end_keyword_loc_set(const pm_parser_t *parser, pm_else_node_t *node */ static pm_implicit_node_t * pm_implicit_node_create(pm_parser_t *parser, pm_node_t *value) { - pm_implicit_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_node_t); - - *node = (pm_implicit_node_t) { - .base = PM_NODE_INIT(parser, PM_IMPLICIT_NODE, 0, PM_LOCATION_INIT_NODE(value)), - .value = value - }; - - return node; + return pm_implicit_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(value), + value + ); } /** @@ -4488,13 +4466,12 @@ static pm_implicit_rest_node_t * pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_COMMA); - pm_implicit_rest_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_rest_node_t); - - *node = (pm_implicit_rest_node_t) { - .base = PM_NODE_INIT(parser, PM_IMPLICIT_REST_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_implicit_rest_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -4503,12 +4480,14 @@ pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) { static pm_integer_node_t * pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER); - pm_integer_node_t *node = PM_NODE_ALLOC(parser, pm_integer_node_t); - *node = (pm_integer_node_t) { - .base = PM_NODE_INIT(parser, PM_INTEGER_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .value = { 0 } - }; + pm_integer_node_t *node = pm_integer_node_new( + parser->arena, + ++parser->node_id, + base | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }) + ); pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; switch (base) { @@ -4532,17 +4511,17 @@ static pm_imaginary_node_t * pm_integer_node_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_integer_node_create(parser, base, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_integer_node_create(parser, base, &((pm_token_t) { .type = PM_TOKEN_INTEGER, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4553,12 +4532,14 @@ static pm_rational_node_t * pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_RATIONAL); - pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t); - *node = (pm_rational_node_t) { - .base = PM_NODE_INIT(parser, PM_RATIONAL_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numerator = { 0 }, - .denominator = { .value = 1, 0 } - }; + pm_rational_node_t *node = pm_rational_node_new( + parser->arena, + ++parser->node_id, + base | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_integer_t) { 0 }), + ((pm_integer_t) { .value = 1 }) + ); pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; switch (base) { @@ -4583,17 +4564,17 @@ static pm_imaginary_node_t * pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) { assert(token->type == PM_TOKEN_INTEGER_RATIONAL_IMAGINARY); - pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t); - *node = (pm_imaginary_node_t) { - .base = PM_NODE_INIT(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)), - .numeric = UP(pm_integer_node_rational_create(parser, base, &((pm_token_t) { + return pm_imaginary_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token), + UP(pm_integer_node_rational_create(parser, base, &((pm_token_t) { .type = PM_TOKEN_INTEGER_RATIONAL, .start = token->start, .end = token->end - 1 }))) - }; - - return node; + ); } /** @@ -4601,8 +4582,6 @@ pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t b */ static pm_in_node_t * pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t *statements, const pm_token_t *in_keyword, const pm_token_t *then_keyword) { - pm_in_node_t *node = PM_NODE_ALLOC(parser, pm_in_node_t); - uint32_t start = PM_TOKEN_START(parser, in_keyword); uint32_t end; @@ -4614,15 +4593,16 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t end = PM_NODE_END(pattern); } - *node = (pm_in_node_t) { - .base = PM_NODE_INIT(parser, PM_IN_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .pattern = pattern, - .statements = statements, - .in_loc = TOK2LOC(parser, in_keyword), - .then_loc = NTOK2LOC(parser, then_keyword) - }; - - return node; + return pm_in_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + pattern, + statements, + TOK2LOC(parser, in_keyword), + NTOK2LOC(parser, then_keyword) + ); } /** @@ -4631,17 +4611,17 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t static pm_instance_variable_and_write_node_t * pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_instance_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_and_write_node_t); - - *node = (pm_instance_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_instance_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4649,18 +4629,17 @@ pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_vari */ static pm_instance_variable_operator_write_node_t * pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_instance_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_operator_write_node_t); - - *node = (pm_instance_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) - }; - - return node; + return pm_instance_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1) + ); } /** @@ -4669,17 +4648,17 @@ pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance static pm_instance_variable_or_write_node_t * pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) { assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_instance_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_or_write_node_t); - - *node = (pm_instance_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name = target->name, - .name_loc = target->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - return node; + return pm_instance_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->name, + target->base.location, + TOK2LOC(parser, operator), + value + ); } /** @@ -4688,14 +4667,14 @@ pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_varia static pm_instance_variable_read_node_t * pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_INSTANCE_VARIABLE); - pm_instance_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_read_node_t); - - *node = (pm_instance_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - return node; + return pm_instance_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -4704,18 +4683,16 @@ pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *tok */ static pm_instance_variable_write_node_t * pm_instance_variable_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) { - pm_instance_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_instance_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_INSTANCE_VARIABLE_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(read_node, value)), - .name = read_node->name, - .name_loc = read_node->base.location, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_instance_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(read_node, value), + read_node->name, + read_node->base.location, + value, + TOK2LOC(parser, operator) + ); } /** @@ -4767,16 +4744,15 @@ pm_interpolated_node_append(pm_arena_t *arena, pm_node_t *node, pm_node_list_t * */ static pm_interpolated_regular_expression_node_t * pm_interpolated_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening) { - pm_interpolated_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_regular_expression_node_t); - - *node = (pm_interpolated_regular_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_REGULAR_EXPRESSION_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, opening)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, opening), - .parts = { 0 } - }; - - return node; + return pm_interpolated_regular_expression_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, opening), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, opening) + ); } static inline void @@ -4918,7 +4894,6 @@ pm_interpolated_string_node_append(pm_arena_t *arena, pm_interpolated_string_nod */ static pm_interpolated_string_node_t * pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) { - pm_interpolated_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_string_node_t); pm_node_flags_t flags = PM_NODE_FLAG_STATIC_LITERAL; switch (parser->frozen_string_literal) { @@ -4933,12 +4908,15 @@ pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *openin uint32_t start = opening == NULL ? 0 : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? 0 : PM_TOKEN_END(parser, closing); - *node = (pm_interpolated_string_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_STRING_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = NTOK2LOC(parser, closing), - .parts = { 0 } - }; + pm_interpolated_string_node_t *node = pm_interpolated_string_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, closing) + ); if (parts != NULL) { pm_node_t *part; @@ -4983,17 +4961,18 @@ pm_interpolated_symbol_node_closing_loc_set(const pm_parser_t *parser, pm_interp */ static pm_interpolated_symbol_node_t * pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) { - pm_interpolated_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_symbol_node_t); - uint32_t start = opening == NULL ? 0 : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? 0 : PM_TOKEN_END(parser, closing); - *node = (pm_interpolated_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .closing_loc = NTOK2LOC(parser, closing), - .parts = { 0 } - }; + pm_interpolated_symbol_node_t *node = pm_interpolated_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + NTOK2LOC(parser, closing) + ); if (parts != NULL) { pm_node_t *part; @@ -5010,16 +4989,15 @@ pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *openin */ static pm_interpolated_x_string_node_t * pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_interpolated_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_x_string_node_t); - - *node = (pm_interpolated_x_string_node_t) { - .base = PM_NODE_INIT(parser, PM_INTERPOLATED_X_STRING_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .parts = { 0 } - }; - - return node; + return pm_interpolated_x_string_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, closing) + ); } static inline void @@ -5039,13 +5017,12 @@ pm_interpolated_xstring_node_closing_set(const pm_parser_t *parser, pm_interpola */ static pm_it_local_variable_read_node_t * pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_it_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_it_local_variable_read_node_t); - - *node = (pm_it_local_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_IT_LOCAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - }; - - return node; + return pm_it_local_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name) + ); } /** @@ -5053,13 +5030,12 @@ pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *nam */ static pm_it_parameters_node_t * pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) { - pm_it_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_it_parameters_node_t); - - *node = (pm_it_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_IT_PARAMETERS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - }; - - return node; + return pm_it_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing) + ); } /** @@ -5067,14 +5043,13 @@ pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, con */ static pm_keyword_hash_node_t * pm_keyword_hash_node_create(pm_parser_t *parser) { - pm_keyword_hash_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_hash_node_t); - - *node = (pm_keyword_hash_node_t) { - .base = PM_NODE_INIT(parser, PM_KEYWORD_HASH_NODE, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS, PM_LOCATION_INIT_UNSET), - .elements = { 0 } - }; - - return node; + return pm_keyword_hash_node_new( + parser->arena, + ++parser->node_id, + PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -5100,15 +5075,14 @@ pm_keyword_hash_node_elements_append(pm_arena_t *arena, pm_keyword_hash_node_t * */ static pm_required_keyword_parameter_node_t * pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name) { - pm_required_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_keyword_parameter_node_t); - - *node = (pm_required_keyword_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REQUIRED_KEYWORD_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = pm_parser_constant_id_raw(parser, name->start, name->end - 1), - .name_loc = TOK2LOC(parser, name), - }; - - return node; + return pm_required_keyword_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_parser_constant_id_raw(parser, name->start, name->end - 1), + TOK2LOC(parser, name) + ); } /** @@ -5116,16 +5090,15 @@ pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t */ static pm_optional_keyword_parameter_node_t * pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, pm_node_t *value) { - pm_optional_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_keyword_parameter_node_t); - - *node = (pm_optional_keyword_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_OPTIONAL_KEYWORD_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, name, value)), - .name = pm_parser_constant_id_raw(parser, name->start, name->end - 1), - .name_loc = TOK2LOC(parser, name), - .value = value - }; - - return node; + return pm_optional_keyword_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, name, value), + pm_parser_constant_id_raw(parser, name->start, name->end - 1), + TOK2LOC(parser, name), + value + ); } /** @@ -5133,16 +5106,15 @@ pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t */ static pm_keyword_rest_parameter_node_t * pm_keyword_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) { - pm_keyword_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_rest_parameter_node_t); - - *node = (pm_keyword_rest_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_KEYWORD_REST_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_keyword_rest_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -5158,19 +5130,18 @@ pm_lambda_node_create( pm_node_t *parameters, pm_node_t *body ) { - pm_lambda_node_t *node = PM_NODE_ALLOC(parser, pm_lambda_node_t); - - *node = (pm_lambda_node_t) { - .base = PM_NODE_INIT(parser, PM_LAMBDA_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, closing)), - .locals = *locals, - .operator_loc = TOK2LOC(parser, operator), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing), - .parameters = parameters, - .body = body - }; - - return node; + return pm_lambda_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, closing), + *locals, + TOK2LOC(parser, operator), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing), + parameters, + body + ); } /** @@ -5180,18 +5151,18 @@ static pm_local_variable_and_write_node_t * pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_IT_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE)); assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL); - pm_local_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_and_write_node_t); - - *node = (pm_local_variable_and_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_AND_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_and_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + depth + ); } /** @@ -5199,19 +5170,18 @@ pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, */ static pm_local_variable_operator_write_node_t * pm_local_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { - pm_local_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_operator_write_node_t); - - *node = (pm_local_variable_operator_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .binary_operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .binary_operator = pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), - .depth = depth - }; - - return node; + return pm_local_variable_operator_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + pm_parser_constant_id_raw(parser, operator->start, operator->end - 1), + depth + ); } /** @@ -5221,18 +5191,18 @@ static pm_local_variable_or_write_node_t * pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) { assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_IT_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE)); assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL); - pm_local_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_or_write_node_t); - - *node = (pm_local_variable_or_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_OR_WRITE_NODE, 0, PM_LOCATION_INIT_NODES(target, value)), - .name_loc = target->location, - .operator_loc = TOK2LOC(parser, operator), - .value = value, - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_or_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(target, value), + target->location, + TOK2LOC(parser, operator), + value, + name, + depth + ); } /** @@ -5242,15 +5212,14 @@ static pm_local_variable_read_node_t * pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_token_t *name, pm_constant_id_t name_id, uint32_t depth, bool missing) { if (!missing) pm_locals_read(&pm_parser_scope_find(parser, depth)->locals, name_id); - pm_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_read_node_t); - - *node = (pm_local_variable_read_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .name = name_id, - .depth = depth - }; - - return node; + return pm_local_variable_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + name_id, + depth + ); } /** @@ -5277,19 +5246,17 @@ pm_local_variable_read_node_missing_create(pm_parser_t *parser, const pm_token_t */ static pm_local_variable_write_node_t * pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name, uint32_t depth, pm_node_t *value, const pm_location_t *name_loc, const pm_token_t *operator) { - pm_local_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_local_variable_write_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_WRITE_NODE, flags, ((pm_location_t) { .start = name_loc->start, .length = PM_NODE_END(value) - name_loc->start })), - .name = name, - .depth = depth, - .value = value, - .name_loc = *name_loc, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_local_variable_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + ((pm_location_t) { .start = name_loc->start, .length = PM_NODE_END(value) - name_loc->start }), + name, + depth, + *name_loc, + value, + TOK2LOC(parser, operator) + ); } /** @@ -5332,15 +5299,15 @@ pm_refute_numbered_parameter(pm_parser_t *parser, uint32_t start, uint32_t lengt static pm_local_variable_target_node_t * pm_local_variable_target_node_create(pm_parser_t *parser, const pm_location_t *location, pm_constant_id_t name, uint32_t depth) { pm_refute_numbered_parameter(parser, location->start, location->length); - pm_local_variable_target_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_target_node_t); - - *node = (pm_local_variable_target_node_t) { - .base = PM_NODE_INIT(parser, PM_LOCAL_VARIABLE_TARGET_NODE, 0, ((pm_location_t) { .start = location->start, .length = location->length })), - .name = name, - .depth = depth - }; - return node; + return pm_local_variable_target_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = location->start, .length = location->length }), + name, + depth + ); } /** @@ -5350,16 +5317,15 @@ static pm_match_predicate_node_t * pm_match_predicate_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) { pm_assert_value_expression(parser, value); - pm_match_predicate_node_t *node = PM_NODE_ALLOC(parser, pm_match_predicate_node_t); - - *node = (pm_match_predicate_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_PREDICATE_NODE, 0, PM_LOCATION_INIT_NODES(value, pattern)), - .value = value, - .pattern = pattern, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_match_predicate_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, pattern), + value, + pattern, + TOK2LOC(parser, operator) + ); } /** @@ -5369,16 +5335,15 @@ static pm_match_required_node_t * pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) { pm_assert_value_expression(parser, value); - pm_match_required_node_t *node = PM_NODE_ALLOC(parser, pm_match_required_node_t); - - *node = (pm_match_required_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_REQUIRED_NODE, 0, PM_LOCATION_INIT_NODES(value, pattern)), - .value = value, - .pattern = pattern, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_match_required_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(value, pattern), + value, + pattern, + TOK2LOC(parser, operator) + ); } /** @@ -5386,15 +5351,14 @@ pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t * */ static pm_match_write_node_t * pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) { - pm_match_write_node_t *node = PM_NODE_ALLOC(parser, pm_match_write_node_t); - - *node = (pm_match_write_node_t) { - .base = PM_NODE_INIT(parser, PM_MATCH_WRITE_NODE, 0, PM_LOCATION_INIT_NODE(call)), - .call = call, - .targets = { 0 } - }; - - return node; + return pm_match_write_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(call), + call, + ((pm_node_list_t) { 0 }) + ); } /** @@ -5402,19 +5366,18 @@ pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) { */ static pm_module_node_t * pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *module_keyword, pm_node_t *constant_path, const pm_token_t *name, pm_node_t *body, const pm_token_t *end_keyword) { - pm_module_node_t *node = PM_NODE_ALLOC(parser, pm_module_node_t); - - *node = (pm_module_node_t) { - .base = PM_NODE_INIT(parser, PM_MODULE_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, module_keyword, end_keyword)), - .locals = (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals), - .module_keyword_loc = TOK2LOC(parser, module_keyword), - .constant_path = constant_path, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword), - .name = pm_parser_constant_id_token(parser, name) - }; - - return node; + return pm_module_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, module_keyword, end_keyword), + (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals), + TOK2LOC(parser, module_keyword), + constant_path, + body, + TOK2LOC(parser, end_keyword), + pm_parser_constant_id_token(parser, name) + ); } /** @@ -5422,18 +5385,17 @@ pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const */ static pm_multi_target_node_t * pm_multi_target_node_create(pm_parser_t *parser) { - pm_multi_target_node_t *node = PM_NODE_ALLOC(parser, pm_multi_target_node_t); - - *node = (pm_multi_target_node_t) { - .base = PM_NODE_INIT(parser, PM_MULTI_TARGET_NODE, 0, PM_LOCATION_INIT_UNSET), - .lefts = { 0 }, - .rest = NULL, - .rights = { 0 }, - .lparen_loc = { 0 }, - .rparen_loc = { 0 } - }; - - return node; + return pm_multi_target_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }) + ); } /** @@ -5494,24 +5456,21 @@ pm_multi_target_node_closing_set(const pm_parser_t *parser, pm_multi_target_node */ static pm_multi_write_node_t * pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, const pm_token_t *operator, pm_node_t *value) { - pm_multi_write_node_t *node = PM_NODE_ALLOC(parser, pm_multi_write_node_t); - pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY); - - *node = (pm_multi_write_node_t) { - .base = PM_NODE_INIT(parser, PM_MULTI_WRITE_NODE, flags, PM_LOCATION_INIT_NODES(target, value)), - .lefts = target->lefts, - .rest = target->rest, - .rights = target->rights, - .lparen_loc = target->lparen_loc, - .rparen_loc = target->rparen_loc, - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - // The target is no longer necessary because we've reused its children. - // It is arena-allocated so no explicit free is needed. - - return node; + /* The target is no longer necessary because we have reused its children. It + * is arena-allocated so no explicit free is needed. */ + return pm_multi_write_node_new( + parser->arena, + ++parser->node_id, + pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY), + PM_LOCATION_INIT_NODES(target, value), + target->lefts, + target->rest, + target->rights, + target->lparen_loc, + target->rparen_loc, + TOK2LOC(parser, operator), + value + ); } /** @@ -5520,15 +5479,15 @@ pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, static pm_next_node_t * pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_NEXT); - pm_next_node_t *node = PM_NODE_ALLOC(parser, pm_next_node_t); - *node = (pm_next_node_t) { - .base = PM_NODE_INIT(parser, PM_NEXT_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .keyword_loc = TOK2LOC(parser, keyword), - .arguments = arguments - }; - - return node; + return pm_next_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + arguments, + TOK2LOC(parser, keyword) + ); } /** @@ -5537,13 +5496,13 @@ pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments static pm_nil_node_t * pm_nil_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_NIL); - pm_nil_node_t *node = PM_NODE_ALLOC(parser, pm_nil_node_t); - - *node = (pm_nil_node_t) { - .base = PM_NODE_INIT(parser, PM_NIL_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_nil_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -5553,15 +5512,15 @@ static pm_no_block_parameter_node_t * pm_no_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) { assert(operator->type == PM_TOKEN_AMPERSAND || operator->type == PM_TOKEN_UAMPERSAND); assert(keyword->type == PM_TOKEN_KEYWORD_NIL); - pm_no_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_block_parameter_node_t); - - *node = (pm_no_block_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_NO_BLOCK_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, keyword)), - .operator_loc = TOK2LOC(parser, operator), - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_no_block_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, keyword), + TOK2LOC(parser, operator), + TOK2LOC(parser, keyword) + ); } /** @@ -5571,15 +5530,15 @@ static pm_no_keywords_parameter_node_t * pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) { assert(operator->type == PM_TOKEN_USTAR_STAR || operator->type == PM_TOKEN_STAR_STAR); assert(keyword->type == PM_TOKEN_KEYWORD_NIL); - pm_no_keywords_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_keywords_parameter_node_t); - - *node = (pm_no_keywords_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_NO_KEYWORDS_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, keyword)), - .operator_loc = TOK2LOC(parser, operator), - .keyword_loc = TOK2LOC(parser, keyword) - }; - return node; + return pm_no_keywords_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, keyword), + TOK2LOC(parser, operator), + TOK2LOC(parser, keyword) + ); } /** @@ -5587,14 +5546,13 @@ pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *oper */ static pm_numbered_parameters_node_t * pm_numbered_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing, uint8_t maximum) { - pm_numbered_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_parameters_node_t); - - *node = (pm_numbered_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_NUMBERED_PARAMETERS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .maximum = maximum - }; - - return node; + return pm_numbered_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + maximum + ); } /** @@ -5652,14 +5610,14 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to static pm_numbered_reference_read_node_t * pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) { assert(name->type == PM_TOKEN_NUMBERED_REFERENCE); - pm_numbered_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_reference_read_node_t); - - *node = (pm_numbered_reference_read_node_t) { - .base = PM_NODE_INIT(parser, PM_NUMBERED_REFERENCE_READ_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, name)), - .number = pm_numbered_reference_read_node_number(parser, name) - }; - return node; + return pm_numbered_reference_read_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, name), + pm_numbered_reference_read_node_number(parser, name) + ); } /** @@ -5667,17 +5625,16 @@ pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *na */ static pm_optional_parameter_node_t * pm_optional_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator, pm_node_t *value) { - pm_optional_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_parameter_node_t); - - *node = (pm_optional_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_OPTIONAL_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, name, value)), - .name = pm_parser_constant_id_token(parser, name), - .name_loc = TOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator), - .value = value - }; - - return node; + return pm_optional_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, name, value), + pm_parser_constant_id_token(parser, name), + TOK2LOC(parser, name), + TOK2LOC(parser, operator), + value + ); } /** @@ -5687,16 +5644,15 @@ static pm_or_node_t * pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); - pm_or_node_t *node = PM_NODE_ALLOC(parser, pm_or_node_t); - - *node = (pm_or_node_t) { - .base = PM_NODE_INIT(parser, PM_OR_NODE, 0, PM_LOCATION_INIT_NODES(left, right)), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_or_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(left, right), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -5704,20 +5660,19 @@ pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operat */ static pm_parameters_node_t * pm_parameters_node_create(pm_parser_t *parser) { - pm_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_parameters_node_t); - - *node = (pm_parameters_node_t) { - .base = PM_NODE_INIT(parser, PM_PARAMETERS_NODE, 0, PM_LOCATION_INIT_UNSET), - .rest = NULL, - .keyword_rest = NULL, - .block = NULL, - .requireds = { 0 }, - .optionals = { 0 }, - .posts = { 0 }, - .keywords = { 0 } - }; - - return node; + return pm_parameters_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }), + ((pm_node_list_t) { 0 }), + NULL, + ((pm_node_list_t) { 0 }), + ((pm_node_list_t) { 0 }), + NULL, + NULL + ); } /** @@ -5804,15 +5759,14 @@ pm_parameters_node_block_set(pm_parameters_node_t *params, pm_node_t *param) { */ static pm_program_node_t * pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_statements_node_t *statements) { - pm_program_node_t *node = PM_NODE_ALLOC(parser, pm_program_node_t); - - *node = (pm_program_node_t) { - .base = PM_NODE_INIT(parser, PM_PROGRAM_NODE, 0, PM_LOCATION_INIT_NODE(statements)), - .locals = *locals, - .statements = statements - }; - - return node; + return pm_program_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODE(statements), + *locals, + statements + ); } /** @@ -5820,16 +5774,15 @@ pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_st */ static pm_parentheses_node_t * pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_node_t *body, const pm_token_t *closing, pm_node_flags_t flags) { - pm_parentheses_node_t *node = PM_NODE_ALLOC(parser, pm_parentheses_node_t); - - *node = (pm_parentheses_node_t) { - .base = PM_NODE_INIT(parser, PM_PARENTHESES_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .body = body, - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_parentheses_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + body, + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5837,17 +5790,16 @@ pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_no */ static pm_pinned_expression_node_t * pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *operator, const pm_token_t *lparen, const pm_token_t *rparen) { - pm_pinned_expression_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_expression_node_t); - - *node = (pm_pinned_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_PINNED_EXPRESSION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, operator, rparen)), - .expression = expression, - .operator_loc = TOK2LOC(parser, operator), - .lparen_loc = TOK2LOC(parser, lparen), - .rparen_loc = TOK2LOC(parser, rparen) - }; - - return node; + return pm_pinned_expression_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, operator, rparen), + expression, + TOK2LOC(parser, operator), + TOK2LOC(parser, lparen), + TOK2LOC(parser, rparen) + ); } /** @@ -5855,15 +5807,14 @@ pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, con */ static pm_pinned_variable_node_t * pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) { - pm_pinned_variable_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_variable_node_t); - - *node = (pm_pinned_variable_node_t) { - .base = PM_NODE_INIT(parser, PM_PINNED_VARIABLE_NODE, 0, PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable)), - .variable = variable, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_pinned_variable_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN_NODE(parser, operator, variable), + variable, + TOK2LOC(parser, operator) + ); } /** @@ -5871,17 +5822,16 @@ pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, */ static pm_post_execution_node_t * pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_post_execution_node_t *node = PM_NODE_ALLOC(parser, pm_post_execution_node_t); - - *node = (pm_post_execution_node_t) { - .base = PM_NODE_INIT(parser, PM_POST_EXECUTION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .statements = statements, - .keyword_loc = TOK2LOC(parser, keyword), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_post_execution_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + statements, + TOK2LOC(parser, keyword), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5889,17 +5839,16 @@ pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, co */ static pm_pre_execution_node_t * pm_pre_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) { - pm_pre_execution_node_t *node = PM_NODE_ALLOC(parser, pm_pre_execution_node_t); - - *node = (pm_pre_execution_node_t) { - .base = PM_NODE_INIT(parser, PM_PRE_EXECUTION_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .statements = statements, - .keyword_loc = TOK2LOC(parser, keyword), - .opening_loc = TOK2LOC(parser, opening), - .closing_loc = TOK2LOC(parser, closing) - }; - - return node; + return pm_pre_execution_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + statements, + TOK2LOC(parser, keyword), + TOK2LOC(parser, opening), + TOK2LOC(parser, closing) + ); } /** @@ -5909,8 +5858,6 @@ static pm_range_node_t * pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) { pm_assert_value_expression(parser, left); pm_assert_value_expression(parser, right); - - pm_range_node_t *node = PM_NODE_ALLOC(parser, pm_range_node_t); pm_node_flags_t flags = 0; // Indicate that this node is an exclusive range if the operator is `...`. @@ -5931,14 +5878,15 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope uint32_t start = left == NULL ? PM_TOKEN_START(parser, operator) : PM_NODE_START(left); uint32_t end = right == NULL ? PM_TOKEN_END(parser, operator) : PM_NODE_END(right); - *node = (pm_range_node_t) { - .base = PM_NODE_INIT(parser, PM_RANGE_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .left = left, - .right = right, - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_range_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + left, + right, + TOK2LOC(parser, operator) + ); } /** @@ -5947,13 +5895,13 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope static pm_redo_node_t * pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_REDO); - pm_redo_node_t *node = PM_NODE_ALLOC(parser, pm_redo_node_t); - *node = (pm_redo_node_t) { - .base = PM_NODE_INIT(parser, PM_REDO_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_redo_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -5962,18 +5910,16 @@ pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_regular_expression_node_t * pm_regular_expression_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *unescaped) { - pm_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_regular_expression_node_t); - pm_node_flags_t flags = pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL; - - *node = (pm_regular_expression_node_t) { - .base = PM_NODE_INIT(parser, PM_REGULAR_EXPRESSION_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = TOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_regular_expression_node_new( + parser->arena, + ++parser->node_id, + pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + TOK2LOC(parser, content), + TOK2LOC(parser, closing), + *unescaped + ); } /** @@ -5989,14 +5935,13 @@ pm_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening */ static pm_required_parameter_node_t * pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) { - pm_required_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_parameter_node_t); - - *node = (pm_required_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REQUIRED_PARAMETER_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .name = pm_parser_constant_id_token(parser, token) - }; - - return node; + return pm_required_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + pm_parser_constant_id_token(parser, token) + ); } /** @@ -6004,16 +5949,15 @@ pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) */ static pm_rescue_modifier_node_t * pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *keyword, pm_node_t *rescue_expression) { - pm_rescue_modifier_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_modifier_node_t); - - *node = (pm_rescue_modifier_node_t) { - .base = PM_NODE_INIT(parser, PM_RESCUE_MODIFIER_NODE, 0, PM_LOCATION_INIT_NODES(expression, rescue_expression)), - .expression = expression, - .keyword_loc = TOK2LOC(parser, keyword), - .rescue_expression = rescue_expression - }; - - return node; + return pm_rescue_modifier_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_NODES(expression, rescue_expression), + expression, + TOK2LOC(parser, keyword), + rescue_expression + ); } /** @@ -6021,20 +5965,19 @@ pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const */ static pm_rescue_node_t * pm_rescue_node_create(pm_parser_t *parser, const pm_token_t *keyword) { - pm_rescue_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_node_t); - - *node = (pm_rescue_node_t) { - .base = PM_NODE_INIT(parser, PM_RESCUE_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, keyword)), - .keyword_loc = TOK2LOC(parser, keyword), - .operator_loc = { 0 }, - .then_keyword_loc = { 0 }, - .reference = NULL, - .statements = NULL, - .subsequent = NULL, - .exceptions = { 0 } - }; - - return node; + return pm_rescue_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, keyword), + TOK2LOC(parser, keyword), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + NULL, + ((pm_location_t) { 0 }), + NULL, + NULL + ); } static inline void @@ -6085,16 +6028,15 @@ pm_rescue_node_exceptions_append(pm_arena_t *arena, pm_rescue_node_t *node, pm_n */ static pm_rest_parameter_node_t * pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) { - pm_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_rest_parameter_node_t); - - *node = (pm_rest_parameter_node_t) { - .base = PM_NODE_INIT(parser, PM_REST_PARAMETER_NODE, 0, (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name)), - .name = name == NULL ? 0 : pm_parser_constant_id_token(parser, name), - .name_loc = NTOK2LOC(parser, name), - .operator_loc = TOK2LOC(parser, operator) - }; - - return node; + return pm_rest_parameter_node_new( + parser->arena, + ++parser->node_id, + 0, + (name == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKENS(parser, operator, name), + name == NULL ? 0 : pm_parser_constant_id_token(parser, name), + NTOK2LOC(parser, name), + TOK2LOC(parser, operator) + ); } /** @@ -6103,13 +6045,13 @@ pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, c static pm_retry_node_t * pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_RETRY); - pm_retry_node_t *node = PM_NODE_ALLOC(parser, pm_retry_node_t); - - *node = (pm_retry_node_t) { - .base = PM_NODE_INIT(parser, PM_RETRY_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_retry_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6117,15 +6059,14 @@ pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_return_node_t * pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) { - pm_return_node_t *node = PM_NODE_ALLOC(parser, pm_return_node_t); - - *node = (pm_return_node_t) { - .base = PM_NODE_INIT(parser, PM_RETURN_NODE, 0, (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments)), - .keyword_loc = TOK2LOC(parser, keyword), - .arguments = arguments - }; - - return node; + return pm_return_node_new( + parser->arena, + ++parser->node_id, + 0, + (arguments == NULL) ? PM_LOCATION_INIT_TOKEN(parser, keyword) : PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, arguments), + TOK2LOC(parser, keyword), + arguments + ); } /** @@ -6134,13 +6075,13 @@ pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argumen static pm_self_node_t * pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_SELF); - pm_self_node_t *node = PM_NODE_ALLOC(parser, pm_self_node_t); - *node = (pm_self_node_t) { - .base = PM_NODE_INIT(parser, PM_SELF_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_self_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6148,14 +6089,13 @@ pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_shareable_constant_node_t * pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shareable_constant_value_t value) { - pm_shareable_constant_node_t *node = PM_NODE_ALLOC(parser, pm_shareable_constant_node_t); - - *node = (pm_shareable_constant_node_t) { - .base = PM_NODE_INIT(parser, PM_SHAREABLE_CONSTANT_NODE, (pm_node_flags_t) value, PM_LOCATION_INIT_NODE(write)), - .write = write - }; - - return node; + return pm_shareable_constant_node_new( + parser->arena, + ++parser->node_id, + (pm_node_flags_t) value, + PM_LOCATION_INIT_NODE(write), + write + ); } /** @@ -6163,19 +6103,18 @@ pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shar */ static pm_singleton_class_node_t * pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, const pm_token_t *operator, pm_node_t *expression, pm_node_t *body, const pm_token_t *end_keyword) { - pm_singleton_class_node_t *node = PM_NODE_ALLOC(parser, pm_singleton_class_node_t); - - *node = (pm_singleton_class_node_t) { - .base = PM_NODE_INIT(parser, PM_SINGLETON_CLASS_NODE, 0, PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword)), - .locals = *locals, - .class_keyword_loc = TOK2LOC(parser, class_keyword), - .operator_loc = TOK2LOC(parser, operator), - .expression = expression, - .body = body, - .end_keyword_loc = TOK2LOC(parser, end_keyword) - }; - - return node; + return pm_singleton_class_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKENS(parser, class_keyword, end_keyword), + *locals, + TOK2LOC(parser, class_keyword), + TOK2LOC(parser, operator), + expression, + body, + TOK2LOC(parser, end_keyword) + ); } /** @@ -6184,13 +6123,13 @@ pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *local static pm_source_encoding_node_t * pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD___ENCODING__); - pm_source_encoding_node_t *node = PM_NODE_ALLOC(parser, pm_source_encoding_node_t); - *node = (pm_source_encoding_node_t) { - .base = PM_NODE_INIT(parser, PM_SOURCE_ENCODING_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - - return node; + return pm_source_encoding_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6198,7 +6137,6 @@ pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_source_file_node_t* pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) { - pm_source_file_node_t *node = PM_NODE_ALLOC(parser, pm_source_file_node_t); assert(file_keyword->type == PM_TOKEN_KEYWORD___FILE__); pm_node_flags_t flags = 0; @@ -6212,12 +6150,13 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) break; } - *node = (pm_source_file_node_t) { - .base = PM_NODE_INIT(parser, PM_SOURCE_FILE_NODE, flags, PM_LOCATION_INIT_TOKEN(parser, file_keyword)), - .filepath = parser->filepath - }; - - return node; + return pm_source_file_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKEN(parser, file_keyword), + parser->filepath + ); } /** @@ -6226,13 +6165,13 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) static pm_source_line_node_t * pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD___LINE__); - pm_source_line_node_t *node = PM_NODE_ALLOC(parser, pm_source_line_node_t); - - *node = (pm_source_line_node_t) { - .base = PM_NODE_INIT(parser, PM_SOURCE_LINE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_source_line_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6240,15 +6179,14 @@ pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_splat_node_t * pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) { - pm_splat_node_t *node = PM_NODE_ALLOC(parser, pm_splat_node_t); - - *node = (pm_splat_node_t) { - .base = PM_NODE_INIT(parser, PM_SPLAT_NODE, 0, (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression)), - .operator_loc = TOK2LOC(parser, operator), - .expression = expression - }; - - return node; + return pm_splat_node_new( + parser->arena, + ++parser->node_id, + 0, + (expression == NULL) ? PM_LOCATION_INIT_TOKEN(parser, operator) : PM_LOCATION_INIT_TOKEN_NODE(parser, operator, expression), + TOK2LOC(parser, operator), + expression + ); } /** @@ -6256,14 +6194,13 @@ pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t */ static pm_statements_node_t * pm_statements_node_create(pm_parser_t *parser) { - pm_statements_node_t *node = PM_NODE_ALLOC(parser, pm_statements_node_t); - - *node = (pm_statements_node_t) { - .base = PM_NODE_INIT(parser, PM_STATEMENTS_NODE, 0, PM_LOCATION_INIT_UNSET), - .body = { 0 } - }; - - return node; + return pm_statements_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_node_list_t) { 0 }) + ); } /** @@ -6331,7 +6268,6 @@ pm_statements_node_body_prepend(pm_arena_t *arena, pm_statements_node_t *node, p */ static inline pm_string_node_t * pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *string) { - pm_string_node_t *node = PM_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -6346,15 +6282,16 @@ pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, uint32_t start = PM_TOKEN_START(parser, opening == NULL ? content : opening); uint32_t end = PM_TOKEN_END(parser, closing == NULL ? content : closing); - *node = (pm_string_node_t) { - .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = NTOK2LOC(parser, closing), - .unescaped = *string - }; - - return node; + return pm_string_node_new( + parser->arena, + ++parser->node_id, + flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + TOK2LOC(parser, content), + NTOK2LOC(parser, closing), + *string + ); } /** @@ -6382,21 +6319,21 @@ pm_string_node_create_current_string(pm_parser_t *parser, const pm_token_t *open static pm_super_node_t * pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_t *arguments) { assert(keyword->type == PM_TOKEN_KEYWORD_SUPER); - pm_super_node_t *node = PM_NODE_ALLOC(parser, pm_super_node_t); const pm_location_t *end = pm_arguments_end(arguments); assert(end != NULL && "unreachable"); - *node = (pm_super_node_t) { - .base = PM_NODE_INIT(parser, PM_SUPER_NODE, 0, ((pm_location_t) { .start = PM_TOKEN_START(parser, keyword), .length = PM_LOCATION_END(end) - PM_TOKEN_START(parser, keyword) })), - .keyword_loc = TOK2LOC(parser, keyword), - .lparen_loc = arguments->opening_loc, - .arguments = arguments->arguments, - .rparen_loc = arguments->closing_loc, - .block = arguments->block - }; - - return node; + return pm_super_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = PM_TOKEN_START(parser, keyword), .length = PM_LOCATION_END(end) - PM_TOKEN_START(parser, keyword) }), + TOK2LOC(parser, keyword), + arguments->opening_loc, + arguments->arguments, + arguments->closing_loc, + arguments->block + ); } /** @@ -6615,20 +6552,19 @@ parse_and_validate_regular_expression_encoding(pm_parser_t *parser, const pm_str */ static pm_symbol_node_t * pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing, const pm_string_t *unescaped, pm_node_flags_t flags) { - pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t); - uint32_t start = opening == NULL ? PM_TOKEN_START(parser, value) : PM_TOKEN_START(parser, opening); uint32_t end = closing == NULL ? PM_TOKEN_END(parser, value) : PM_TOKEN_END(parser, closing); - *node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | flags, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .opening_loc = NTOK2LOC(parser, opening), - .value_loc = NTOK2LOC(parser, value), - .closing_loc = NTOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL | flags, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + NTOK2LOC(parser, opening), + NTOK2LOC(parser, value), + NTOK2LOC(parser, closing), + *unescaped + ); } /** @@ -6672,13 +6608,16 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_symbol_node_t * pm_symbol_node_synthesized_create(pm_parser_t *parser, const char *content) { - pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t); - - *node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, PM_LOCATION_INIT_UNSET), - .value_loc = { 0 }, - .unescaped = { 0 } - }; + pm_symbol_node_t *node = pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, + PM_LOCATION_INIT_UNSET, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_string_t) { 0 }) + ); pm_string_constant_init(&node->unescaped, content, strlen(content)); return node; @@ -6718,15 +6657,16 @@ pm_symbol_node_label_p(const pm_parser_t *parser, const pm_node_t *node) { */ static pm_symbol_node_t * pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_token_t *opening, const pm_token_t *closing) { - pm_symbol_node_t *new_node = PM_NODE_ALLOC(parser, pm_symbol_node_t); - - *new_node = (pm_symbol_node_t) { - .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .value_loc = node->content_loc, - .closing_loc = TOK2LOC(parser, closing), - .unescaped = node->unescaped - }; + pm_symbol_node_t *new_node = pm_symbol_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + node->content_loc, + TOK2LOC(parser, closing), + node->unescaped + ); pm_token_t content = { .type = PM_TOKEN_IDENTIFIER, @@ -6736,8 +6676,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_node_flag_set(UP(new_node), parse_symbol_encoding(parser, &content, &node->unescaped, true)); - // The old node is arena-allocated so no explicit free is needed. - + /* The old node is arena-allocated so no explicit free is needed. */ return new_node; } @@ -6746,7 +6685,6 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const */ static pm_string_node_t * pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { - pm_string_node_t *new_node = PM_NODE_ALLOC(parser, pm_string_node_t); pm_node_flags_t flags = 0; switch (parser->frozen_string_literal) { @@ -6758,16 +6696,18 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { break; } - *new_node = (pm_string_node_t) { - .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, PM_LOCATION_INIT_NODE(node)), - .opening_loc = node->opening_loc, - .content_loc = node->value_loc, - .closing_loc = node->closing_loc, - .unescaped = node->unescaped - }; - - // The old node is arena-allocated so no explicit free is needed. + pm_string_node_t *new_node = pm_string_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODE(node), + node->opening_loc, + node->value_loc, + node->closing_loc, + node->unescaped + ); + /* The old node is arena-allocated so no explicit free is needed. */ return new_node; } @@ -6777,13 +6717,13 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) { static pm_true_node_t * pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_TRUE); - pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t); - - *node = (pm_true_node_t) { - .base = PM_NODE_INIT(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_TOKEN(parser, token)) - }; - return node; + return pm_true_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_TOKEN(parser, token) + ); } /** @@ -6791,13 +6731,12 @@ pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) { */ static pm_true_node_t * pm_true_node_synthesized_create(pm_parser_t *parser) { - pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t); - - *node = (pm_true_node_t) { - .base = PM_NODE_INIT(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, PM_LOCATION_INIT_UNSET) - }; - - return node; + return pm_true_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_STATIC_LITERAL, + PM_LOCATION_INIT_UNSET + ); } /** @@ -6806,15 +6745,15 @@ pm_true_node_synthesized_create(pm_parser_t *parser) { static pm_undef_node_t * pm_undef_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_KEYWORD_UNDEF); - pm_undef_node_t *node = PM_NODE_ALLOC(parser, pm_undef_node_t); - *node = (pm_undef_node_t) { - .base = PM_NODE_INIT(parser, PM_UNDEF_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, token)), - .keyword_loc = TOK2LOC(parser, token), - .names = { 0 } - }; - - return node; + return pm_undef_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, token), + ((pm_node_list_t) { 0 }), + TOK2LOC(parser, token) + ); } /** @@ -6832,21 +6771,20 @@ pm_undef_node_append(pm_arena_t *arena, pm_undef_node_t *node, pm_node_t *name) static pm_unless_node_t * pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - - pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t); pm_node_t *end = statements == NULL ? predicate : UP(statements); - *node = (pm_unless_node_t) { - .base = PM_NODE_INIT(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, end)), - .keyword_loc = TOK2LOC(parser, keyword), - .predicate = predicate, - .then_keyword_loc = NTOK2LOC(parser, then_keyword), - .statements = statements, - .else_clause = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_unless_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_TOKEN_NODE(parser, keyword, end), + TOK2LOC(parser, keyword), + predicate, + NTOK2LOC(parser, then_keyword), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } /** @@ -6855,22 +6793,22 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t static pm_unless_node_t * pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *unless_keyword, pm_node_t *predicate) { pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t); pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); - *node = (pm_unless_node_t) { - .base = PM_NODE_INIT(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, PM_LOCATION_INIT_NODES(statement, predicate)), - .keyword_loc = TOK2LOC(parser, unless_keyword), - .predicate = predicate, - .then_keyword_loc = { 0 }, - .statements = statements, - .else_clause = NULL, - .end_keyword_loc = { 0 } - }; - - return node; + return pm_unless_node_new( + parser->arena, + ++parser->node_id, + PM_NODE_FLAG_NEWLINE, + PM_LOCATION_INIT_NODES(statement, predicate), + TOK2LOC(parser, unless_keyword), + predicate, + ((pm_location_t) { 0 }), + statements, + NULL, + ((pm_location_t) { 0 }) + ); } static inline void @@ -6907,19 +6845,19 @@ pm_loop_modifier_block_exits(pm_parser_t *parser, pm_statements_node_t *statemen */ static pm_until_node_t * pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *do_keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - *node = (pm_until_node_t) { - .base = PM_NODE_INIT(parser, PM_UNTIL_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .closing_loc = TOK2LOC(parser, closing), - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_until_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + TOK2LOC(parser, keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, closing), + predicate, + statements + ); } /** @@ -6927,20 +6865,20 @@ pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to */ static pm_until_node_t * pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); pm_loop_modifier_block_exits(parser, statements); - *node = (pm_until_node_t) { - .base = PM_NODE_INIT(parser, PM_UNTIL_NODE, flags, PM_LOCATION_INIT_NODES(statements, predicate)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_until_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODES(statements, predicate), + TOK2LOC(parser, keyword), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -6948,17 +6886,16 @@ pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm */ static pm_when_node_t * pm_when_node_create(pm_parser_t *parser, const pm_token_t *keyword) { - pm_when_node_t *node = PM_NODE_ALLOC(parser, pm_when_node_t); - - *node = (pm_when_node_t) { - .base = PM_NODE_INIT(parser, PM_WHEN_NODE, 0, PM_LOCATION_INIT_TOKEN(parser, keyword)), - .keyword_loc = TOK2LOC(parser, keyword), - .statements = NULL, - .then_keyword_loc = { 0 }, - .conditions = { 0 } - }; - - return node; + return pm_when_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_TOKEN(parser, keyword), + TOK2LOC(parser, keyword), + ((pm_node_list_t) { 0 }), + ((pm_location_t) { 0 }), + NULL + ); } /** @@ -6996,19 +6933,19 @@ pm_when_node_statements_set(pm_when_node_t *node, pm_statements_node_t *statemen */ static pm_while_node_t * pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *do_keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, flags, PM_LOCATION_INIT_TOKENS(parser, keyword, closing)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = NTOK2LOC(parser, do_keyword), - .closing_loc = TOK2LOC(parser, closing), - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_TOKENS(parser, keyword, closing), + TOK2LOC(parser, keyword), + NTOK2LOC(parser, do_keyword), + TOK2LOC(parser, closing), + predicate, + statements + ); } /** @@ -7016,20 +6953,20 @@ pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to */ static pm_while_node_t * pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) { - pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL); pm_loop_modifier_block_exits(parser, statements); - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, flags, PM_LOCATION_INIT_NODES(statements, predicate)), - .keyword_loc = TOK2LOC(parser, keyword), - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + flags, + PM_LOCATION_INIT_NODES(statements, predicate), + TOK2LOC(parser, keyword), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -7037,18 +6974,17 @@ pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm */ static pm_while_node_t * pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_statements_node_t *statements) { - pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t); - - *node = (pm_while_node_t) { - .base = PM_NODE_INIT(parser, PM_WHILE_NODE, 0, PM_LOCATION_INIT_UNSET), - .keyword_loc = { 0 }, - .do_keyword_loc = { 0 }, - .closing_loc = { 0 }, - .predicate = predicate, - .statements = statements - }; - - return node; + return pm_while_node_new( + parser->arena, + ++parser->node_id, + 0, + PM_LOCATION_INIT_UNSET, + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + ((pm_location_t) { 0 }), + predicate, + statements + ); } /** @@ -7057,17 +6993,16 @@ pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_s */ static pm_x_string_node_t * pm_xstring_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *unescaped) { - pm_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_x_string_node_t); - - *node = (pm_x_string_node_t) { - .base = PM_NODE_INIT(parser, PM_X_STRING_NODE, PM_STRING_FLAGS_FROZEN, PM_LOCATION_INIT_TOKENS(parser, opening, closing)), - .opening_loc = TOK2LOC(parser, opening), - .content_loc = TOK2LOC(parser, content), - .closing_loc = TOK2LOC(parser, closing), - .unescaped = *unescaped - }; - - return node; + return pm_x_string_node_new( + parser->arena, + ++parser->node_id, + PM_STRING_FLAGS_FROZEN, + PM_LOCATION_INIT_TOKENS(parser, opening, closing), + TOK2LOC(parser, opening), + TOK2LOC(parser, content), + TOK2LOC(parser, closing), + *unescaped + ); } /** @@ -7083,8 +7018,6 @@ pm_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_ */ static pm_yield_node_t * pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_location_t *lparen_loc, pm_arguments_node_t *arguments, const pm_location_t *rparen_loc) { - pm_yield_node_t *node = PM_NODE_ALLOC(parser, pm_yield_node_t); - uint32_t start = PM_TOKEN_START(parser, keyword); uint32_t end; @@ -7098,15 +7031,16 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo end = PM_TOKEN_END(parser, keyword); } - *node = (pm_yield_node_t) { - .base = PM_NODE_INIT(parser, PM_YIELD_NODE, 0, ((pm_location_t) { .start = start, .length = U32(end - start) })), - .keyword_loc = TOK2LOC(parser, keyword), - .lparen_loc = *lparen_loc, - .arguments = arguments, - .rparen_loc = *rparen_loc - }; - - return node; + return pm_yield_node_new( + parser->arena, + ++parser->node_id, + 0, + ((pm_location_t) { .start = start, .length = U32(end - start) }), + TOK2LOC(parser, keyword), + *lparen_loc, + arguments, + *rparen_loc + ); } /** diff --git a/templates/include/prism/node_new.h.erb b/templates/include/prism/node_new.h.erb new file mode 100644 index 0000000000..56c214e006 --- /dev/null +++ b/templates/include/prism/node_new.h.erb @@ -0,0 +1,42 @@ +/** + * @file node_new.h + * + * Static inline functions for allocating and initializing AST nodes. + * + * -- + */ +#ifndef PRISM_NODE_NEW_H +#define PRISM_NODE_NEW_H + +#include "prism/node.h" + +<%- nodes.each do |node| -%> +<%- params = node.fields.map(&:c_param) -%> +/** + * Allocate and initialize a new <%= node.name %> node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. +<%- node.fields.each do |field| -%> + * @param <%= field.name %> <%= field.comment ? Prism::Template::Doxygen.verbatim(field.comment.lines.first.strip) : "The #{field.name} field." %> +<%- end -%> + * @return The newly allocated and initialized node. + */ +static inline pm_<%= node.human %>_t * +pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { + pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); + + *node = (pm_<%= node.human %>_t) { + .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %> +<%- node.fields.each_with_index do |field, index| -%> + .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %> +<%- end -%> + }; + + return node; +} + +<%- end -%> +#endif diff --git a/templates/template.rb b/templates/template.rb index e571c58bf2..70fa17c83d 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -105,6 +105,11 @@ def should_be_serialized? # Some node fields can be specialized if they point to a specific kind of # node and not just a generic node. class NodeKindField < Field + # The C type to use for this field as a function parameter. + def c_param + "struct #{c_type} *#{name}" + end + def initialize(kind:, **options) @kind = kind super(**options) @@ -210,6 +215,10 @@ def check_field_kind # This represents a field on a node that is a list of nodes. We pass them as # references and store them directly on the struct. class NodeListField < NodeKindField + def c_param + "pm_node_list_t #{name}" + end + def element_rbs_class if specific_kind "#{specific_kind}" @@ -250,6 +259,10 @@ def check_field_kind # This represents a field on a node that is the ID of a string interned # through the parser's constant pool. class ConstantField < Field + def c_param + "pm_constant_id_t #{name}" + end + def rbs_class "Symbol" end @@ -266,6 +279,10 @@ def java_type # This represents a field on a node that is the ID of a string interned # through the parser's constant pool and can be optionally null. class OptionalConstantField < Field + def c_param + "pm_constant_id_t #{name}" + end + def rbs_class "Symbol?" end @@ -282,6 +299,10 @@ def java_type # This represents a field on a node that is a list of IDs that are associated # with strings interned through the parser's constant pool. class ConstantListField < Field + def c_param + "pm_constant_id_list_t #{name}" + end + def rbs_class "Array[Symbol]" end @@ -297,6 +318,10 @@ def java_type # This represents a field on a node that is a string. class StringField < Field + def c_param + "pm_string_t #{name}" + end + def rbs_class "String" end @@ -312,6 +337,10 @@ def java_type # This represents a field on a node that is a location. class LocationField < Field + def c_param + "pm_location_t #{name}" + end + def semantic_field? false end @@ -331,6 +360,10 @@ def java_type # This represents a field on a node that is a location that is optional. class OptionalLocationField < Field + def c_param + "pm_location_t #{name}" + end + def semantic_field? false end @@ -350,6 +383,10 @@ def java_type # This represents an integer field. class UInt8Field < Field + def c_param + "uint8_t #{name}" + end + def rbs_class "Integer" end @@ -365,6 +402,10 @@ def java_type # This represents an integer field. class UInt32Field < Field + def c_param + "uint32_t #{name}" + end + def rbs_class "Integer" end @@ -381,6 +422,10 @@ def java_type # This represents an arbitrarily-sized integer. When it gets to Ruby it will # be an Integer. class IntegerField < Field + def c_param + "pm_integer_t #{name}" + end + def rbs_class "Integer" end @@ -397,6 +442,10 @@ def java_type # This represents a double-precision floating point number. When it gets to # Ruby it will be a Float. class DoubleField < Field + def c_param + "double #{name}" + end + def rbs_class "Float" end @@ -636,6 +685,7 @@ def locals "ext/prism/api_node.c", "include/prism/ast.h", "include/prism/diagnostic.h", + "include/prism/node_new.h", "javascript/src/deserialize.js", "javascript/src/nodes.js", "javascript/src/visitor.js", From 7d17fd254bd08aed6b75adee1091e2c91f43c8d3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 6 Mar 2026 13:21:23 -0500 Subject: [PATCH 089/289] Fix the handling of `do` on commands Introduce PM_TOKEN_KEYWORD_DO_BLOCK to distinguish do-blocks on command-style calls from regular `do` keywords. Add parse_command_do_block to attach these blocks to call nodes. Track in_endless_def_body to prevent do-block consumption inside endless method definitions, allowing blocks to correctly bubble up to outer contexts like `private def f = puts "Hello" do end`. --- config.yml | 2 + include/prism/parser.h | 7 + lib/prism/lex_compat.rb | 1 + lib/prism/translation/parser/lexer.rb | 1 + .../4.0/endless_methods_command_call.txt | 231 +++++++++++--- snapshots/blocks.txt | 283 ++++++++++++++++-- snapshots/endless_methods.txt | 168 ++++++++--- src/prism.c | 88 +++++- templates/src/token_type.c.erb | 2 + test/prism/errors/def_endless_do.txt | 5 +- .../4.0/endless_methods_command_call.txt | 3 + test/prism/fixtures/blocks.txt | 8 + test/prism/fixtures/endless_methods.txt | 4 + 13 files changed, 675 insertions(+), 128 deletions(-) diff --git a/config.yml b/config.yml index d8a10bc113..c82c239de6 100644 --- a/config.yml +++ b/config.yml @@ -494,6 +494,8 @@ tokens: comment: "def" - name: KEYWORD_DEFINED comment: "defined?" + - name: KEYWORD_DO_BLOCK + comment: "do keyword for a block attached to a command" - name: KEYWORD_DO_LOOP comment: "do keyword for a predicate in a while, until, or for loop" - name: KEYWORD_END_UPCASE diff --git a/include/prism/parser.h b/include/prism/parser.h index c76fba58cf..ed4871197c 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -885,6 +885,13 @@ struct pm_parser { /** Whether or not we're at the beginning of a command. */ bool command_start; + /** + * Whether or not we're currently parsing the body of an endless method + * definition. In this context, PM_TOKEN_KEYWORD_DO_BLOCK should not be + * consumed by commands (it should bubble up to the outer context). + */ + bool in_endless_def_body; + /** Whether or not we're currently recovering from a syntax error. */ bool recovering; diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 99d8daacdd..0bc56ec592 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -134,6 +134,7 @@ def deconstruct_keys(keys) # :nodoc: KEYWORD_DEF: :on_kw, KEYWORD_DEFINED: :on_kw, KEYWORD_DO: :on_kw, + KEYWORD_DO_BLOCK: :on_kw, KEYWORD_DO_LOOP: :on_kw, KEYWORD_ELSE: :on_kw, KEYWORD_ELSIF: :on_kw, diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb index 8e18a3cd1e..e82042867f 100644 --- a/lib/prism/translation/parser/lexer.rb +++ b/lib/prism/translation/parser/lexer.rb @@ -87,6 +87,7 @@ class Lexer # :nodoc: KEYWORD_DEF: :kDEF, KEYWORD_DEFINED: :kDEFINED, KEYWORD_DO: :kDO, + KEYWORD_DO_BLOCK: :kDO_BLOCK, KEYWORD_DO_LOOP: :kDO_COND, KEYWORD_END: :kEND, KEYWORD_END_UPCASE: :klEND, diff --git a/snapshots/4.0/endless_methods_command_call.txt b/snapshots/4.0/endless_methods_command_call.txt index d2c58ec8b0..cb819358ef 100644 --- a/snapshots/4.0/endless_methods_command_call.txt +++ b/snapshots/4.0/endless_methods_command_call.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(8,31)) +@ ProgramNode (location: (1,0)-(11,37)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(8,31)) + @ StatementsNode (location: (1,0)-(11,37)) ├── flags: ∅ - └── body: (length: 8) + └── body: (length: 10) ├── @ CallNode (location: (1,0)-(1,30)) │ ├── flags: newline, ignore_visibility │ ├── receiver: ∅ @@ -421,75 +421,208 @@ │ ├── closing_loc: ∅ │ ├── equal_loc: ∅ │ └── block: ∅ - └── @ CallNode (location: (8,0)-(8,31)) + ├── @ CallNode (location: (8,0)-(8,31)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :private + │ ├── message_loc: (8,0)-(8,7) = "private" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (8,8)-(8,31)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ DefNode (location: (8,8)-(8,31)) + │ │ ├── flags: ∅ + │ │ ├── name: :foo + │ │ ├── name_loc: (8,16)-(8,19) = "foo" + │ │ ├── receiver: + │ │ │ @ CallNode (location: (8,12)-(8,15)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :obj + │ │ │ ├── message_loc: (8,12)-(8,15) = "obj" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── parameters: + │ │ │ @ ParametersNode (location: (8,20)-(8,21)) + │ │ │ ├── flags: ∅ + │ │ │ ├── requireds: (length: 1) + │ │ │ │ └── @ RequiredParameterNode (location: (8,20)-(8,21)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :x + │ │ │ ├── optionals: (length: 0) + │ │ │ ├── rest: ∅ + │ │ │ ├── posts: (length: 0) + │ │ │ ├── keywords: (length: 0) + │ │ │ ├── keyword_rest: ∅ + │ │ │ └── block: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (8,25)-(8,31)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (8,25)-(8,31)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :puts + │ │ │ ├── message_loc: (8,25)-(8,29) = "puts" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (8,30)-(8,31)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ LocalVariableReadNode (location: (8,30)-(8,31)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :x + │ │ │ │ └── depth: 0 + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: [:x] + │ │ ├── def_keyword_loc: (8,8)-(8,11) = "def" + │ │ ├── operator_loc: (8,15)-(8,16) = "." + │ │ ├── lparen_loc: (8,19)-(8,20) = "(" + │ │ ├── rparen_loc: (8,21)-(8,22) = ")" + │ │ ├── equal_loc: (8,23)-(8,24) = "=" + │ │ └── end_keyword_loc: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (10,0)-(10,25)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :private + │ ├── message_loc: (10,0)-(10,7) = "private" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (10,8)-(10,25)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ DefNode (location: (10,8)-(10,25)) + │ │ ├── flags: ∅ + │ │ ├── name: :foo + │ │ ├── name_loc: (10,12)-(10,15) = "foo" + │ │ ├── receiver: ∅ + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (10,18)-(10,25)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (10,18)-(10,25)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :bar + │ │ │ ├── message_loc: (10,18)-(10,21) = "bar" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (10,22)-(10,25)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ CallNode (location: (10,22)-(10,25)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ ├── message_loc: (10,22)-(10,25) = "baz" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: [] + │ │ ├── def_keyword_loc: (10,8)-(10,11) = "def" + │ │ ├── operator_loc: ∅ + │ │ ├── lparen_loc: ∅ + │ │ ├── rparen_loc: ∅ + │ │ ├── equal_loc: (10,16)-(10,17) = "=" + │ │ └── end_keyword_loc: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + └── @ CallNode (location: (11,0)-(11,37)) ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :private - ├── message_loc: (8,0)-(8,7) = "private" + ├── message_loc: (11,0)-(11,7) = "private" ├── opening_loc: ∅ ├── arguments: - │ @ ArgumentsNode (location: (8,8)-(8,31)) + │ @ ArgumentsNode (location: (11,8)-(11,25)) │ ├── flags: ∅ │ └── arguments: (length: 1) - │ └── @ DefNode (location: (8,8)-(8,31)) + │ └── @ DefNode (location: (11,8)-(11,25)) │ ├── flags: ∅ │ ├── name: :foo - │ ├── name_loc: (8,16)-(8,19) = "foo" - │ ├── receiver: - │ │ @ CallNode (location: (8,12)-(8,15)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :obj - │ │ ├── message_loc: (8,12)-(8,15) = "obj" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ ├── equal_loc: ∅ - │ │ └── block: ∅ - │ ├── parameters: - │ │ @ ParametersNode (location: (8,20)-(8,21)) - │ │ ├── flags: ∅ - │ │ ├── requireds: (length: 1) - │ │ │ └── @ RequiredParameterNode (location: (8,20)-(8,21)) - │ │ │ ├── flags: ∅ - │ │ │ └── name: :x - │ │ ├── optionals: (length: 0) - │ │ ├── rest: ∅ - │ │ ├── posts: (length: 0) - │ │ ├── keywords: (length: 0) - │ │ ├── keyword_rest: ∅ - │ │ └── block: ∅ + │ ├── name_loc: (11,12)-(11,15) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: ∅ │ ├── body: - │ │ @ StatementsNode (location: (8,25)-(8,31)) + │ │ @ StatementsNode (location: (11,18)-(11,25)) │ │ ├── flags: ∅ │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (8,25)-(8,31)) + │ │ └── @ CallNode (location: (11,18)-(11,25)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :puts - │ │ ├── message_loc: (8,25)-(8,29) = "puts" + │ │ ├── name: :bar + │ │ ├── message_loc: (11,18)-(11,21) = "bar" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (8,30)-(8,31)) + │ │ │ @ ArgumentsNode (location: (11,22)-(11,25)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) - │ │ │ └── @ LocalVariableReadNode (location: (8,30)-(8,31)) - │ │ │ ├── flags: ∅ - │ │ │ ├── name: :x - │ │ │ └── depth: 0 + │ │ │ └── @ CallNode (location: (11,22)-(11,25)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :baz + │ │ │ ├── message_loc: (11,22)-(11,25) = "baz" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ │ │ ├── closing_loc: ∅ │ │ ├── equal_loc: ∅ │ │ └── block: ∅ - │ ├── locals: [:x] - │ ├── def_keyword_loc: (8,8)-(8,11) = "def" - │ ├── operator_loc: (8,15)-(8,16) = "." - │ ├── lparen_loc: (8,19)-(8,20) = "(" - │ ├── rparen_loc: (8,21)-(8,22) = ")" - │ ├── equal_loc: (8,23)-(8,24) = "=" + │ ├── locals: [] + │ ├── def_keyword_loc: (11,8)-(11,11) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: (11,16)-(11,17) = "=" │ └── end_keyword_loc: ∅ ├── closing_loc: ∅ ├── equal_loc: ∅ - └── block: ∅ + └── block: + @ BlockNode (location: (11,26)-(11,37)) + ├── flags: ∅ + ├── locals: [] + ├── parameters: ∅ + ├── body: + │ @ StatementsNode (location: (11,29)-(11,33)) + │ ├── flags: ∅ + │ └── body: (length: 1) + │ └── @ CallNode (location: (11,29)-(11,33)) + │ ├── flags: newline, variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :expr + │ ├── message_loc: (11,29)-(11,33) = "expr" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── opening_loc: (11,26)-(11,28) = "do" + └── closing_loc: (11,34)-(11,37) = "end" diff --git a/snapshots/blocks.txt b/snapshots/blocks.txt index 62943535e1..03148044f9 100644 --- a/snapshots/blocks.txt +++ b/snapshots/blocks.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(54,17)) +@ ProgramNode (location: (1,0)-(62,25)) ├── flags: ∅ ├── locals: [:fork] └── statements: - @ StatementsNode (location: (1,0)-(54,17)) + @ StatementsNode (location: (1,0)-(62,25)) ├── flags: ∅ - └── body: (length: 20) + └── body: (length: 24) ├── @ CallNode (location: (1,0)-(1,16)) │ ├── flags: newline │ ├── receiver: @@ -829,41 +829,284 @@ │ ├── closing_loc: ∅ │ ├── equal_loc: ∅ │ └── block: ∅ - └── @ CallNode (location: (54,0)-(54,17)) + ├── @ CallNode (location: (54,0)-(54,17)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (54,0)-(54,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: + │ @ BlockNode (location: (54,4)-(54,17)) + │ ├── flags: ∅ + │ ├── locals: [:bar] + │ ├── parameters: + │ │ @ BlockParametersNode (location: (54,7)-(54,13)) + │ │ ├── flags: ∅ + │ │ ├── parameters: + │ │ │ @ ParametersNode (location: (54,8)-(54,12)) + │ │ │ ├── flags: ∅ + │ │ │ ├── requireds: (length: 1) + │ │ │ │ └── @ RequiredParameterNode (location: (54,8)-(54,11)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :bar + │ │ │ ├── optionals: (length: 0) + │ │ │ ├── rest: + │ │ │ │ @ ImplicitRestNode (location: (54,11)-(54,12)) + │ │ │ │ └── flags: ∅ + │ │ │ ├── posts: (length: 0) + │ │ │ ├── keywords: (length: 0) + │ │ │ ├── keyword_rest: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: (length: 0) + │ │ ├── opening_loc: (54,7)-(54,8) = "|" + │ │ └── closing_loc: (54,12)-(54,13) = "|" + │ ├── body: ∅ + │ ├── opening_loc: (54,4)-(54,6) = "do" + │ └── closing_loc: (54,14)-(54,17) = "end" + ├── @ CallNode (location: (56,0)-(56,23)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (56,0)-(56,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (56,4)-(56,16)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (56,4)-(56,16)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :bar + │ │ ├── message_loc: (56,4)-(56,7) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (56,8)-(56,16)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 2) + │ │ │ ├── @ CallNode (location: (56,8)-(56,11)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :baz + │ │ │ │ ├── message_loc: (56,8)-(56,11) = "baz" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ └── @ CallNode (location: (56,13)-(56,16)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :qux + │ │ │ ├── message_loc: (56,13)-(56,16) = "qux" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: + │ @ BlockNode (location: (56,17)-(56,23)) + │ ├── flags: ∅ + │ ├── locals: [] + │ ├── parameters: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (56,17)-(56,19) = "do" + │ └── closing_loc: (56,20)-(56,23) = "end" + ├── @ CallNode (location: (58,0)-(58,18)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ CallNode (location: (58,0)-(58,3)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (58,0)-(58,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── call_operator_loc: (58,3)-(58,4) = "." + │ ├── name: :bar + │ ├── message_loc: (58,4)-(58,7) = "bar" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (58,8)-(58,11)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (58,8)-(58,11)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :baz + │ │ ├── message_loc: (58,8)-(58,11) = "baz" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: + │ @ BlockNode (location: (58,12)-(58,18)) + │ ├── flags: ∅ + │ ├── locals: [] + │ ├── parameters: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (58,12)-(58,14) = "do" + │ └── closing_loc: (58,15)-(58,18) = "end" + ├── @ CallNode (location: (60,0)-(60,34)) + │ ├── flags: newline + │ ├── receiver: + │ │ @ CallNode (location: (60,0)-(60,18)) + │ │ ├── flags: ∅ + │ │ ├── receiver: + │ │ │ @ CallNode (location: (60,0)-(60,3)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :foo + │ │ │ ├── message_loc: (60,0)-(60,3) = "foo" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── call_operator_loc: (60,3)-(60,4) = "." + │ │ ├── name: :bar + │ │ ├── message_loc: (60,4)-(60,7) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (60,8)-(60,11)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ CallNode (location: (60,8)-(60,11)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :baz + │ │ │ ├── message_loc: (60,8)-(60,11) = "baz" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: + │ │ @ BlockNode (location: (60,12)-(60,18)) + │ │ ├── flags: ∅ + │ │ ├── locals: [] + │ │ ├── parameters: ∅ + │ │ ├── body: ∅ + │ │ ├── opening_loc: (60,12)-(60,14) = "do" + │ │ └── closing_loc: (60,15)-(60,18) = "end" + │ ├── call_operator_loc: (60,18)-(60,19) = "." + │ ├── name: :qux + │ ├── message_loc: (60,19)-(60,22) = "qux" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (60,23)-(60,27)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (60,23)-(60,27)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :quux + │ │ ├── message_loc: (60,23)-(60,27) = "quux" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: + │ @ BlockNode (location: (60,28)-(60,34)) + │ ├── flags: ∅ + │ ├── locals: [] + │ ├── parameters: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (60,28)-(60,30) = "do" + │ └── closing_loc: (60,31)-(60,34) = "end" + └── @ CallNode (location: (62,0)-(62,25)) ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo - ├── message_loc: (54,0)-(54,3) = "foo" + ├── message_loc: (62,0)-(62,3) = "foo" ├── opening_loc: ∅ - ├── arguments: ∅ + ├── arguments: + │ @ ArgumentsNode (location: (62,4)-(62,12)) + │ ├── flags: ∅ + │ └── arguments: (length: 2) + │ ├── @ CallNode (location: (62,4)-(62,7)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :bar + │ │ ├── message_loc: (62,4)-(62,7) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ └── @ CallNode (location: (62,9)-(62,12)) + │ ├── flags: variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :baz + │ ├── message_loc: (62,9)-(62,12) = "baz" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ ├── closing_loc: ∅ ├── equal_loc: ∅ └── block: - @ BlockNode (location: (54,4)-(54,17)) + @ BlockNode (location: (62,13)-(62,25)) ├── flags: ∅ - ├── locals: [:bar] + ├── locals: [:x] ├── parameters: - │ @ BlockParametersNode (location: (54,7)-(54,13)) + │ @ BlockParametersNode (location: (62,16)-(62,19)) │ ├── flags: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (54,8)-(54,12)) + │ │ @ ParametersNode (location: (62,17)-(62,18)) │ │ ├── flags: ∅ │ │ ├── requireds: (length: 1) - │ │ │ └── @ RequiredParameterNode (location: (54,8)-(54,11)) + │ │ │ └── @ RequiredParameterNode (location: (62,17)-(62,18)) │ │ │ ├── flags: ∅ - │ │ │ └── name: :bar + │ │ │ └── name: :x │ │ ├── optionals: (length: 0) - │ │ ├── rest: - │ │ │ @ ImplicitRestNode (location: (54,11)-(54,12)) - │ │ │ └── flags: ∅ + │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── locals: (length: 0) - │ ├── opening_loc: (54,7)-(54,8) = "|" - │ └── closing_loc: (54,12)-(54,13) = "|" - ├── body: ∅ - ├── opening_loc: (54,4)-(54,6) = "do" - └── closing_loc: (54,14)-(54,17) = "end" + │ ├── opening_loc: (62,16)-(62,17) = "|" + │ └── closing_loc: (62,18)-(62,19) = "|" + ├── body: + │ @ StatementsNode (location: (62,20)-(62,21)) + │ ├── flags: ∅ + │ └── body: (length: 1) + │ └── @ LocalVariableReadNode (location: (62,20)-(62,21)) + │ ├── flags: newline + │ ├── name: :x + │ └── depth: 0 + ├── opening_loc: (62,13)-(62,15) = "do" + └── closing_loc: (62,22)-(62,25) = "end" diff --git a/snapshots/endless_methods.txt b/snapshots/endless_methods.txt index 938ec25a56..9334abec63 100644 --- a/snapshots/endless_methods.txt +++ b/snapshots/endless_methods.txt @@ -1,10 +1,10 @@ -@ ProgramNode (location: (1,0)-(7,15)) +@ ProgramNode (location: (1,0)-(11,18)) ├── flags: ∅ ├── locals: [:x] └── statements: - @ StatementsNode (location: (1,0)-(7,15)) + @ StatementsNode (location: (1,0)-(11,18)) ├── flags: ∅ - └── body: (length: 4) + └── body: (length: 6) ├── @ DefNode (location: (1,0)-(1,11)) │ ├── flags: newline │ ├── name: :foo @@ -116,44 +116,128 @@ │ ├── rparen_loc: ∅ │ ├── equal_loc: (5,11)-(5,12) = "=" │ └── end_keyword_loc: ∅ - └── @ LocalVariableWriteNode (location: (7,0)-(7,15)) + ├── @ LocalVariableWriteNode (location: (7,0)-(7,15)) + │ ├── flags: newline + │ ├── name: :x + │ ├── depth: 0 + │ ├── name_loc: (7,0)-(7,1) = "x" + │ ├── value: + │ │ @ DefNode (location: (7,4)-(7,15)) + │ │ ├── flags: ∅ + │ │ ├── name: :f + │ │ ├── name_loc: (7,8)-(7,9) = "f" + │ │ ├── receiver: ∅ + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (7,12)-(7,15)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (7,12)-(7,15)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :p + │ │ │ ├── message_loc: (7,12)-(7,13) = "p" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (7,14)-(7,15)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ IntegerNode (location: (7,14)-(7,15)) + │ │ │ │ ├── flags: static_literal, decimal + │ │ │ │ └── value: 1 + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── locals: [] + │ │ ├── def_keyword_loc: (7,4)-(7,7) = "def" + │ │ ├── operator_loc: ∅ + │ │ ├── lparen_loc: ∅ + │ │ ├── rparen_loc: ∅ + │ │ ├── equal_loc: (7,10)-(7,11) = "=" + │ │ └── end_keyword_loc: ∅ + │ └── operator_loc: (7,2)-(7,3) = "=" + ├── @ DefNode (location: (9,0)-(9,17)) + │ ├── flags: newline + │ ├── name: :foo + │ ├── name_loc: (9,4)-(9,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (9,10)-(9,17)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ CallNode (location: (9,10)-(9,17)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :bar + │ │ ├── message_loc: (9,10)-(9,13) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (9,14)-(9,17)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ CallNode (location: (9,14)-(9,17)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :baz + │ │ │ ├── message_loc: (9,14)-(9,17) = "baz" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── locals: [] + │ ├── def_keyword_loc: (9,0)-(9,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: (9,8)-(9,9) = "=" + │ └── end_keyword_loc: ∅ + └── @ DefNode (location: (11,0)-(11,18)) ├── flags: newline - ├── name: :x - ├── depth: 0 - ├── name_loc: (7,0)-(7,1) = "x" - ├── value: - │ @ DefNode (location: (7,4)-(7,15)) + ├── name: :foo + ├── name_loc: (11,4)-(11,7) = "foo" + ├── receiver: ∅ + ├── parameters: ∅ + ├── body: + │ @ StatementsNode (location: (11,10)-(11,18)) │ ├── flags: ∅ - │ ├── name: :f - │ ├── name_loc: (7,8)-(7,9) = "f" - │ ├── receiver: ∅ - │ ├── parameters: ∅ - │ ├── body: - │ │ @ StatementsNode (location: (7,12)-(7,15)) - │ │ ├── flags: ∅ - │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (7,12)-(7,15)) - │ │ ├── flags: ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :p - │ │ ├── message_loc: (7,12)-(7,13) = "p" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (7,14)-(7,15)) - │ │ │ ├── flags: ∅ - │ │ │ └── arguments: (length: 1) - │ │ │ └── @ IntegerNode (location: (7,14)-(7,15)) - │ │ │ ├── flags: static_literal, decimal - │ │ │ └── value: 1 - │ │ ├── closing_loc: ∅ - │ │ ├── equal_loc: ∅ - │ │ └── block: ∅ - │ ├── locals: [] - │ ├── def_keyword_loc: (7,4)-(7,7) = "def" - │ ├── operator_loc: ∅ - │ ├── lparen_loc: ∅ - │ ├── rparen_loc: ∅ - │ ├── equal_loc: (7,10)-(7,11) = "=" - │ └── end_keyword_loc: ∅ - └── operator_loc: (7,2)-(7,3) = "=" + │ └── body: (length: 1) + │ └── @ CallNode (location: (11,10)-(11,18)) + │ ├── flags: ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :bar + │ ├── message_loc: (11,10)-(11,13) = "bar" + │ ├── opening_loc: (11,13)-(11,14) = "(" + │ ├── arguments: + │ │ @ ArgumentsNode (location: (11,14)-(11,17)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (11,14)-(11,17)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :baz + │ │ ├── message_loc: (11,14)-(11,17) = "baz" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: (11,17)-(11,18) = ")" + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── locals: [] + ├── def_keyword_loc: (11,0)-(11,3) = "def" + ├── operator_loc: ∅ + ├── lparen_loc: ∅ + ├── rparen_loc: ∅ + ├── equal_loc: (11,8)-(11,9) = "=" + └── end_keyword_loc: ∅ diff --git a/src/prism.c b/src/prism.c index 6f21c97bc3..efe21c5e7e 100644 --- a/src/prism.c +++ b/src/prism.c @@ -8330,9 +8330,15 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) { switch (width) { case 2: if (lex_keyword(parser, current_start, "do", width, PM_LEX_STATE_BEG, PM_TOKEN_KEYWORD_DO, PM_TOKEN_EOF) != PM_TOKEN_EOF) { + if (parser->enclosure_nesting == parser->lambda_enclosure_nesting) { + return PM_TOKEN_KEYWORD_DO; + } if (pm_do_loop_stack_p(parser)) { return PM_TOKEN_KEYWORD_DO_LOOP; } + if (!pm_accepts_block_stack_p(parser)) { + return PM_TOKEN_KEYWORD_DO_BLOCK; + } return PM_TOKEN_KEYWORD_DO; } @@ -12497,6 +12503,7 @@ token_begins_expression_p(pm_token_type_t type) { case PM_TOKEN_EOF: case PM_TOKEN_LAMBDA_BEGIN: case PM_TOKEN_KEYWORD_DO: + case PM_TOKEN_KEYWORD_DO_BLOCK: case PM_TOKEN_KEYWORD_DO_LOOP: case PM_TOKEN_KEYWORD_END: case PM_TOKEN_KEYWORD_ELSE: @@ -14825,6 +14832,27 @@ parse_block(pm_parser_t *parser, uint16_t depth) { return pm_block_node_create(parser, &locals, &opening, parameters, statements, &parser->previous); } +/** + * Attach a do-block (PM_TOKEN_KEYWORD_DO_BLOCK) to a command-style call node. + * The current token must be PM_TOKEN_KEYWORD_DO_BLOCK when this is called. + */ +static void +parse_command_do_block(pm_parser_t *parser, pm_call_node_t *call, uint16_t depth) { + parser_lex(parser); + pm_block_node_t *block = parse_block(parser, (uint16_t) (depth + 1)); + + if (call->block != NULL) { + pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_BLOCK_MULTI); + if (call->arguments == NULL) { + call->arguments = pm_arguments_node_create(parser); + } + pm_arguments_node_arguments_append(parser->arena, call->arguments, call->block); + } + + call->block = UP(block); + PM_NODE_LENGTH_SET_NODE(call, block); +} + /** * Parse a list of arguments and their surrounding parentheses if they are * present. It returns true if it found any pieces of arguments (parentheses, @@ -14833,6 +14861,7 @@ parse_block(pm_parser_t *parser, uint16_t depth) { static bool parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call, uint16_t depth) { bool found = false; + bool parsed_command_args = false; if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { found |= true; @@ -14855,6 +14884,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept } } else if (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND)) && !match1(parser, PM_TOKEN_BRACE_LEFT)) { found |= true; + parsed_command_args = true; pm_accepts_block_stack_push(parser, false); // If we get here, then the subsequent token cannot be used as an infix @@ -14885,6 +14915,9 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept } else if (pm_accepts_block_stack_p(parser) && accept1(parser, PM_TOKEN_KEYWORD_DO)) { found |= true; block = parse_block(parser, (uint16_t) (depth + 1)); + } else if (parsed_command_args && pm_accepts_block_stack_p(parser) && !parser->in_endless_def_body && accept1(parser, PM_TOKEN_KEYWORD_DO_BLOCK)) { + found |= true; + block = parse_block(parser, (uint16_t) (depth + 1)); } if (block != NULL) { @@ -15300,7 +15333,7 @@ parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newl #define PM_CASE_KEYWORD PM_TOKEN_KEYWORD___ENCODING__: case PM_TOKEN_KEYWORD___FILE__: case PM_TOKEN_KEYWORD___LINE__: \ case PM_TOKEN_KEYWORD_ALIAS: case PM_TOKEN_KEYWORD_AND: case PM_TOKEN_KEYWORD_BEGIN: case PM_TOKEN_KEYWORD_BEGIN_UPCASE: \ case PM_TOKEN_KEYWORD_BREAK: case PM_TOKEN_KEYWORD_CASE: case PM_TOKEN_KEYWORD_CLASS: case PM_TOKEN_KEYWORD_DEF: \ - case PM_TOKEN_KEYWORD_DEFINED: case PM_TOKEN_KEYWORD_DO: case PM_TOKEN_KEYWORD_DO_LOOP: case PM_TOKEN_KEYWORD_ELSE: \ + case PM_TOKEN_KEYWORD_DEFINED: case PM_TOKEN_KEYWORD_DO: case PM_TOKEN_KEYWORD_DO_BLOCK: case PM_TOKEN_KEYWORD_DO_LOOP: case PM_TOKEN_KEYWORD_ELSE: \ case PM_TOKEN_KEYWORD_ELSIF: case PM_TOKEN_KEYWORD_END: case PM_TOKEN_KEYWORD_END_UPCASE: case PM_TOKEN_KEYWORD_ENSURE: \ case PM_TOKEN_KEYWORD_FALSE: case PM_TOKEN_KEYWORD_FOR: case PM_TOKEN_KEYWORD_IF: case PM_TOKEN_KEYWORD_IN: \ case PM_TOKEN_KEYWORD_MODULE: case PM_TOKEN_KEYWORD_NEXT: case PM_TOKEN_KEYWORD_NIL: case PM_TOKEN_KEYWORD_NOT: \ @@ -17486,7 +17519,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b element = UP(pm_keyword_hash_node_create(parser)); pm_static_literals_t hash_keys = { 0 }; - if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) { + if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_KEYWORD_DO_BLOCK, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) { parse_assocs(parser, &hash_keys, element, (uint16_t) (depth + 1)); } @@ -18895,20 +18928,30 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b allow_command_call = binding_power == PM_BINDING_POWER_ASSIGNMENT || binding_power < PM_BINDING_POWER_COMPOSITION; } + // Inside a def body, we push true onto the + // accepts_block_stack so that `do` is lexed as + // PM_TOKEN_KEYWORD_DO (which can only start a block for + // primary-level constructs, not commands). During command + // argument parsing, the stack is pushed to false, causing + // `do` to be lexed as PM_TOKEN_KEYWORD_DO_BLOCK, which + // is not consumed inside the endless def body and instead + // left for the outer context. + pm_accepts_block_stack_push(parser, true); + bool previous_in_endless_def_body = parser->in_endless_def_body; + parser->in_endless_def_body = true; pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_command_call, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); + parser->in_endless_def_body = previous_in_endless_def_body; + pm_accepts_block_stack_pop(parser); - // In an endless method definition, the body is not allowed to - // be a command with a do..end block. - if (PM_NODE_TYPE_P(statement, PM_CALL_NODE)) { - pm_call_node_t *call = (pm_call_node_t *) statement; - - if (call->arguments != NULL && call->block != NULL && PM_NODE_TYPE_P(call->block, PM_BLOCK_NODE)) { - pm_block_node_t *block = (pm_block_node_t *) call->block; - - if (parser->start[block->opening_loc.start] != '{') { - pm_parser_err_node(parser, call->block, PM_ERR_DEF_ENDLESS_DO_BLOCK); - } - } + // If an unconsumed PM_TOKEN_KEYWORD_DO follows the body, + // it is an error (e.g., `def f = 1 do end`). + // PM_TOKEN_KEYWORD_DO_BLOCK is intentionally not caught + // here — it should bubble up to the outer context (e.g., + // `private def f = puts "Hello" do end` where the block + // attaches to `private`). + if (accept1(parser, PM_TOKEN_KEYWORD_DO)) { + pm_block_node_t *block = parse_block(parser, (uint16_t) (depth + 1)); + pm_parser_err_node(parser, UP(block), PM_ERR_DEF_ENDLESS_DO_BLOCK); } if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { @@ -20066,9 +20109,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b opening = parser->previous; if (!match3(parser, PM_TOKEN_KEYWORD_END, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { - pm_accepts_block_stack_push(parser, true); body = UP(parse_statements(parser, PM_CONTEXT_LAMBDA_DO_END, (uint16_t) (depth + 1))); - pm_accepts_block_stack_pop(parser); } if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) { @@ -21518,6 +21559,14 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc } break; case PM_CALL_NODE: + // A do-block can attach to a command-style call at the + // primary level. Inside an endless def body, DO_BLOCK must + // not be consumed so it can bubble up to the outer context + // (e.g., `private` in `private def f = bar baz do end`). + if (match1(parser, PM_TOKEN_KEYWORD_DO_BLOCK) && !parser->in_endless_def_body && pm_accepts_block_stack_p(parser) && pm_call_node_command_p((pm_call_node_t *) node)) { + parse_command_do_block(parser, (pm_call_node_t *) node, depth); + } + // If we have a call node, then we need to check if it looks like a // method call without parentheses that contains arguments. If it // does, then it has different rules for parsing infix operators, @@ -21573,6 +21622,13 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc } break; case PM_CALL_NODE: + // A do-block can attach to a command-style call + // produced by infix operators (e.g., dot-calls like + // `obj.method args do end`). + if (match1(parser, PM_TOKEN_KEYWORD_DO_BLOCK) && !parser->in_endless_def_body && pm_accepts_block_stack_p(parser) && pm_call_node_command_p((pm_call_node_t *) node)) { + parse_command_do_block(parser, (pm_call_node_t *) node, depth); + } + // These expressions are also statements, by virtue of the // right-hand side of the expression (i.e., the last argument to // the call node) being an implicit array. diff --git a/templates/src/token_type.c.erb b/templates/src/token_type.c.erb index 5c6f271310..94e41ec4ba 100644 --- a/templates/src/token_type.c.erb +++ b/templates/src/token_type.c.erb @@ -167,6 +167,8 @@ pm_token_type_human(pm_token_type_t token_type) { return "'defined?'"; case PM_TOKEN_KEYWORD_DO: return "'do'"; + case PM_TOKEN_KEYWORD_DO_BLOCK: + return "'do'"; case PM_TOKEN_KEYWORD_DO_LOOP: return "'do'"; case PM_TOKEN_KEYWORD_ELSE: diff --git a/test/prism/errors/def_endless_do.txt b/test/prism/errors/def_endless_do.txt index 4d786638a6..d66b7086da 100644 --- a/test/prism/errors/def_endless_do.txt +++ b/test/prism/errors/def_endless_do.txt @@ -1,3 +1,6 @@ def a = a b do 1 end - ^~~~~~~~ unexpected `do` for block in an endless method definition + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', expecting end-of-input + ^~~ unexpected 'end', ignoring it diff --git a/test/prism/fixtures/4.0/endless_methods_command_call.txt b/test/prism/fixtures/4.0/endless_methods_command_call.txt index 91a9d156d5..146a6ee579 100644 --- a/test/prism/fixtures/4.0/endless_methods_command_call.txt +++ b/test/prism/fixtures/4.0/endless_methods_command_call.txt @@ -6,3 +6,6 @@ private def foo(x) = puts x private def obj.foo = puts "Hello" private def obj.foo() = puts "Hello" private def obj.foo(x) = puts x + +private def foo = bar baz +private def foo = bar baz do expr end diff --git a/test/prism/fixtures/blocks.txt b/test/prism/fixtures/blocks.txt index e33d95c150..51ec84950c 100644 --- a/test/prism/fixtures/blocks.txt +++ b/test/prism/fixtures/blocks.txt @@ -52,3 +52,11 @@ foo lambda { | } foo do |bar,| end + +foo bar baz, qux do end + +foo.bar baz do end + +foo.bar baz do end.qux quux do end + +foo bar, baz do |x| x end diff --git a/test/prism/fixtures/endless_methods.txt b/test/prism/fixtures/endless_methods.txt index 7eb3bf4318..6e0488a5ee 100644 --- a/test/prism/fixtures/endless_methods.txt +++ b/test/prism/fixtures/endless_methods.txt @@ -5,3 +5,7 @@ def bar = A "" def method = 1 + 2 + 3 x = def f = p 1 + +def foo = bar baz + +def foo = bar(baz) From 35470bb90d1869e75833715bce820dab00e13bce Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 6 Mar 2026 15:57:13 -0500 Subject: [PATCH 090/289] Fix precedence of infix operators after command --- src/prism.c | 17 ++++++++++++++++- test/prism/errors/command_call_in_2.txt | 4 ++++ test/prism/errors/command_call_in_3.txt | 4 ++++ test/prism/errors/command_call_in_4.txt | 4 ++++ test/prism/errors/command_call_in_5.txt | 4 ++++ test/prism/errors/command_call_in_6.txt | 4 ++++ test/prism/errors/command_call_in_7.txt | 4 ++++ test/prism/errors_test.rb | 4 ---- 8 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 test/prism/errors/command_call_in_2.txt create mode 100644 test/prism/errors/command_call_in_3.txt create mode 100644 test/prism/errors/command_call_in_4.txt create mode 100644 test/prism/errors/command_call_in_5.txt create mode 100644 test/prism/errors/command_call_in_6.txt create mode 100644 test/prism/errors/command_call_in_7.txt diff --git a/src/prism.c b/src/prism.c index efe21c5e7e..2e2d6bcbd4 100644 --- a/src/prism.c +++ b/src/prism.c @@ -21621,7 +21621,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc return node; } break; - case PM_CALL_NODE: + case PM_CALL_NODE: { // A do-block can attach to a command-style call // produced by infix operators (e.g., dot-calls like // `obj.method args do end`). @@ -21635,7 +21635,22 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { return node; } + + // Command-style calls (calls with arguments but without + // parentheses) only accept composition (and/or) and modifier + // (if/unless/etc.) operators. We need to exclude operator calls + // (e.g., a + b) which also satisfy pm_call_node_command_p but + // are not commands. + const pm_call_node_t *cast = (const pm_call_node_t *) node; + if ( + (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_COMPOSITION) && + (cast->receiver == NULL || cast->call_operator_loc.length > 0) && + pm_call_node_command_p(cast) + ) { + return node; + } break; + } case PM_RESCUE_MODIFIER_NODE: // A rescue modifier whose handler is a one-liner pattern match // (=> or in) produces a statement. That means it cannot be diff --git a/test/prism/errors/command_call_in_2.txt b/test/prism/errors/command_call_in_2.txt new file mode 100644 index 0000000000..6676b1acba --- /dev/null +++ b/test/prism/errors/command_call_in_2.txt @@ -0,0 +1,4 @@ +a.b x in pattern + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + diff --git a/test/prism/errors/command_call_in_3.txt b/test/prism/errors/command_call_in_3.txt new file mode 100644 index 0000000000..6fe026d7d3 --- /dev/null +++ b/test/prism/errors/command_call_in_3.txt @@ -0,0 +1,4 @@ +a.b x: in pattern + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + diff --git a/test/prism/errors/command_call_in_4.txt b/test/prism/errors/command_call_in_4.txt new file mode 100644 index 0000000000..045afe6498 --- /dev/null +++ b/test/prism/errors/command_call_in_4.txt @@ -0,0 +1,4 @@ +a.b &x in pattern + ^~ unexpected 'in', expecting end-of-input + ^~ unexpected 'in', ignoring it + diff --git a/test/prism/errors/command_call_in_5.txt b/test/prism/errors/command_call_in_5.txt new file mode 100644 index 0000000000..be07287f81 --- /dev/null +++ b/test/prism/errors/command_call_in_5.txt @@ -0,0 +1,4 @@ +a.b *x => pattern + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + diff --git a/test/prism/errors/command_call_in_6.txt b/test/prism/errors/command_call_in_6.txt new file mode 100644 index 0000000000..470f323872 --- /dev/null +++ b/test/prism/errors/command_call_in_6.txt @@ -0,0 +1,4 @@ +a.b x: => pattern + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + diff --git a/test/prism/errors/command_call_in_7.txt b/test/prism/errors/command_call_in_7.txt new file mode 100644 index 0000000000..a8bea912b5 --- /dev/null +++ b/test/prism/errors/command_call_in_7.txt @@ -0,0 +1,4 @@ +a.b &x => pattern + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 898f4afb45..c3362eaaf5 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -60,10 +60,6 @@ def test_unterminated_empty_string_closing assert_nil statement.closing end - def test_invalid_message_name - assert_equal :"", Prism.parse_statement("+.@foo,+=foo").write_name - end - def test_regexp_encoding_option_mismatch_error # UTF-8 char with ASCII-8BIT modifier result = Prism.parse('/Ȃ/n') From 7d21e564ac4d0a7e2ebb4f2b63bc1db73a043c47 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 6 Mar 2026 16:01:02 -0500 Subject: [PATCH 091/289] Fix not without parentheses binding power --- src/prism.c | 10 ++++++---- test/prism/errors/not_without_parens_assignment.txt | 4 ++++ test/prism/errors/not_without_parens_call.txt | 7 +++++++ test/prism/errors/not_without_parens_command.txt | 4 ++++ test/prism/errors/not_without_parens_command_call.txt | 4 ++++ test/prism/errors/not_without_parens_return.txt | 4 ++++ 6 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 test/prism/errors/not_without_parens_assignment.txt create mode 100644 test/prism/errors/not_without_parens_call.txt create mode 100644 test/prism/errors/not_without_parens_command.txt create mode 100644 test/prism/errors/not_without_parens_command_call.txt create mode 100644 test/prism/errors/not_without_parens_return.txt diff --git a/src/prism.c b/src/prism.c index efe21c5e7e..1a6165810c 100644 --- a/src/prism.c +++ b/src/prism.c @@ -19195,10 +19195,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_arguments_t arguments = { 0 }; pm_node_t *receiver = NULL; - // If we do not accept a command call, then we also do not accept a - // not without parentheses. In this case we need to reject this - // syntax. - if (!accepts_command_call && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { + // The `not` keyword without parentheses is only valid in contexts + // where it would be parsed as an expression (i.e., at or below + // the `not` binding power level). In other contexts (e.g., method + // arguments, array elements, assignment right-hand sides), + // parentheses are required: `not(x)`. + if (binding_power > PM_BINDING_POWER_NOT && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES)) { pm_parser_err(parser, PM_TOKEN_END(parser, &parser->previous), 1, PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN); } else { diff --git a/test/prism/errors/not_without_parens_assignment.txt b/test/prism/errors/not_without_parens_assignment.txt new file mode 100644 index 0000000000..32d58efedf --- /dev/null +++ b/test/prism/errors/not_without_parens_assignment.txt @@ -0,0 +1,4 @@ +x = not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/not_without_parens_call.txt b/test/prism/errors/not_without_parens_call.txt new file mode 100644 index 0000000000..a778193400 --- /dev/null +++ b/test/prism/errors/not_without_parens_call.txt @@ -0,0 +1,7 @@ +foo(not y) + ^ expected a `(` after `not` + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/not_without_parens_command.txt b/test/prism/errors/not_without_parens_command.txt new file mode 100644 index 0000000000..957a06f8f1 --- /dev/null +++ b/test/prism/errors/not_without_parens_command.txt @@ -0,0 +1,4 @@ +foo not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/not_without_parens_command_call.txt b/test/prism/errors/not_without_parens_command_call.txt new file mode 100644 index 0000000000..564833c7de --- /dev/null +++ b/test/prism/errors/not_without_parens_command_call.txt @@ -0,0 +1,4 @@ +a.b not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/not_without_parens_return.txt b/test/prism/errors/not_without_parens_return.txt new file mode 100644 index 0000000000..1c7edb6ff1 --- /dev/null +++ b/test/prism/errors/not_without_parens_return.txt @@ -0,0 +1,4 @@ +return not y + ^ expected a `(` after `not` + ^ unexpected local variable or method, expecting end-of-input + From 17c404f62fb6a403289f79959e77dc8a91fcbf82 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 5 Mar 2026 12:23:45 -0500 Subject: [PATCH 092/289] Add a simple benchmark script to bin/prism --- bin/prism | 54 +++++++++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/bin/prism b/bin/prism index e3bb0a32d9..43bdea1f36 100755 --- a/bin/prism +++ b/bin/prism @@ -8,7 +8,7 @@ module Prism class CLI def run(argv) case argv.shift - when "benchmark" then benchmark(argv) + when "bench" then bench(argv) when "bundle" then bundle(argv) when "console" then console when "dot" then dot(argv) @@ -25,7 +25,7 @@ module Prism else puts <<~TXT Usage: - bin/prism benchmark [source_file] + bin/prism bench [file ...] bin/prism bundle [...] bin/prism console bin/prism dot [source] @@ -49,46 +49,34 @@ module Prism # Commands ############################################################################ - # bin/prism benchmark [source_file] - def benchmark(argv) + # bin/prism bench [file ...] + # Measures raw parse throughput using Prism.profile (no Ruby AST creation). + def bench(argv) require "benchmark/ips" - require "parser/current" - require "ripper" - require "ruby_parser" - - filepath = argv.fetch(0) { File.expand_path("../lib/prism/node.rb", __dir__) } - source = File.read(filepath) - - Benchmark.ips do |x| - x.report("Prism") do - Prism.parse(source, filepath: filepath) - end - x.report("Ripper::SexpBuilder") do - Ripper.sexp_raw(source, filepath) - end - - x.report("Prism::Translation::Ripper::SexpBuilder") do - Prism::Translation::Ripper.sexp_raw(source, filepath) + files = + if argv.any? + argv.map { |path| [path, File.read(path)] } + else + Dir[File.join(__dir__, "../test/prism/fixtures/**/*.txt")].sort.map { |path| [path, File.read(path)] } + + Dir[File.join(__dir__, "../lib/**/*.rb")].sort.map { |path| [path, File.read(path)] } end - x.report("Parser::CurrentRuby") do - Parser::CurrentRuby.parse(source, filepath) - end + total_bytes = files.sum { |_, source| source.bytesize } + puts "Benchmarking #{files.size} files (#{total_bytes} bytes total)" + puts - x.report("Prism::Translation::Parser") do - Prism::Translation::Parser.parse(source, filepath) - end + Benchmark.ips do |x| + x.time = 10 + x.warmup = 3 - x.report("RubyParser") do - RubyParser.new.parse(source, filepath) + x.report("parse (all files)") do + files.each { |_, source| Prism.profile(source) } end - x.report("Prism::Translation::RubyParser") do - Prism::Translation::RubyParser.new.parse(source, filepath) + x.report("parse (fixtures only)") do + files.each { |path, source| Prism.profile(source) if path.end_with?(".txt") } end - - x.compare! end end From 0e7fb6b868c1082b89d0c2c3788ed7568fbcb809 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 6 Mar 2026 20:41:27 -0500 Subject: [PATCH 093/289] Copy and embed for serialization format --- docs/serialization.md | 15 ++---- javascript/src/parsePrism.js | 2 +- .../java/org/ruby_lang/prism/Loader.java.erb | 40 ++++---------- templates/javascript/src/deserialize.js.erb | 31 +++-------- templates/lib/prism/serialize.rb.erb | 38 ++++--------- templates/src/serialize.c.erb | 54 ++++--------------- 6 files changed, 39 insertions(+), 141 deletions(-) diff --git a/docs/serialization.md b/docs/serialization.md index ec395f8847..8c1b47c690 100644 --- a/docs/serialization.md +++ b/docs/serialization.md @@ -126,7 +126,7 @@ Every field on the node is then appended to the serialized string. The fields ca * `node` - A field that is a node. This is structured just as like parent node. * `node?` - A field that is a node that is optionally present. If the node is not present, then a single `0` byte will be written in its place. If it is present, then it will be structured just as like parent node. * `node[]` - A field that is an array of nodes. This is structured as a variable-length integer length, followed by the child nodes themselves. -* `string` - A field that is a string. For example, this is used as the name of the method in a call node, since it cannot directly reference the source string (as in `@-` or `foo=`). This is structured as a variable-length integer byte length, followed by the string itself (_without_ a trailing null byte). +* `string` - A field that is a string. For example, this is used as the name of the method in a call node, since it cannot directly reference the source string (as in `@-` or `foo=`). This is structured as a variable-length integer byte length, followed by the string bytes (_without_ a trailing null byte). * `constant` - A variable-length integer that represents an index in the constant pool. * `constant?` - An optional variable-length integer that represents an index in the constant pool. If it's not present, then a single `0` byte will be written in its place. * `integer` - A field that represents an arbitrary-sized integer. The structure is listed above. @@ -135,23 +135,14 @@ Every field on the node is then appended to the serialized string. The fields ca * `uint8` - A field that is an 8-bit unsigned integer. This is structured as a single byte. * `uint32` - A field that is a 32-bit unsigned integer. This is structured as a variable-length integer. -After the syntax tree, the content pool is serialized. This is a list of constants that were referenced from within the tree. The content pool begins at the offset specified in the header. Constants can be either "owned" (in which case their contents are embedded in the serialization) or "shared" (in which case their contents represent a slice of the source string). The most significant bit of the constant indicates whether it is owned or shared. - -In the case that it is owned, the constant is structured as follows: +After the syntax tree, the content pool is serialized. This is a list of constants that were referenced from within the tree. The content pool begins at the offset specified in the header. Every constant is embedded in the serialization. Each constant is structured as follows: | # bytes | field | | --- | --- | | `4` | the byte offset in the serialization for the contents of the constant | | `4` | the byte length in the serialization | -Note that you will need to mask off the most significant bit for the byte offset in the serialization. In the case that it is shared, the constant is structured as follows: - -| # bytes | field | -| --- | --- | -| `4` | the byte offset in the source string for the contents of the constant | -| `4` | the byte length in the source string | - -After the constant pool, the contents of the owned constants are serialized. This is just a sequence of bytes that represent the contents of the constants. At the end of the serialization, the buffer is null terminated. +After the constant pool, the contents of the constants are serialized. This is just a sequence of bytes that represent the contents of the constants. At the end of the serialization, the buffer is null terminated. ## APIs diff --git a/javascript/src/parsePrism.js b/javascript/src/parsePrism.js index 38084da3f1..269f84c825 100644 --- a/javascript/src/parsePrism.js +++ b/javascript/src/parsePrism.js @@ -43,7 +43,7 @@ export function parsePrism(prism, source, options = {}) { prism.pm_serialize_parse(bufferPointer, sourcePointer, sourceArray.length, optionsPointer); const serializedView = new Uint8Array(prism.memory.buffer, prism.pm_buffer_value(bufferPointer), prism.pm_buffer_length(bufferPointer)); - const result = deserialize(sourceArray, serializedView); + const result = deserialize(serializedView); prism.pm_buffer_free(bufferPointer); prism.free(sourcePointer); diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index af47aeed73..b48dd4c1cb 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -40,13 +40,11 @@ public class Loader { private static final class ConstantPool { private final Loader loader; - private final byte[] source; private final int bufferOffset; private final <%= string_type %>[] cache; - ConstantPool(Loader loader, byte[] source, int bufferOffset, int length) { + ConstantPool(Loader loader, int bufferOffset, int length) { this.loader = loader; - this.source = source; this.bufferOffset = bufferOffset; cache = new <%= string_type %>[length]; } @@ -61,15 +59,10 @@ public class Loader { int length = buffer.getInt(offset + 4); byte[] bytes = new byte[length]; - - if (Integer.compareUnsigned(start, 0x7FFFFFFF) <= 0) { - System.arraycopy(source, start, bytes, 0, length); - } else { - int position = buffer.position(); - buffer.position(start & 0x7FFFFFFF); - buffer.get(bytes, 0, length); - buffer.position(position); - } + int position = buffer.position(); + buffer.position(start); + buffer.get(bytes, 0, length); + buffer.position(position); constant = loader.bytesToName(bytes); cache[index] = constant; @@ -125,7 +118,7 @@ public class Loader { int constantPoolBufferOffset = buffer.getInt(); int constantPoolLength = loadVarUInt(); - this.constantPool = new ConstantPool(this, source.bytes, constantPoolBufferOffset, constantPoolLength); + this.constantPool = new ConstantPool(this, constantPoolBufferOffset, constantPoolLength); Nodes.Node node; if (errors.length == 0) { @@ -146,28 +139,13 @@ public class Loader { return new ParseResult(node, magicComments, dataLocation, errors, warnings, source); } - private byte[] loadEmbeddedString() { + private byte[] loadString() { int length = loadVarUInt(); byte[] bytes = new byte[length]; buffer.get(bytes); return bytes; } - private byte[] loadString() { - switch (buffer.get()) { - case 1: - int start = loadVarUInt(); - int length = loadVarUInt(); - byte[] bytes = new byte[length]; - System.arraycopy(source.bytes, start, bytes, 0, length); - return bytes; - case 2: - return loadEmbeddedString(); - default: - throw new Error("Expected 0 or 1 but was " + buffer.get()); - } - } - private int[] loadLineOffsets() { int count = loadVarUInt(); int[] lineOffsets = new int[count]; @@ -199,7 +177,7 @@ public class Loader { // error messages only contain ASCII characters for (int i = 0; i < count; i++) { Nodes.ErrorType type = Nodes.ERROR_TYPES[loadVarUInt()]; - byte[] bytes = loadEmbeddedString(); + byte[] bytes = loadString(); String message = new String(bytes, StandardCharsets.US_ASCII); Nodes.Location location = loadLocation(); ParseResult.ErrorLevel level = ParseResult.ERROR_LEVELS[buffer.get()]; @@ -218,7 +196,7 @@ public class Loader { // warning messages only contain ASCII characters for (int i = 0; i < count; i++) { Nodes.WarningType type = Nodes.WARNING_TYPES[loadVarUInt() - <%= errors.length %>]; - byte[] bytes = loadEmbeddedString(); + byte[] bytes = loadString(); String message = new String(bytes, StandardCharsets.US_ASCII); Nodes.Location location = loadLocation(); ParseResult.WarningLevel level = ParseResult.WARNING_LEVELS[buffer.get()]; diff --git a/templates/javascript/src/deserialize.js.erb b/templates/javascript/src/deserialize.js.erb index 7aebee750c..2aeb142f8d 100644 --- a/templates/javascript/src/deserialize.js.erb +++ b/templates/javascript/src/deserialize.js.erb @@ -29,8 +29,7 @@ class SerializationBuffer { ["ascii-8bit", "ascii"] ]); - constructor(source, array) { - this.source = source; + constructor(array) { this.array = array; this.index = 0; this.fileEncoding = "utf-8"; @@ -96,32 +95,15 @@ class SerializationBuffer { readStringField(flags) { if (flags === undefined) flags = 0; - const type = this.readByte(); - - switch (type) { - case 1: { - const startOffset = this.readVarInt(); - const length = this.readVarInt(); - return this.decodeString(this.source.slice(startOffset, startOffset + length), flags); - } - case 2: - return this.decodeString(this.readBytes(this.readVarInt()), flags); - default: - throw new Error(`Unknown serialized string type: ${type}`); - } + return this.decodeString(this.readBytes(this.readVarInt()), flags); } scanConstant(constantPoolOffset, constantIndex) { const offset = constantPoolOffset + constantIndex * 8; - let startOffset = this.scanUint32(offset); + const startOffset = this.scanUint32(offset); const length = this.scanUint32(offset + 4); - if (startOffset & (1 << 31)) { - startOffset &= (1 << 31) - 1; - return new TextDecoder().decode(this.array.slice(startOffset, startOffset + length)); - } else { - return new TextDecoder().decode(this.source.slice(startOffset, startOffset + length)); - } + return this.getDecoder(this.fileEncoding).decode(this.array.slice(startOffset, startOffset + length)); } readDouble() { @@ -293,13 +275,12 @@ const warningTypes = [ * Accept two Uint8Arrays, one for the source and one for the serialized format. * Return the AST corresponding to the serialized form. * - * @param {Uint8Array} source * @param {Uint8Array} array * @returns {ParseResult} * @throws {Error} */ -export function deserialize(source, array) { - const buffer = new SerializationBuffer(source, array); +export function deserialize(array) { + const buffer = new SerializationBuffer(array); if (buffer.readString(5) !== "PRISM") { throw new Error("Invalid serialization"); diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index c336662f2c..4e61c89a89 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -46,7 +46,7 @@ module Prism cpool_base = loader.load_uint32 cpool_size = loader.load_varuint - constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size) + constant_pool = ConstantPool.new(serialized, cpool_base, cpool_size) node = loader.load_node(constant_pool, encoding, freeze) #: ProgramNode loader.load_constant_pool(constant_pool) @@ -171,7 +171,7 @@ module Prism cpool_base = loader.load_uint32 cpool_size = loader.load_varuint - constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size) + constant_pool = ConstantPool.new(serialized, cpool_base, cpool_size) node = loader.load_node(constant_pool, encoding, freeze) #: ProgramNode loader.load_constant_pool(constant_pool) @@ -202,14 +202,12 @@ module Prism class ConstantPool # :nodoc: attr_reader :size #: Integer - # @rbs @input: String # @rbs @serialized: String # @rbs @base: Integer # @rbs @pool: Array[Symbol?] - #: (String input, String serialized, Integer base, Integer size) -> void - def initialize(input, serialized, base, size) - @input = input + #: (String serialized, Integer base, Integer size) -> void + def initialize(serialized, base, size) @serialized = serialized @base = base @size = size @@ -224,11 +222,7 @@ module Prism start = @serialized.unpack1("L", offset: offset) #: Integer length = @serialized.unpack1("L", offset: offset + 4) #: Integer - if start.nobits?(1 << 31) - (@input.byteslice(start, length) or raise).force_encoding(encoding).to_sym - else - (@serialized.byteslice(start & ((1 << 31) - 1), length) or raise).force_encoding(encoding).to_sym - end + (@serialized.byteslice(start, length) or raise).force_encoding(encoding).to_sym end end end @@ -289,8 +283,8 @@ module Prism trailer = 0 constant_pool.size.times do |index| - start, length = (io.read(8) or raise).unpack("L2") #: [Integer, Integer] - trailer += length if start.anybits?(1 << 31) + length = (io.read(8) or raise).unpack1("L", offset: 4) #: Integer + trailer += length end io.read(trailer) @@ -388,7 +382,7 @@ module Prism error = ParseError.new( DIAGNOSTIC_TYPES.fetch(load_varuint), - load_embedded_string(encoding), + load_string(encoding), load_location_object(freeze), load_error_level ) @@ -422,7 +416,7 @@ module Prism warning = ParseWarning.new( DIAGNOSTIC_TYPES.fetch(load_varuint), - load_embedded_string(encoding), + load_string(encoding), load_location_object(freeze), load_warning_level ) @@ -507,21 +501,9 @@ module Prism end end - #: (Encoding encoding) -> String - def load_embedded_string(encoding) - (io.read(load_varuint) or raise).force_encoding(encoding).freeze - end - #: (Encoding encoding) -> String def load_string(encoding) - case (type = io.getbyte) - when 1 - (input.byteslice(load_varuint, load_varuint) or raise).force_encoding(encoding).freeze - when 2 - load_embedded_string(encoding) - else - raise "Unknown serialized string type: #{type}" - end + (io.read(load_varuint) or raise).force_encoding(encoding).freeze end #: (bool freeze) -> Location diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index e58bb81f0a..4fe0cb88c1 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -26,28 +26,10 @@ pm_serialize_location(const pm_location_t *location, pm_buffer_t *buffer) { } static void -pm_serialize_string(const pm_parser_t *parser, const pm_string_t *string, pm_buffer_t *buffer) { - switch (string->type) { - case PM_STRING_SHARED: { - pm_buffer_append_byte(buffer, 1); - pm_buffer_append_varuint(buffer, pm_ptrdifft_to_u32(pm_string_source(string) - parser->start)); - pm_buffer_append_varuint(buffer, pm_sizet_to_u32(pm_string_length(string))); - break; - } - case PM_STRING_OWNED: - case PM_STRING_CONSTANT: { - uint32_t length = pm_sizet_to_u32(pm_string_length(string)); - pm_buffer_append_byte(buffer, 2); - pm_buffer_append_varuint(buffer, length); - pm_buffer_append_bytes(buffer, pm_string_source(string), length); - break; - } -#ifdef PRISM_HAS_MMAP - case PM_STRING_MAPPED: - assert(false && "Cannot serialize mapped strings."); - break; -#endif - } +pm_serialize_string(const pm_string_t *string, pm_buffer_t *buffer) { + uint32_t length = pm_sizet_to_u32(pm_string_length(string)); + pm_buffer_append_varuint(buffer, length); + pm_buffer_append_bytes(buffer, pm_string_source(string), length); } static void @@ -102,7 +84,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_serialize_node(parser, (pm_node_t *)((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); } <%- when Prism::Template::StringField -%> - pm_serialize_string(parser, &((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); + pm_serialize_string(&((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); <%- when Prism::Template::NodeListField -%> uint32_t <%= field.name %>_size = pm_sizet_to_u32(((pm_<%= node.human %>_t *)node)-><%= field.name %>.size); pm_buffer_append_varuint(buffer, <%= field.name %>_size); @@ -304,28 +286,12 @@ pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) pm_constant_t *constant = &parser->constant_pool.constants[bucket->id - 1]; size_t buffer_offset = offset + ((((size_t)bucket->id) - 1) * 8); - if (bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED || bucket->type == PM_CONSTANT_POOL_BUCKET_CONSTANT) { - // Since this is an owned or constant constant, we are going to - // write its contents into the buffer after the constant pool. - // So effectively in place of the source offset, we have a - // buffer offset. We will add a leading 1 to indicate that this - // is a buffer offset. - uint32_t content_offset = pm_sizet_to_u32(buffer->length); - uint32_t owned_mask = 1U << 31; - - assert(content_offset < owned_mask); - content_offset |= owned_mask; - - memcpy(buffer->value + buffer_offset, &content_offset, 4); - pm_buffer_append_bytes(buffer, constant->start, constant->length); - } else { - // Since this is a shared constant, we are going to write its - // source offset directly into the buffer. - uint32_t source_offset = pm_ptrdifft_to_u32(constant->start - parser->start); - memcpy(buffer->value + buffer_offset, &source_offset, 4); - } + // Write the constant contents into the buffer after the constant + // pool. In place of the source offset, we store a buffer offset. + uint32_t content_offset = pm_sizet_to_u32(buffer->length); + memcpy(buffer->value + buffer_offset, &content_offset, 4); + pm_buffer_append_bytes(buffer, constant->start, constant->length); - // Now we can write the length of the constant into the buffer. uint32_t constant_length = pm_sizet_to_u32(constant->length); memcpy(buffer->value + buffer_offset + 4, &constant_length, 4); } From 94646f5329eeae9c2d22aa2f1fa4bfb001795ce9 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Sun, 8 Mar 2026 15:35:29 +0100 Subject: [PATCH 094/289] Fix link to node interface Closes #3974 --- templates/lib/prism/node.rb.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/lib/prism/node.rb.erb b/templates/lib/prism/node.rb.erb index 817b59b477..fb13051aba 100644 --- a/templates/lib/prism/node.rb.erb +++ b/templates/lib/prism/node.rb.erb @@ -457,7 +457,7 @@ module Prism # ---------------------------------------------------------------------------------- # :section: Node Interface # These methods are present on all subclasses of Node. - # Read the [node interface docs](rdoc-ref:Node@node-interface) for more information. + # Read the [node interface docs](Node.html#node-interface) for more information. # ---------------------------------------------------------------------------------- # See Node.accept. From 1b492aa3c8f1b40815a0d575887dc30094aa7ef2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 8 Mar 2026 10:52:26 -0400 Subject: [PATCH 095/289] Update types --- rakelib/typecheck.rake | 3 + rbi/generated/prism.rbi | 36 +- rbi/generated/prism/compiler.rbi | 310 +- rbi/generated/prism/desugar_compiler.rbi | 24 +- rbi/generated/prism/dispatcher.rbi | 14 +- rbi/generated/prism/dot_visitor.rbi | 20 +- rbi/generated/prism/dsl.rbi | 148 +- rbi/generated/prism/inspect_visitor.rbi | 4 +- rbi/generated/prism/lex_compat.rbi | 38 +- rbi/generated/prism/mutation_compiler.rbi | 304 +- rbi/generated/prism/node.rbi | 3504 ++++++++--------- rbi/generated/prism/node_ext.rbi | 30 +- rbi/generated/prism/parse_result.rbi | 50 +- rbi/generated/prism/parse_result/comments.rbi | 2 +- rbi/generated/prism/pattern.rbi | 6 +- rbi/generated/prism/reflection.rbi | 2 +- rbi/generated/prism/relocation.rbi | 66 +- rbi/generated/prism/serialize.rbi | 19 +- rbi/generated/prism/visitor.rbi | 4 +- sig/generated/prism/parse_result.rbs | 2 + sig/generated/prism/serialize.rbs | 9 +- 21 files changed, 2296 insertions(+), 2299 deletions(-) diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index be18cc3b25..69bd4a0078 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -345,11 +345,14 @@ namespace :typecheck do desc "Typecheck with Sorbet" task sorbet: :templates do + require "fileutils" + locals = { polyfills: Dir["lib/prism/polyfill/**/*.rb"], gem_rbis: Dir["sorbet/rbi/**/*.rbi"] } + FileUtils.mkdir_p("sorbet") File.write("sorbet/typed_overrides.yml", ERB.new(<<~YAML, trim_mode: "-").result_with_hash(locals)) false: - ./lib/prism/lex_compat.rb diff --git a/rbi/generated/prism.rbi b/rbi/generated/prism.rbi index 355ebd2073..037c50382c 100644 --- a/rbi/generated/prism.rbi +++ b/rbi/generated/prism.rbi @@ -16,7 +16,7 @@ module Prism # resembles the return value of Ripper.lex. # # For supported options, see Prism.parse. - sig { params(source: String, options: T.untyped).returns(LexCompat::Result) } + sig { params(source: String, options: ::T.untyped).returns(LexCompat::Result) } def self.lex_compat(source, **options); end # Load the serialized AST using the source as a reference into a tree. @@ -26,54 +26,54 @@ module Prism VERSION = T.let(nil, String) BACKEND = T.let(nil, Symbol) - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } def self.parse(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } def self.profile(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } def self.lex(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } def self.parse_lex(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } def self.dump(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } def self.parse_comments(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } def self.parse_success?(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(source: String, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + sig { params(source: String, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } def self.parse_failure?(source, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(stream: T.untyped, filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + sig { params(stream: ::T.untyped, filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } def self.parse_stream(stream, filepath: T.unsafe(nil), command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseResult) } def self.parse_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).void } def self.profile_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(LexResult) } def self.lex_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(ParseLexResult) } def self.parse_lex_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(String) } def self.dump_file(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Array[Comment]) } def self.parse_file_comments(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } def self.parse_file_success?(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end - sig { params(filepath: String, command_line: String, encoding: T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } + sig { params(filepath: String, command_line: String, encoding: ::T.any(Encoding, FalseClass), freeze: T::Boolean, frozen_string_literal: T::Boolean, line: Integer, main_script: T::Boolean, partial_script: T::Boolean, scopes: T::Array[T::Array[Symbol]], version: String).returns(T::Boolean) } def self.parse_file_failure?(filepath, command_line: T.unsafe(nil), encoding: T.unsafe(nil), freeze: T.unsafe(nil), frozen_string_literal: T.unsafe(nil), line: T.unsafe(nil), main_script: T.unsafe(nil), partial_script: T.unsafe(nil), scopes: T.unsafe(nil), version: T.unsafe(nil)); end end diff --git a/rbi/generated/prism/compiler.rbi b/rbi/generated/prism/compiler.rbi index 4a47221123..af86919953 100644 --- a/rbi/generated/prism/compiler.rbi +++ b/rbi/generated/prism/compiler.rbi @@ -19,471 +19,471 @@ module Prism # # => [:program, [[[:call, [[:integer], [:arguments, [[:integer]]]]]]]] class Compiler < Visitor # Visit an individual node. - sig { params(arg0: T.nilable(Node)).returns(T.untyped) } + sig { params(arg0: ::T.nilable(Node)).returns(::T.untyped) } def visit(arg0); end # Visit a list of nodes. - sig { params(arg0: T::Array[T.nilable(Node)]).returns(T.untyped) } + sig { params(arg0: T::Array[::T.nilable(Node)]).returns(::T.untyped) } def visit_all(arg0); end # Visit the child nodes of the given node. - sig { params(arg0: Node).returns(T::Array[T.untyped]) } + sig { params(arg0: Node).returns(T::Array[::T.untyped]) } def visit_child_nodes(arg0); end - sig { params(arg0: AliasGlobalVariableNode).returns(T::Array[T.untyped]) } + sig { params(arg0: AliasGlobalVariableNode).returns(T::Array[::T.untyped]) } def visit_alias_global_variable_node(arg0); end - sig { params(arg0: AliasMethodNode).returns(T::Array[T.untyped]) } + sig { params(arg0: AliasMethodNode).returns(T::Array[::T.untyped]) } def visit_alias_method_node(arg0); end - sig { params(arg0: AlternationPatternNode).returns(T::Array[T.untyped]) } + sig { params(arg0: AlternationPatternNode).returns(T::Array[::T.untyped]) } def visit_alternation_pattern_node(arg0); end - sig { params(arg0: AndNode).returns(T::Array[T.untyped]) } + sig { params(arg0: AndNode).returns(T::Array[::T.untyped]) } def visit_and_node(arg0); end - sig { params(arg0: ArgumentsNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ArgumentsNode).returns(T::Array[::T.untyped]) } def visit_arguments_node(arg0); end - sig { params(arg0: ArrayNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ArrayNode).returns(T::Array[::T.untyped]) } def visit_array_node(arg0); end - sig { params(arg0: ArrayPatternNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ArrayPatternNode).returns(T::Array[::T.untyped]) } def visit_array_pattern_node(arg0); end - sig { params(arg0: AssocNode).returns(T::Array[T.untyped]) } + sig { params(arg0: AssocNode).returns(T::Array[::T.untyped]) } def visit_assoc_node(arg0); end - sig { params(arg0: AssocSplatNode).returns(T::Array[T.untyped]) } + sig { params(arg0: AssocSplatNode).returns(T::Array[::T.untyped]) } def visit_assoc_splat_node(arg0); end - sig { params(arg0: BackReferenceReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BackReferenceReadNode).returns(T::Array[::T.untyped]) } def visit_back_reference_read_node(arg0); end - sig { params(arg0: BeginNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BeginNode).returns(T::Array[::T.untyped]) } def visit_begin_node(arg0); end - sig { params(arg0: BlockArgumentNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BlockArgumentNode).returns(T::Array[::T.untyped]) } def visit_block_argument_node(arg0); end - sig { params(arg0: BlockLocalVariableNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BlockLocalVariableNode).returns(T::Array[::T.untyped]) } def visit_block_local_variable_node(arg0); end - sig { params(arg0: BlockNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BlockNode).returns(T::Array[::T.untyped]) } def visit_block_node(arg0); end - sig { params(arg0: BlockParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BlockParameterNode).returns(T::Array[::T.untyped]) } def visit_block_parameter_node(arg0); end - sig { params(arg0: BlockParametersNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BlockParametersNode).returns(T::Array[::T.untyped]) } def visit_block_parameters_node(arg0); end - sig { params(arg0: BreakNode).returns(T::Array[T.untyped]) } + sig { params(arg0: BreakNode).returns(T::Array[::T.untyped]) } def visit_break_node(arg0); end - sig { params(arg0: CallAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CallAndWriteNode).returns(T::Array[::T.untyped]) } def visit_call_and_write_node(arg0); end - sig { params(arg0: CallNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CallNode).returns(T::Array[::T.untyped]) } def visit_call_node(arg0); end - sig { params(arg0: CallOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CallOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_call_operator_write_node(arg0); end - sig { params(arg0: CallOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CallOrWriteNode).returns(T::Array[::T.untyped]) } def visit_call_or_write_node(arg0); end - sig { params(arg0: CallTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CallTargetNode).returns(T::Array[::T.untyped]) } def visit_call_target_node(arg0); end - sig { params(arg0: CapturePatternNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CapturePatternNode).returns(T::Array[::T.untyped]) } def visit_capture_pattern_node(arg0); end - sig { params(arg0: CaseMatchNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CaseMatchNode).returns(T::Array[::T.untyped]) } def visit_case_match_node(arg0); end - sig { params(arg0: CaseNode).returns(T::Array[T.untyped]) } + sig { params(arg0: CaseNode).returns(T::Array[::T.untyped]) } def visit_case_node(arg0); end - sig { params(arg0: ClassNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ClassNode).returns(T::Array[::T.untyped]) } def visit_class_node(arg0); end - sig { params(arg0: ClassVariableAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ClassVariableAndWriteNode).returns(T::Array[::T.untyped]) } def visit_class_variable_and_write_node(arg0); end - sig { params(arg0: ClassVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ClassVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_class_variable_operator_write_node(arg0); end - sig { params(arg0: ClassVariableOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ClassVariableOrWriteNode).returns(T::Array[::T.untyped]) } def visit_class_variable_or_write_node(arg0); end - sig { params(arg0: ClassVariableReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ClassVariableReadNode).returns(T::Array[::T.untyped]) } def visit_class_variable_read_node(arg0); end - sig { params(arg0: ClassVariableTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ClassVariableTargetNode).returns(T::Array[::T.untyped]) } def visit_class_variable_target_node(arg0); end - sig { params(arg0: ClassVariableWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ClassVariableWriteNode).returns(T::Array[::T.untyped]) } def visit_class_variable_write_node(arg0); end - sig { params(arg0: ConstantAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantAndWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_and_write_node(arg0); end - sig { params(arg0: ConstantOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_operator_write_node(arg0); end - sig { params(arg0: ConstantOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantOrWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_or_write_node(arg0); end - sig { params(arg0: ConstantPathAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantPathAndWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_path_and_write_node(arg0); end - sig { params(arg0: ConstantPathNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantPathNode).returns(T::Array[::T.untyped]) } def visit_constant_path_node(arg0); end - sig { params(arg0: ConstantPathOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantPathOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_path_operator_write_node(arg0); end - sig { params(arg0: ConstantPathOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantPathOrWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_path_or_write_node(arg0); end - sig { params(arg0: ConstantPathTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantPathTargetNode).returns(T::Array[::T.untyped]) } def visit_constant_path_target_node(arg0); end - sig { params(arg0: ConstantPathWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantPathWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_path_write_node(arg0); end - sig { params(arg0: ConstantReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantReadNode).returns(T::Array[::T.untyped]) } def visit_constant_read_node(arg0); end - sig { params(arg0: ConstantTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantTargetNode).returns(T::Array[::T.untyped]) } def visit_constant_target_node(arg0); end - sig { params(arg0: ConstantWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ConstantWriteNode).returns(T::Array[::T.untyped]) } def visit_constant_write_node(arg0); end - sig { params(arg0: DefNode).returns(T::Array[T.untyped]) } + sig { params(arg0: DefNode).returns(T::Array[::T.untyped]) } def visit_def_node(arg0); end - sig { params(arg0: DefinedNode).returns(T::Array[T.untyped]) } + sig { params(arg0: DefinedNode).returns(T::Array[::T.untyped]) } def visit_defined_node(arg0); end - sig { params(arg0: ElseNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ElseNode).returns(T::Array[::T.untyped]) } def visit_else_node(arg0); end - sig { params(arg0: EmbeddedStatementsNode).returns(T::Array[T.untyped]) } + sig { params(arg0: EmbeddedStatementsNode).returns(T::Array[::T.untyped]) } def visit_embedded_statements_node(arg0); end - sig { params(arg0: EmbeddedVariableNode).returns(T::Array[T.untyped]) } + sig { params(arg0: EmbeddedVariableNode).returns(T::Array[::T.untyped]) } def visit_embedded_variable_node(arg0); end - sig { params(arg0: EnsureNode).returns(T::Array[T.untyped]) } + sig { params(arg0: EnsureNode).returns(T::Array[::T.untyped]) } def visit_ensure_node(arg0); end - sig { params(arg0: FalseNode).returns(T::Array[T.untyped]) } + sig { params(arg0: FalseNode).returns(T::Array[::T.untyped]) } def visit_false_node(arg0); end - sig { params(arg0: FindPatternNode).returns(T::Array[T.untyped]) } + sig { params(arg0: FindPatternNode).returns(T::Array[::T.untyped]) } def visit_find_pattern_node(arg0); end - sig { params(arg0: FlipFlopNode).returns(T::Array[T.untyped]) } + sig { params(arg0: FlipFlopNode).returns(T::Array[::T.untyped]) } def visit_flip_flop_node(arg0); end - sig { params(arg0: FloatNode).returns(T::Array[T.untyped]) } + sig { params(arg0: FloatNode).returns(T::Array[::T.untyped]) } def visit_float_node(arg0); end - sig { params(arg0: ForNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ForNode).returns(T::Array[::T.untyped]) } def visit_for_node(arg0); end - sig { params(arg0: ForwardingArgumentsNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ForwardingArgumentsNode).returns(T::Array[::T.untyped]) } def visit_forwarding_arguments_node(arg0); end - sig { params(arg0: ForwardingParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ForwardingParameterNode).returns(T::Array[::T.untyped]) } def visit_forwarding_parameter_node(arg0); end - sig { params(arg0: ForwardingSuperNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ForwardingSuperNode).returns(T::Array[::T.untyped]) } def visit_forwarding_super_node(arg0); end - sig { params(arg0: GlobalVariableAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: GlobalVariableAndWriteNode).returns(T::Array[::T.untyped]) } def visit_global_variable_and_write_node(arg0); end - sig { params(arg0: GlobalVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: GlobalVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_global_variable_operator_write_node(arg0); end - sig { params(arg0: GlobalVariableOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: GlobalVariableOrWriteNode).returns(T::Array[::T.untyped]) } def visit_global_variable_or_write_node(arg0); end - sig { params(arg0: GlobalVariableReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: GlobalVariableReadNode).returns(T::Array[::T.untyped]) } def visit_global_variable_read_node(arg0); end - sig { params(arg0: GlobalVariableTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: GlobalVariableTargetNode).returns(T::Array[::T.untyped]) } def visit_global_variable_target_node(arg0); end - sig { params(arg0: GlobalVariableWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: GlobalVariableWriteNode).returns(T::Array[::T.untyped]) } def visit_global_variable_write_node(arg0); end - sig { params(arg0: HashNode).returns(T::Array[T.untyped]) } + sig { params(arg0: HashNode).returns(T::Array[::T.untyped]) } def visit_hash_node(arg0); end - sig { params(arg0: HashPatternNode).returns(T::Array[T.untyped]) } + sig { params(arg0: HashPatternNode).returns(T::Array[::T.untyped]) } def visit_hash_pattern_node(arg0); end - sig { params(arg0: IfNode).returns(T::Array[T.untyped]) } + sig { params(arg0: IfNode).returns(T::Array[::T.untyped]) } def visit_if_node(arg0); end - sig { params(arg0: ImaginaryNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ImaginaryNode).returns(T::Array[::T.untyped]) } def visit_imaginary_node(arg0); end - sig { params(arg0: ImplicitNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ImplicitNode).returns(T::Array[::T.untyped]) } def visit_implicit_node(arg0); end - sig { params(arg0: ImplicitRestNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ImplicitRestNode).returns(T::Array[::T.untyped]) } def visit_implicit_rest_node(arg0); end - sig { params(arg0: InNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InNode).returns(T::Array[::T.untyped]) } def visit_in_node(arg0); end - sig { params(arg0: IndexAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: IndexAndWriteNode).returns(T::Array[::T.untyped]) } def visit_index_and_write_node(arg0); end - sig { params(arg0: IndexOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: IndexOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_index_operator_write_node(arg0); end - sig { params(arg0: IndexOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: IndexOrWriteNode).returns(T::Array[::T.untyped]) } def visit_index_or_write_node(arg0); end - sig { params(arg0: IndexTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: IndexTargetNode).returns(T::Array[::T.untyped]) } def visit_index_target_node(arg0); end - sig { params(arg0: InstanceVariableAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InstanceVariableAndWriteNode).returns(T::Array[::T.untyped]) } def visit_instance_variable_and_write_node(arg0); end - sig { params(arg0: InstanceVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InstanceVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_instance_variable_operator_write_node(arg0); end - sig { params(arg0: InstanceVariableOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InstanceVariableOrWriteNode).returns(T::Array[::T.untyped]) } def visit_instance_variable_or_write_node(arg0); end - sig { params(arg0: InstanceVariableReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InstanceVariableReadNode).returns(T::Array[::T.untyped]) } def visit_instance_variable_read_node(arg0); end - sig { params(arg0: InstanceVariableTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InstanceVariableTargetNode).returns(T::Array[::T.untyped]) } def visit_instance_variable_target_node(arg0); end - sig { params(arg0: InstanceVariableWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InstanceVariableWriteNode).returns(T::Array[::T.untyped]) } def visit_instance_variable_write_node(arg0); end - sig { params(arg0: IntegerNode).returns(T::Array[T.untyped]) } + sig { params(arg0: IntegerNode).returns(T::Array[::T.untyped]) } def visit_integer_node(arg0); end - sig { params(arg0: InterpolatedMatchLastLineNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InterpolatedMatchLastLineNode).returns(T::Array[::T.untyped]) } def visit_interpolated_match_last_line_node(arg0); end - sig { params(arg0: InterpolatedRegularExpressionNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InterpolatedRegularExpressionNode).returns(T::Array[::T.untyped]) } def visit_interpolated_regular_expression_node(arg0); end - sig { params(arg0: InterpolatedStringNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InterpolatedStringNode).returns(T::Array[::T.untyped]) } def visit_interpolated_string_node(arg0); end - sig { params(arg0: InterpolatedSymbolNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InterpolatedSymbolNode).returns(T::Array[::T.untyped]) } def visit_interpolated_symbol_node(arg0); end - sig { params(arg0: InterpolatedXStringNode).returns(T::Array[T.untyped]) } + sig { params(arg0: InterpolatedXStringNode).returns(T::Array[::T.untyped]) } def visit_interpolated_x_string_node(arg0); end - sig { params(arg0: ItLocalVariableReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ItLocalVariableReadNode).returns(T::Array[::T.untyped]) } def visit_it_local_variable_read_node(arg0); end - sig { params(arg0: ItParametersNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ItParametersNode).returns(T::Array[::T.untyped]) } def visit_it_parameters_node(arg0); end - sig { params(arg0: KeywordHashNode).returns(T::Array[T.untyped]) } + sig { params(arg0: KeywordHashNode).returns(T::Array[::T.untyped]) } def visit_keyword_hash_node(arg0); end - sig { params(arg0: KeywordRestParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: KeywordRestParameterNode).returns(T::Array[::T.untyped]) } def visit_keyword_rest_parameter_node(arg0); end - sig { params(arg0: LambdaNode).returns(T::Array[T.untyped]) } + sig { params(arg0: LambdaNode).returns(T::Array[::T.untyped]) } def visit_lambda_node(arg0); end - sig { params(arg0: LocalVariableAndWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: LocalVariableAndWriteNode).returns(T::Array[::T.untyped]) } def visit_local_variable_and_write_node(arg0); end - sig { params(arg0: LocalVariableOperatorWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: LocalVariableOperatorWriteNode).returns(T::Array[::T.untyped]) } def visit_local_variable_operator_write_node(arg0); end - sig { params(arg0: LocalVariableOrWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: LocalVariableOrWriteNode).returns(T::Array[::T.untyped]) } def visit_local_variable_or_write_node(arg0); end - sig { params(arg0: LocalVariableReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: LocalVariableReadNode).returns(T::Array[::T.untyped]) } def visit_local_variable_read_node(arg0); end - sig { params(arg0: LocalVariableTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: LocalVariableTargetNode).returns(T::Array[::T.untyped]) } def visit_local_variable_target_node(arg0); end - sig { params(arg0: LocalVariableWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: LocalVariableWriteNode).returns(T::Array[::T.untyped]) } def visit_local_variable_write_node(arg0); end - sig { params(arg0: MatchLastLineNode).returns(T::Array[T.untyped]) } + sig { params(arg0: MatchLastLineNode).returns(T::Array[::T.untyped]) } def visit_match_last_line_node(arg0); end - sig { params(arg0: MatchPredicateNode).returns(T::Array[T.untyped]) } + sig { params(arg0: MatchPredicateNode).returns(T::Array[::T.untyped]) } def visit_match_predicate_node(arg0); end - sig { params(arg0: MatchRequiredNode).returns(T::Array[T.untyped]) } + sig { params(arg0: MatchRequiredNode).returns(T::Array[::T.untyped]) } def visit_match_required_node(arg0); end - sig { params(arg0: MatchWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: MatchWriteNode).returns(T::Array[::T.untyped]) } def visit_match_write_node(arg0); end - sig { params(arg0: MissingNode).returns(T::Array[T.untyped]) } + sig { params(arg0: MissingNode).returns(T::Array[::T.untyped]) } def visit_missing_node(arg0); end - sig { params(arg0: ModuleNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ModuleNode).returns(T::Array[::T.untyped]) } def visit_module_node(arg0); end - sig { params(arg0: MultiTargetNode).returns(T::Array[T.untyped]) } + sig { params(arg0: MultiTargetNode).returns(T::Array[::T.untyped]) } def visit_multi_target_node(arg0); end - sig { params(arg0: MultiWriteNode).returns(T::Array[T.untyped]) } + sig { params(arg0: MultiWriteNode).returns(T::Array[::T.untyped]) } def visit_multi_write_node(arg0); end - sig { params(arg0: NextNode).returns(T::Array[T.untyped]) } + sig { params(arg0: NextNode).returns(T::Array[::T.untyped]) } def visit_next_node(arg0); end - sig { params(arg0: NilNode).returns(T::Array[T.untyped]) } + sig { params(arg0: NilNode).returns(T::Array[::T.untyped]) } def visit_nil_node(arg0); end - sig { params(arg0: NoBlockParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: NoBlockParameterNode).returns(T::Array[::T.untyped]) } def visit_no_block_parameter_node(arg0); end - sig { params(arg0: NoKeywordsParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: NoKeywordsParameterNode).returns(T::Array[::T.untyped]) } def visit_no_keywords_parameter_node(arg0); end - sig { params(arg0: NumberedParametersNode).returns(T::Array[T.untyped]) } + sig { params(arg0: NumberedParametersNode).returns(T::Array[::T.untyped]) } def visit_numbered_parameters_node(arg0); end - sig { params(arg0: NumberedReferenceReadNode).returns(T::Array[T.untyped]) } + sig { params(arg0: NumberedReferenceReadNode).returns(T::Array[::T.untyped]) } def visit_numbered_reference_read_node(arg0); end - sig { params(arg0: OptionalKeywordParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: OptionalKeywordParameterNode).returns(T::Array[::T.untyped]) } def visit_optional_keyword_parameter_node(arg0); end - sig { params(arg0: OptionalParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: OptionalParameterNode).returns(T::Array[::T.untyped]) } def visit_optional_parameter_node(arg0); end - sig { params(arg0: OrNode).returns(T::Array[T.untyped]) } + sig { params(arg0: OrNode).returns(T::Array[::T.untyped]) } def visit_or_node(arg0); end - sig { params(arg0: ParametersNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ParametersNode).returns(T::Array[::T.untyped]) } def visit_parameters_node(arg0); end - sig { params(arg0: ParenthesesNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ParenthesesNode).returns(T::Array[::T.untyped]) } def visit_parentheses_node(arg0); end - sig { params(arg0: PinnedExpressionNode).returns(T::Array[T.untyped]) } + sig { params(arg0: PinnedExpressionNode).returns(T::Array[::T.untyped]) } def visit_pinned_expression_node(arg0); end - sig { params(arg0: PinnedVariableNode).returns(T::Array[T.untyped]) } + sig { params(arg0: PinnedVariableNode).returns(T::Array[::T.untyped]) } def visit_pinned_variable_node(arg0); end - sig { params(arg0: PostExecutionNode).returns(T::Array[T.untyped]) } + sig { params(arg0: PostExecutionNode).returns(T::Array[::T.untyped]) } def visit_post_execution_node(arg0); end - sig { params(arg0: PreExecutionNode).returns(T::Array[T.untyped]) } + sig { params(arg0: PreExecutionNode).returns(T::Array[::T.untyped]) } def visit_pre_execution_node(arg0); end - sig { params(arg0: ProgramNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ProgramNode).returns(T::Array[::T.untyped]) } def visit_program_node(arg0); end - sig { params(arg0: RangeNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RangeNode).returns(T::Array[::T.untyped]) } def visit_range_node(arg0); end - sig { params(arg0: RationalNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RationalNode).returns(T::Array[::T.untyped]) } def visit_rational_node(arg0); end - sig { params(arg0: RedoNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RedoNode).returns(T::Array[::T.untyped]) } def visit_redo_node(arg0); end - sig { params(arg0: RegularExpressionNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RegularExpressionNode).returns(T::Array[::T.untyped]) } def visit_regular_expression_node(arg0); end - sig { params(arg0: RequiredKeywordParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RequiredKeywordParameterNode).returns(T::Array[::T.untyped]) } def visit_required_keyword_parameter_node(arg0); end - sig { params(arg0: RequiredParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RequiredParameterNode).returns(T::Array[::T.untyped]) } def visit_required_parameter_node(arg0); end - sig { params(arg0: RescueModifierNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RescueModifierNode).returns(T::Array[::T.untyped]) } def visit_rescue_modifier_node(arg0); end - sig { params(arg0: RescueNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RescueNode).returns(T::Array[::T.untyped]) } def visit_rescue_node(arg0); end - sig { params(arg0: RestParameterNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RestParameterNode).returns(T::Array[::T.untyped]) } def visit_rest_parameter_node(arg0); end - sig { params(arg0: RetryNode).returns(T::Array[T.untyped]) } + sig { params(arg0: RetryNode).returns(T::Array[::T.untyped]) } def visit_retry_node(arg0); end - sig { params(arg0: ReturnNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ReturnNode).returns(T::Array[::T.untyped]) } def visit_return_node(arg0); end - sig { params(arg0: SelfNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SelfNode).returns(T::Array[::T.untyped]) } def visit_self_node(arg0); end - sig { params(arg0: ShareableConstantNode).returns(T::Array[T.untyped]) } + sig { params(arg0: ShareableConstantNode).returns(T::Array[::T.untyped]) } def visit_shareable_constant_node(arg0); end - sig { params(arg0: SingletonClassNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SingletonClassNode).returns(T::Array[::T.untyped]) } def visit_singleton_class_node(arg0); end - sig { params(arg0: SourceEncodingNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SourceEncodingNode).returns(T::Array[::T.untyped]) } def visit_source_encoding_node(arg0); end - sig { params(arg0: SourceFileNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SourceFileNode).returns(T::Array[::T.untyped]) } def visit_source_file_node(arg0); end - sig { params(arg0: SourceLineNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SourceLineNode).returns(T::Array[::T.untyped]) } def visit_source_line_node(arg0); end - sig { params(arg0: SplatNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SplatNode).returns(T::Array[::T.untyped]) } def visit_splat_node(arg0); end - sig { params(arg0: StatementsNode).returns(T::Array[T.untyped]) } + sig { params(arg0: StatementsNode).returns(T::Array[::T.untyped]) } def visit_statements_node(arg0); end - sig { params(arg0: StringNode).returns(T::Array[T.untyped]) } + sig { params(arg0: StringNode).returns(T::Array[::T.untyped]) } def visit_string_node(arg0); end - sig { params(arg0: SuperNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SuperNode).returns(T::Array[::T.untyped]) } def visit_super_node(arg0); end - sig { params(arg0: SymbolNode).returns(T::Array[T.untyped]) } + sig { params(arg0: SymbolNode).returns(T::Array[::T.untyped]) } def visit_symbol_node(arg0); end - sig { params(arg0: TrueNode).returns(T::Array[T.untyped]) } + sig { params(arg0: TrueNode).returns(T::Array[::T.untyped]) } def visit_true_node(arg0); end - sig { params(arg0: UndefNode).returns(T::Array[T.untyped]) } + sig { params(arg0: UndefNode).returns(T::Array[::T.untyped]) } def visit_undef_node(arg0); end - sig { params(arg0: UnlessNode).returns(T::Array[T.untyped]) } + sig { params(arg0: UnlessNode).returns(T::Array[::T.untyped]) } def visit_unless_node(arg0); end - sig { params(arg0: UntilNode).returns(T::Array[T.untyped]) } + sig { params(arg0: UntilNode).returns(T::Array[::T.untyped]) } def visit_until_node(arg0); end - sig { params(arg0: WhenNode).returns(T::Array[T.untyped]) } + sig { params(arg0: WhenNode).returns(T::Array[::T.untyped]) } def visit_when_node(arg0); end - sig { params(arg0: WhileNode).returns(T::Array[T.untyped]) } + sig { params(arg0: WhileNode).returns(T::Array[::T.untyped]) } def visit_while_node(arg0); end - sig { params(arg0: XStringNode).returns(T::Array[T.untyped]) } + sig { params(arg0: XStringNode).returns(T::Array[::T.untyped]) } def visit_x_string_node(arg0); end - sig { params(arg0: YieldNode).returns(T::Array[T.untyped]) } + sig { params(arg0: YieldNode).returns(T::Array[::T.untyped]) } def visit_yield_node(arg0); end end end diff --git a/rbi/generated/prism/desugar_compiler.rbi b/rbi/generated/prism/desugar_compiler.rbi index 3e7c745cc9..167624b9b6 100644 --- a/rbi/generated/prism/desugar_compiler.rbi +++ b/rbi/generated/prism/desugar_compiler.rbi @@ -4,7 +4,7 @@ module Prism class DesugarAndWriteNode include DSL - sig { returns(T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode)) } + sig { returns(::T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode)) } attr_reader :node sig { returns(Source) } @@ -16,10 +16,10 @@ module Prism sig { returns(Symbol) } attr_reader :write_class - sig { returns(T::Hash[Symbol, T.untyped]) } + sig { returns(T::Hash[Symbol, ::T.untyped]) } attr_reader :arguments - sig { params(node: T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + sig { params(node: ::T.any(ClassVariableAndWriteNode, ConstantAndWriteNode, GlobalVariableAndWriteNode, InstanceVariableAndWriteNode, LocalVariableAndWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } def initialize(node, default_source, read_class, write_class, **arguments); end # Desugar `x &&= y` to `x && x = y` @@ -30,7 +30,7 @@ module Prism class DesugarOrWriteDefinedNode include DSL - sig { returns(T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode)) } + sig { returns(::T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode)) } attr_reader :node sig { returns(Source) } @@ -42,10 +42,10 @@ module Prism sig { returns(Symbol) } attr_reader :write_class - sig { returns(T::Hash[Symbol, T.untyped]) } + sig { returns(T::Hash[Symbol, ::T.untyped]) } attr_reader :arguments - sig { params(node: T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + sig { params(node: ::T.any(ClassVariableOrWriteNode, ConstantOrWriteNode, GlobalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } def initialize(node, default_source, read_class, write_class, **arguments); end # Desugar `x ||= y` to `defined?(x) ? x : x = y` @@ -56,7 +56,7 @@ module Prism class DesugarOperatorWriteNode include DSL - sig { returns(T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode)) } + sig { returns(::T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode)) } attr_reader :node sig { returns(Source) } @@ -68,10 +68,10 @@ module Prism sig { returns(Symbol) } attr_reader :write_class - sig { returns(T::Hash[Symbol, T.untyped]) } + sig { returns(T::Hash[Symbol, ::T.untyped]) } attr_reader :arguments - sig { params(node: T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + sig { params(node: ::T.any(ClassVariableOperatorWriteNode, ConstantOperatorWriteNode, GlobalVariableOperatorWriteNode, InstanceVariableOperatorWriteNode, LocalVariableOperatorWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } def initialize(node, default_source, read_class, write_class, **arguments); end # Desugar `x += y` to `x = x + y` @@ -82,7 +82,7 @@ module Prism class DesugarOrWriteNode include DSL - sig { returns(T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode)) } + sig { returns(::T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode)) } attr_reader :node sig { returns(Source) } @@ -94,10 +94,10 @@ module Prism sig { returns(Symbol) } attr_reader :write_class - sig { returns(T::Hash[Symbol, T.untyped]) } + sig { returns(T::Hash[Symbol, ::T.untyped]) } attr_reader :arguments - sig { params(node: T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: T.untyped).void } + sig { params(node: ::T.any(InstanceVariableOrWriteNode, LocalVariableOrWriteNode), default_source: Source, read_class: Symbol, write_class: Symbol, arguments: ::T.untyped).void } def initialize(node, default_source, read_class, write_class, **arguments); end # Desugar `x ||= y` to `x || x = y` diff --git a/rbi/generated/prism/dispatcher.rbi b/rbi/generated/prism/dispatcher.rbi index 14ef40c9c1..2dfeedf26f 100644 --- a/rbi/generated/prism/dispatcher.rbi +++ b/rbi/generated/prism/dispatcher.rbi @@ -35,7 +35,7 @@ module Prism class Dispatcher < Visitor # A hash mapping event names to arrays of listeners that should be notified # when that event is fired. - sig { returns(T::Hash[Symbol, T::Array[T.untyped]]) } + sig { returns(T::Hash[Symbol, T::Array[::T.untyped]]) } attr_reader :listeners # Initialize a new dispatcher. @@ -43,20 +43,20 @@ module Prism def initialize; end # Register a listener for one or more events. - sig { params(arg0: T.untyped, args: Symbol).void } + sig { params(arg0: ::T.untyped, args: Symbol).void } def register(arg0, *args); end # Register all public methods of a listener that match the pattern # `on__(enter|leave)`. - sig { params(arg0: T.untyped).void } + sig { params(arg0: ::T.untyped).void } def register_public_methods(arg0); end # Register a listener for the given events. - sig { params(arg0: T.untyped, arg1: T::Array[Symbol]).void } + sig { params(arg0: ::T.untyped, arg1: T::Array[Symbol]).void } def register_events(arg0, arg1); end # Walks `root` dispatching events to all registered listeners. - sig { params(node: T.nilable(Node)).returns(T.untyped) } + sig { params(node: ::T.nilable(Node)).returns(::T.untyped) } def dispatch(node); end # Dispatches a single event for `node` to all registered listeners. @@ -520,10 +520,10 @@ module Prism def visit_yield_node(node); end class DispatchOnce < Visitor - sig { returns(T::Hash[Symbol, T::Array[T.untyped]]) } + sig { returns(T::Hash[Symbol, T::Array[::T.untyped]]) } attr_reader :listeners - sig { params(listeners: T::Hash[Symbol, T::Array[T.untyped]]).void } + sig { params(listeners: T::Hash[Symbol, T::Array[::T.untyped]]).void } def initialize(listeners); end # Dispatch enter and leave events for AliasGlobalVariableNode nodes. diff --git a/rbi/generated/prism/dot_visitor.rbi b/rbi/generated/prism/dot_visitor.rbi index 835dd112b6..d707be5a1a 100644 --- a/rbi/generated/prism/dot_visitor.rbi +++ b/rbi/generated/prism/dot_visitor.rbi @@ -8,13 +8,13 @@ module Prism sig { returns(String) } attr_reader :name - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } attr_reader :value sig { returns(T::Boolean) } attr_reader :port - sig { params(name: String, value: T.nilable(String), port: T::Boolean).void } + sig { params(name: String, value: ::T.nilable(String), port: T::Boolean).void } def initialize(name, value, port); end sig { returns(String) } @@ -31,7 +31,7 @@ module Prism sig { params(name: String).void } def initialize(name); end - sig { params(name: String, value: T.nilable(String), port: T::Boolean).void } + sig { params(name: String, value: ::T.nilable(String), port: T::Boolean).void } def field(name, value = T.unsafe(nil), port: T.unsafe(nil)); end sig { returns(String) } @@ -552,7 +552,7 @@ module Prism # Inspect a node that has call_node_flags flags to display the flags as a # comma-separated list. - sig { params(node: T.any(CallAndWriteNode, CallNode, CallOperatorWriteNode, CallOrWriteNode, CallTargetNode, IndexAndWriteNode, IndexOperatorWriteNode, IndexOrWriteNode, IndexTargetNode)).returns(String) } + sig { params(node: ::T.any(CallAndWriteNode, CallNode, CallOperatorWriteNode, CallOrWriteNode, CallTargetNode, IndexAndWriteNode, IndexOperatorWriteNode, IndexOrWriteNode, IndexTargetNode)).returns(String) } private def call_node_flags_inspect(node); end # Inspect a node that has encoding_flags flags to display the flags as a @@ -562,7 +562,7 @@ module Prism # Inspect a node that has integer_base_flags flags to display the flags as a # comma-separated list. - sig { params(node: T.any(IntegerNode, RationalNode)).returns(String) } + sig { params(node: ::T.any(IntegerNode, RationalNode)).returns(String) } private def integer_base_flags_inspect(node); end # Inspect a node that has interpolated_string_node_flags flags to display the flags as a @@ -577,12 +577,12 @@ module Prism # Inspect a node that has loop_flags flags to display the flags as a # comma-separated list. - sig { params(node: T.any(UntilNode, WhileNode)).returns(String) } + sig { params(node: ::T.any(UntilNode, WhileNode)).returns(String) } private def loop_flags_inspect(node); end # Inspect a node that has parameter_flags flags to display the flags as a # comma-separated list. - sig { params(node: T.any(BlockLocalVariableNode, BlockParameterNode, KeywordRestParameterNode, OptionalKeywordParameterNode, OptionalParameterNode, RequiredKeywordParameterNode, RequiredParameterNode, RestParameterNode)).returns(String) } + sig { params(node: ::T.any(BlockLocalVariableNode, BlockParameterNode, KeywordRestParameterNode, OptionalKeywordParameterNode, OptionalParameterNode, RequiredKeywordParameterNode, RequiredParameterNode, RestParameterNode)).returns(String) } private def parameter_flags_inspect(node); end # Inspect a node that has parentheses_node_flags flags to display the flags as a @@ -592,12 +592,12 @@ module Prism # Inspect a node that has range_flags flags to display the flags as a # comma-separated list. - sig { params(node: T.any(FlipFlopNode, RangeNode)).returns(String) } + sig { params(node: ::T.any(FlipFlopNode, RangeNode)).returns(String) } private def range_flags_inspect(node); end # Inspect a node that has regular_expression_flags flags to display the flags as a # comma-separated list. - sig { params(node: T.any(InterpolatedMatchLastLineNode, InterpolatedRegularExpressionNode, MatchLastLineNode, RegularExpressionNode)).returns(String) } + sig { params(node: ::T.any(InterpolatedMatchLastLineNode, InterpolatedRegularExpressionNode, MatchLastLineNode, RegularExpressionNode)).returns(String) } private def regular_expression_flags_inspect(node); end # Inspect a node that has shareable_constant_node_flags flags to display the flags as a @@ -607,7 +607,7 @@ module Prism # Inspect a node that has string_flags flags to display the flags as a # comma-separated list. - sig { params(node: T.any(SourceFileNode, StringNode)).returns(String) } + sig { params(node: ::T.any(SourceFileNode, StringNode)).returns(String) } private def string_flags_inspect(node); end # Inspect a node that has symbol_flags flags to display the flags as a diff --git a/rbi/generated/prism/dsl.rbi b/rbi/generated/prism/dsl.rbi index d03b4f5a47..ac4e68bfa7 100644 --- a/rbi/generated/prism/dsl.rbi +++ b/rbi/generated/prism/dsl.rbi @@ -62,11 +62,11 @@ module Prism def location(source: T.unsafe(nil), start_offset: T.unsafe(nil), length: T.unsafe(nil)); end # Create a new AliasGlobalVariableNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } def alias_global_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end # Create a new AliasMethodNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(SymbolNode, InterpolatedSymbolNode), old_name: T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(SymbolNode, InterpolatedSymbolNode), old_name: ::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } def alias_method_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end # Create a new AlternationPatternNode node. @@ -82,19 +82,19 @@ module Prism def arguments_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil)); end # Create a new ArrayNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayNode) } def array_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new ArrayPatternNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayPatternNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: ::T.nilable(Node), posts: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayPatternNode) } def array_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), requireds: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new AssocNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: T.nilable(Location)).returns(AssocNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: ::T.nilable(Location)).returns(AssocNode) } def assoc_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), key: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new AssocSplatNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } def assoc_splat_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new BackReferenceReadNode node. @@ -102,11 +102,11 @@ module Prism def back_reference_read_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end # Create a new BeginNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), rescue_clause: T.nilable(RescueNode), else_clause: T.nilable(ElseNode), ensure_clause: T.nilable(EnsureNode), end_keyword_loc: T.nilable(Location)).returns(BeginNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), rescue_clause: ::T.nilable(RescueNode), else_clause: ::T.nilable(ElseNode), ensure_clause: ::T.nilable(EnsureNode), end_keyword_loc: ::T.nilable(Location)).returns(BeginNode) } def begin_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), begin_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), rescue_clause: T.unsafe(nil), else_clause: T.unsafe(nil), ensure_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new BlockArgumentNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: ::T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } def block_argument_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new BlockLocalVariableNode node. @@ -114,35 +114,35 @@ module Prism def block_local_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end # Create a new BlockNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } def block_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new BlockParameterNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } def block_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new BlockParametersNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(BlockParametersNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: ::T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(BlockParametersNode) } def block_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parameters: T.unsafe(nil), locals: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new BreakNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } def break_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end # Create a new CallAndWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } def call_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new CallNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), name: Symbol, message_loc: T.nilable(Location), opening_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), closing_loc: T.nilable(Location), equal_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), name: Symbol, message_loc: ::T.nilable(Location), opening_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), closing_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } def call_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), block: T.unsafe(nil)); end # Create a new CallOperatorWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } def call_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new CallOrWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } def call_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new CallTargetNode node. @@ -154,15 +154,15 @@ module Prism def capture_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new CaseMatchNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[InNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[InNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } def case_match_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new CaseNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[WhenNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[WhenNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } def case_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new ClassNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: T.nilable(Location), superclass: T.nilable(Node), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: ::T.nilable(Location), superclass: ::T.nilable(Node), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } def class_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), inheritance_operator_loc: T.unsafe(nil), superclass: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end # Create a new ClassVariableAndWriteNode node. @@ -206,7 +206,7 @@ module Prism def constant_path_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new ConstantPathNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } def constant_path_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end # Create a new ConstantPathOperatorWriteNode node. @@ -218,7 +218,7 @@ module Prism def constant_path_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new ConstantPathTargetNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } def constant_path_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end # Create a new ConstantPathWriteNode node. @@ -238,27 +238,27 @@ module Prism def constant_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new DefNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: T.nilable(Node), parameters: T.nilable(ParametersNode), body: T.nilable(T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: T.nilable(Location), lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), equal_loc: T.nilable(Location), end_keyword_loc: T.nilable(Location)).returns(DefNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: ::T.nilable(Node), parameters: ::T.nilable(ParametersNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: ::T.nilable(Location), lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), end_keyword_loc: ::T.nilable(Location)).returns(DefNode) } def def_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), receiver: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), locals: T.unsafe(nil), def_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new DefinedNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: T.nilable(Location), value: Node, rparen_loc: T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: ::T.nilable(Location), value: Node, rparen_loc: ::T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } def defined_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lparen_loc: T.unsafe(nil), value: T.unsafe(nil), rparen_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end # Create a new ElseNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: T.nilable(Location)).returns(ElseNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: ::T.nilable(Location)).returns(ElseNode) } def else_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), else_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new EmbeddedStatementsNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: ::T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } def embedded_statements_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), statements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new EmbeddedVariableNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: ::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } def embedded_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), variable: T.unsafe(nil)); end # Create a new EnsureNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } def ensure_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), ensure_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new FalseNode node. @@ -266,11 +266,11 @@ module Prism def false_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new FindPatternNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: T.any(SplatNode, MissingNode), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(FindPatternNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: ::T.any(SplatNode, MissingNode), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(FindPatternNode) } def find_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), left: T.unsafe(nil), requireds: T.unsafe(nil), right: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new FlipFlopNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } def flip_flop_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new FloatNode node. @@ -278,7 +278,7 @@ module Prism def float_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new ForNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: ::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: ::T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } def for_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), index: T.unsafe(nil), collection: T.unsafe(nil), statements: T.unsafe(nil), for_keyword_loc: T.unsafe(nil), in_keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new ForwardingArgumentsNode node. @@ -290,7 +290,7 @@ module Prism def forwarding_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new ForwardingSuperNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: T.nilable(BlockNode)).returns(ForwardingSuperNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: ::T.nilable(BlockNode)).returns(ForwardingSuperNode) } def forwarding_super_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), block: T.unsafe(nil)); end # Create a new GlobalVariableAndWriteNode node. @@ -318,23 +318,23 @@ module Prism def global_variable_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new HashNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[::T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } def hash_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), elements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new HashPatternNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(HashPatternNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: ::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(HashPatternNode) } def hash_pattern_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), elements: T.unsafe(nil), rest: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new IfNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: T.nilable(Location), predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(T.any(ElseNode, IfNode)), end_keyword_loc: T.nilable(Location)).returns(IfNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: ::T.nilable(Location), predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(::T.any(ElseNode, IfNode)), end_keyword_loc: ::T.nilable(Location)).returns(IfNode) } def if_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), if_keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new ImaginaryNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: ::T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } def imaginary_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numeric: T.unsafe(nil)); end # Create a new ImplicitNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } def implicit_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new ImplicitRestNode node. @@ -342,23 +342,23 @@ module Prism def implicit_rest_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new InNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: T.nilable(StatementsNode), in_loc: Location, then_loc: T.nilable(Location)).returns(InNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: ::T.nilable(StatementsNode), in_loc: Location, then_loc: ::T.nilable(Location)).returns(InNode) } def in_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), pattern: T.unsafe(nil), statements: T.unsafe(nil), in_loc: T.unsafe(nil), then_loc: T.unsafe(nil)); end # Create a new IndexAndWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } def index_and_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new IndexOperatorWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } def index_operator_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new IndexOrWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } def index_or_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new IndexTargetNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } def index_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil)); end # Create a new InstanceVariableAndWriteNode node. @@ -390,23 +390,23 @@ module Prism def integer_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new InterpolatedMatchLastLineNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } def interpolated_match_last_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new InterpolatedRegularExpressionNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } def interpolated_regular_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new InterpolatedStringNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: T.nilable(Location)).returns(InterpolatedStringNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedStringNode) } def interpolated_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new InterpolatedSymbolNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: T.nilable(Location)).returns(InterpolatedSymbolNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedSymbolNode) } def interpolated_symbol_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new InterpolatedXStringNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } def interpolated_x_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new ItLocalVariableReadNode node. @@ -418,15 +418,15 @@ module Prism def it_parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new KeywordHashNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[::T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } def keyword_hash_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil)); end # Create a new KeywordRestParameterNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } def keyword_rest_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new LambdaNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode))).returns(LambdaNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode))).returns(LambdaNode) } def lambda_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil)); end # Create a new LocalVariableAndWriteNode node. @@ -474,19 +474,19 @@ module Prism def missing_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new ModuleNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } def module_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), module_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end # Create a new MultiTargetNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location)).returns(MultiTargetNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location)).returns(MultiTargetNode) } def multi_target_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end # Create a new MultiWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } def multi_write_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end # Create a new NextNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } def next_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end # Create a new NilNode node. @@ -522,11 +522,11 @@ module Prism def or_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new ParametersNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: T.nilable(T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[::T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: ::T.nilable(::T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: ::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: ::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } def parameters_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), requireds: T.unsafe(nil), optionals: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), keywords: T.unsafe(nil), keyword_rest: T.unsafe(nil), block: T.unsafe(nil)); end # Create a new ParenthesesNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: ::T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } def parentheses_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new PinnedExpressionNode node. @@ -534,15 +534,15 @@ module Prism def pinned_expression_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end # Create a new PinnedVariableNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: ::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } def pinned_variable_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), variable: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new PostExecutionNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } def post_execution_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new PreExecutionNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } def pre_execution_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end # Create a new ProgramNode node. @@ -550,7 +550,7 @@ module Prism def program_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), statements: T.unsafe(nil)); end # Create a new RangeNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(RangeNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(RangeNode) } def range_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new RationalNode node. @@ -578,11 +578,11 @@ module Prism def rescue_modifier_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), keyword_loc: T.unsafe(nil), rescue_expression: T.unsafe(nil)); end # Create a new RescueNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: T.nilable(Location), reference: T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(RescueNode)).returns(RescueNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: ::T.nilable(Location), reference: ::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(RescueNode)).returns(RescueNode) } def rescue_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), exceptions: T.unsafe(nil), operator_loc: T.unsafe(nil), reference: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil)); end # Create a new RestParameterNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } def rest_parameter_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end # Create a new RetryNode node. @@ -590,7 +590,7 @@ module Prism def retry_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new ReturnNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: T.nilable(ArgumentsNode)).returns(ReturnNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: ::T.nilable(ArgumentsNode)).returns(ReturnNode) } def return_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), arguments: T.unsafe(nil)); end # Create a new SelfNode node. @@ -598,11 +598,11 @@ module Prism def self_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new ShareableConstantNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: ::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } def shareable_constant_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), write: T.unsafe(nil)); end # Create a new SingletonClassNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } def singleton_class_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new SourceEncodingNode node. @@ -618,7 +618,7 @@ module Prism def source_line_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new SplatNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: T.nilable(Node)).returns(SplatNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: ::T.nilable(Node)).returns(SplatNode) } def splat_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil)); end # Create a new StatementsNode node. @@ -626,15 +626,15 @@ module Prism def statements_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil)); end # Create a new StringNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), content_loc: Location, closing_loc: T.nilable(Location), unescaped: String).returns(StringNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), content_loc: Location, closing_loc: ::T.nilable(Location), unescaped: String).returns(StringNode) } def string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end # Create a new SuperNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } def super_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil), block: T.unsafe(nil)); end # Create a new SymbolNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), value_loc: T.nilable(Location), closing_loc: T.nilable(Location), unescaped: String).returns(SymbolNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), value_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), unescaped: String).returns(SymbolNode) } def symbol_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), value_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end # Create a new TrueNode node. @@ -642,23 +642,23 @@ module Prism def true_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end # Create a new UndefNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } def undef_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), names: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end # Create a new UnlessNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), else_clause: T.nilable(ElseNode), end_keyword_loc: T.nilable(Location)).returns(UnlessNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), else_clause: ::T.nilable(ElseNode), end_keyword_loc: ::T.nilable(Location)).returns(UnlessNode) } def unless_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), else_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end # Create a new UntilNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(UntilNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(UntilNode) } def until_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end # Create a new WhenNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode)).returns(WhenNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode)).returns(WhenNode) } def when_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), conditions: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil)); end # Create a new WhileNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(WhileNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(WhileNode) } def while_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end # Create a new XStringNode node. @@ -666,7 +666,7 @@ module Prism def x_string_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end # Create a new YieldNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location)).returns(YieldNode) } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location)).returns(YieldNode) } def yield_node(source: T.unsafe(nil), node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end # Retrieve the value of one of the ArgumentsNodeFlags flags. diff --git a/rbi/generated/prism/inspect_visitor.rbi b/rbi/generated/prism/inspect_visitor.rbi index 85442ef768..449a531c38 100644 --- a/rbi/generated/prism/inspect_visitor.rbi +++ b/rbi/generated/prism/inspect_visitor.rbi @@ -22,7 +22,7 @@ module Prism # The list of commands that we need to execute in order to compose the # final string. - sig { returns(T::Array[[T.any(String, Node, Replace), String]]) } + sig { returns(T::Array[[::T.any(String, Node, Replace), String]]) } attr_reader :commands sig { params(indent: String).void } @@ -497,7 +497,7 @@ module Prism private def inspect_node(name, node); end # Compose a string representing the given inner location field. - sig { params(location: T.nilable(Location)).returns(String) } + sig { params(location: ::T.nilable(Location)).returns(String) } private def inspect_location(location); end end end diff --git a/rbi/generated/prism/lex_compat.rbi b/rbi/generated/prism/lex_compat.rbi index df47383acf..5ce03767c8 100644 --- a/rbi/generated/prism/lex_compat.rbi +++ b/rbi/generated/prism/lex_compat.rbi @@ -32,22 +32,22 @@ module Prism # A result class specialized for holding tokens produced by the lexer. class Result < Prism::Result # The list of tokens that were produced by the lexer. - sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } attr_reader :value # Create a new lex compat result object with the given values. - sig { params(value: T::Array[[[Integer, Integer], Symbol, String, T.untyped]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + sig { params(value: T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end # Implement the hash pattern matching interface for Result. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end end # This is a mapping of prism token types to Ripper token types. This is a # many-to-one mapping because we split up our token types, whereas Ripper # tends to group them. - RIPPER = T.let(nil, T.untyped) + RIPPER = T.let(nil, ::T.untyped) # A heredoc in this case is a list of tokens that belong to the body of the # heredoc that should be appended onto the list of tokens when the heredoc @@ -58,16 +58,16 @@ module Prism # order back into the token stream and set the state of the last token to # the state that the heredoc was opened in. class PlainHeredoc - sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } attr_reader :tokens sig { void } def initialize; end - sig { params(token: [[Integer, Integer], Symbol, String, T.untyped]).void } + sig { params(token: [[Integer, Integer], Symbol, String, ::T.untyped]).void } def <<(token); end - sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } def to_a; end end @@ -78,16 +78,16 @@ module Prism sig { returns(T::Boolean) } attr_reader :split - sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } attr_reader :tokens sig { params(split: T::Boolean).void } def initialize(split); end - sig { params(token: [[Integer, Integer], Symbol, String, T.untyped]).void } + sig { params(token: [[Integer, Integer], Symbol, String, ::T.untyped]).void } def <<(token); end - sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } def to_a; end end @@ -104,13 +104,13 @@ module Prism class DedentingHeredoc TAB_WIDTH = T.let(nil, Integer) - sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } attr_reader :tokens sig { returns(T::Boolean) } attr_reader :dedent_next - sig { returns(T.nilable(Integer)) } + sig { returns(::T.nilable(Integer)) } attr_reader :dedent sig { returns(Integer) } @@ -123,33 +123,33 @@ module Prism # whitespace on plain string content tokens. This allows us to later # remove that amount of whitespace from the beginning of each line. # - sig { params(token: [[Integer, Integer], Symbol, String, T.untyped]).void } + sig { params(token: [[Integer, Integer], Symbol, String, ::T.untyped]).void } def <<(token); end - sig { returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } def to_a; end end # Here we will split between the two types of heredocs and return the # object that will store their tokens. - sig { params(opening: [[Integer, Integer], Symbol, String, T.untyped]).returns(T.any(PlainHeredoc, DashHeredoc, DedentingHeredoc)) } + sig { params(opening: [[Integer, Integer], Symbol, String, ::T.untyped]).returns(::T.any(PlainHeredoc, DashHeredoc, DedentingHeredoc)) } def self.build(opening); end end # In previous versions of Ruby, Ripper wouldn't flush the bom before the # first token, so we had to have a hack in place to account for that. - BOM_FLUSHED = T.let(nil, T.untyped) + BOM_FLUSHED = T.let(nil, ::T.untyped) - sig { returns(T::Hash[Symbol, T.untyped]) } + sig { returns(T::Hash[Symbol, ::T.untyped]) } attr_reader :options - sig { params(source: String, options: T.untyped).void } + sig { params(source: String, options: ::T.untyped).void } def initialize(source, **options); end sig { returns(Result) } def result; end - sig { params(tokens: T::Array[[[Integer, Integer], Symbol, String, T.untyped]], source: Source, data_loc: T.nilable(Location), bom: T::Boolean, eof_token: T.nilable(Token)).returns(T::Array[[[Integer, Integer], Symbol, String, T.untyped]]) } + sig { params(tokens: T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]], source: Source, data_loc: ::T.nilable(Location), bom: T::Boolean, eof_token: ::T.nilable(Token)).returns(T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]]) } private def post_process_tokens(tokens, source, data_loc, bom, eof_token); end end end diff --git a/rbi/generated/prism/mutation_compiler.rbi b/rbi/generated/prism/mutation_compiler.rbi index f62613fa1b..21be124fed 100644 --- a/rbi/generated/prism/mutation_compiler.rbi +++ b/rbi/generated/prism/mutation_compiler.rbi @@ -5,460 +5,460 @@ module Prism # visited. This is useful for consumers that want to mutate the tree, as you # can change subtrees in place without effecting the rest of the tree. class MutationCompiler < Compiler - sig { params(arg0: AliasGlobalVariableNode).returns(T.nilable(Node)) } + sig { params(arg0: AliasGlobalVariableNode).returns(::T.nilable(Node)) } def visit_alias_global_variable_node(arg0); end - sig { params(arg0: AliasMethodNode).returns(T.nilable(Node)) } + sig { params(arg0: AliasMethodNode).returns(::T.nilable(Node)) } def visit_alias_method_node(arg0); end - sig { params(arg0: AlternationPatternNode).returns(T.nilable(Node)) } + sig { params(arg0: AlternationPatternNode).returns(::T.nilable(Node)) } def visit_alternation_pattern_node(arg0); end - sig { params(arg0: AndNode).returns(T.nilable(Node)) } + sig { params(arg0: AndNode).returns(::T.nilable(Node)) } def visit_and_node(arg0); end - sig { params(arg0: ArgumentsNode).returns(T.nilable(Node)) } + sig { params(arg0: ArgumentsNode).returns(::T.nilable(Node)) } def visit_arguments_node(arg0); end - sig { params(arg0: ArrayNode).returns(T.nilable(Node)) } + sig { params(arg0: ArrayNode).returns(::T.nilable(Node)) } def visit_array_node(arg0); end - sig { params(arg0: ArrayPatternNode).returns(T.nilable(Node)) } + sig { params(arg0: ArrayPatternNode).returns(::T.nilable(Node)) } def visit_array_pattern_node(arg0); end - sig { params(arg0: AssocNode).returns(T.nilable(Node)) } + sig { params(arg0: AssocNode).returns(::T.nilable(Node)) } def visit_assoc_node(arg0); end - sig { params(arg0: AssocSplatNode).returns(T.nilable(Node)) } + sig { params(arg0: AssocSplatNode).returns(::T.nilable(Node)) } def visit_assoc_splat_node(arg0); end - sig { params(arg0: BackReferenceReadNode).returns(T.nilable(Node)) } + sig { params(arg0: BackReferenceReadNode).returns(::T.nilable(Node)) } def visit_back_reference_read_node(arg0); end - sig { params(arg0: BeginNode).returns(T.nilable(Node)) } + sig { params(arg0: BeginNode).returns(::T.nilable(Node)) } def visit_begin_node(arg0); end - sig { params(arg0: BlockArgumentNode).returns(T.nilable(Node)) } + sig { params(arg0: BlockArgumentNode).returns(::T.nilable(Node)) } def visit_block_argument_node(arg0); end - sig { params(arg0: BlockLocalVariableNode).returns(T.nilable(Node)) } + sig { params(arg0: BlockLocalVariableNode).returns(::T.nilable(Node)) } def visit_block_local_variable_node(arg0); end - sig { params(arg0: BlockNode).returns(T.nilable(Node)) } + sig { params(arg0: BlockNode).returns(::T.nilable(Node)) } def visit_block_node(arg0); end - sig { params(arg0: BlockParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: BlockParameterNode).returns(::T.nilable(Node)) } def visit_block_parameter_node(arg0); end - sig { params(arg0: BlockParametersNode).returns(T.nilable(Node)) } + sig { params(arg0: BlockParametersNode).returns(::T.nilable(Node)) } def visit_block_parameters_node(arg0); end - sig { params(arg0: BreakNode).returns(T.nilable(Node)) } + sig { params(arg0: BreakNode).returns(::T.nilable(Node)) } def visit_break_node(arg0); end - sig { params(arg0: CallAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: CallAndWriteNode).returns(::T.nilable(Node)) } def visit_call_and_write_node(arg0); end - sig { params(arg0: CallNode).returns(T.nilable(Node)) } + sig { params(arg0: CallNode).returns(::T.nilable(Node)) } def visit_call_node(arg0); end - sig { params(arg0: CallOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: CallOperatorWriteNode).returns(::T.nilable(Node)) } def visit_call_operator_write_node(arg0); end - sig { params(arg0: CallOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: CallOrWriteNode).returns(::T.nilable(Node)) } def visit_call_or_write_node(arg0); end - sig { params(arg0: CallTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: CallTargetNode).returns(::T.nilable(Node)) } def visit_call_target_node(arg0); end - sig { params(arg0: CapturePatternNode).returns(T.nilable(Node)) } + sig { params(arg0: CapturePatternNode).returns(::T.nilable(Node)) } def visit_capture_pattern_node(arg0); end - sig { params(arg0: CaseMatchNode).returns(T.nilable(Node)) } + sig { params(arg0: CaseMatchNode).returns(::T.nilable(Node)) } def visit_case_match_node(arg0); end - sig { params(arg0: CaseNode).returns(T.nilable(Node)) } + sig { params(arg0: CaseNode).returns(::T.nilable(Node)) } def visit_case_node(arg0); end - sig { params(arg0: ClassNode).returns(T.nilable(Node)) } + sig { params(arg0: ClassNode).returns(::T.nilable(Node)) } def visit_class_node(arg0); end - sig { params(arg0: ClassVariableAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ClassVariableAndWriteNode).returns(::T.nilable(Node)) } def visit_class_variable_and_write_node(arg0); end - sig { params(arg0: ClassVariableOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ClassVariableOperatorWriteNode).returns(::T.nilable(Node)) } def visit_class_variable_operator_write_node(arg0); end - sig { params(arg0: ClassVariableOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ClassVariableOrWriteNode).returns(::T.nilable(Node)) } def visit_class_variable_or_write_node(arg0); end - sig { params(arg0: ClassVariableReadNode).returns(T.nilable(Node)) } + sig { params(arg0: ClassVariableReadNode).returns(::T.nilable(Node)) } def visit_class_variable_read_node(arg0); end - sig { params(arg0: ClassVariableTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: ClassVariableTargetNode).returns(::T.nilable(Node)) } def visit_class_variable_target_node(arg0); end - sig { params(arg0: ClassVariableWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ClassVariableWriteNode).returns(::T.nilable(Node)) } def visit_class_variable_write_node(arg0); end - sig { params(arg0: ConstantAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantAndWriteNode).returns(::T.nilable(Node)) } def visit_constant_and_write_node(arg0); end - sig { params(arg0: ConstantOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantOperatorWriteNode).returns(::T.nilable(Node)) } def visit_constant_operator_write_node(arg0); end - sig { params(arg0: ConstantOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantOrWriteNode).returns(::T.nilable(Node)) } def visit_constant_or_write_node(arg0); end - sig { params(arg0: ConstantPathAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantPathAndWriteNode).returns(::T.nilable(Node)) } def visit_constant_path_and_write_node(arg0); end - sig { params(arg0: ConstantPathNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantPathNode).returns(::T.nilable(Node)) } def visit_constant_path_node(arg0); end - sig { params(arg0: ConstantPathOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantPathOperatorWriteNode).returns(::T.nilable(Node)) } def visit_constant_path_operator_write_node(arg0); end - sig { params(arg0: ConstantPathOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantPathOrWriteNode).returns(::T.nilable(Node)) } def visit_constant_path_or_write_node(arg0); end - sig { params(arg0: ConstantPathTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantPathTargetNode).returns(::T.nilable(Node)) } def visit_constant_path_target_node(arg0); end - sig { params(arg0: ConstantPathWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantPathWriteNode).returns(::T.nilable(Node)) } def visit_constant_path_write_node(arg0); end - sig { params(arg0: ConstantReadNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantReadNode).returns(::T.nilable(Node)) } def visit_constant_read_node(arg0); end - sig { params(arg0: ConstantTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantTargetNode).returns(::T.nilable(Node)) } def visit_constant_target_node(arg0); end - sig { params(arg0: ConstantWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: ConstantWriteNode).returns(::T.nilable(Node)) } def visit_constant_write_node(arg0); end - sig { params(arg0: DefNode).returns(T.nilable(Node)) } + sig { params(arg0: DefNode).returns(::T.nilable(Node)) } def visit_def_node(arg0); end - sig { params(arg0: DefinedNode).returns(T.nilable(Node)) } + sig { params(arg0: DefinedNode).returns(::T.nilable(Node)) } def visit_defined_node(arg0); end - sig { params(arg0: ElseNode).returns(T.nilable(Node)) } + sig { params(arg0: ElseNode).returns(::T.nilable(Node)) } def visit_else_node(arg0); end - sig { params(arg0: EmbeddedStatementsNode).returns(T.nilable(Node)) } + sig { params(arg0: EmbeddedStatementsNode).returns(::T.nilable(Node)) } def visit_embedded_statements_node(arg0); end - sig { params(arg0: EmbeddedVariableNode).returns(T.nilable(Node)) } + sig { params(arg0: EmbeddedVariableNode).returns(::T.nilable(Node)) } def visit_embedded_variable_node(arg0); end - sig { params(arg0: EnsureNode).returns(T.nilable(Node)) } + sig { params(arg0: EnsureNode).returns(::T.nilable(Node)) } def visit_ensure_node(arg0); end - sig { params(arg0: FalseNode).returns(T.nilable(Node)) } + sig { params(arg0: FalseNode).returns(::T.nilable(Node)) } def visit_false_node(arg0); end - sig { params(arg0: FindPatternNode).returns(T.nilable(Node)) } + sig { params(arg0: FindPatternNode).returns(::T.nilable(Node)) } def visit_find_pattern_node(arg0); end - sig { params(arg0: FlipFlopNode).returns(T.nilable(Node)) } + sig { params(arg0: FlipFlopNode).returns(::T.nilable(Node)) } def visit_flip_flop_node(arg0); end - sig { params(arg0: FloatNode).returns(T.nilable(Node)) } + sig { params(arg0: FloatNode).returns(::T.nilable(Node)) } def visit_float_node(arg0); end - sig { params(arg0: ForNode).returns(T.nilable(Node)) } + sig { params(arg0: ForNode).returns(::T.nilable(Node)) } def visit_for_node(arg0); end - sig { params(arg0: ForwardingArgumentsNode).returns(T.nilable(Node)) } + sig { params(arg0: ForwardingArgumentsNode).returns(::T.nilable(Node)) } def visit_forwarding_arguments_node(arg0); end - sig { params(arg0: ForwardingParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: ForwardingParameterNode).returns(::T.nilable(Node)) } def visit_forwarding_parameter_node(arg0); end - sig { params(arg0: ForwardingSuperNode).returns(T.nilable(Node)) } + sig { params(arg0: ForwardingSuperNode).returns(::T.nilable(Node)) } def visit_forwarding_super_node(arg0); end - sig { params(arg0: GlobalVariableAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: GlobalVariableAndWriteNode).returns(::T.nilable(Node)) } def visit_global_variable_and_write_node(arg0); end - sig { params(arg0: GlobalVariableOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: GlobalVariableOperatorWriteNode).returns(::T.nilable(Node)) } def visit_global_variable_operator_write_node(arg0); end - sig { params(arg0: GlobalVariableOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: GlobalVariableOrWriteNode).returns(::T.nilable(Node)) } def visit_global_variable_or_write_node(arg0); end - sig { params(arg0: GlobalVariableReadNode).returns(T.nilable(Node)) } + sig { params(arg0: GlobalVariableReadNode).returns(::T.nilable(Node)) } def visit_global_variable_read_node(arg0); end - sig { params(arg0: GlobalVariableTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: GlobalVariableTargetNode).returns(::T.nilable(Node)) } def visit_global_variable_target_node(arg0); end - sig { params(arg0: GlobalVariableWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: GlobalVariableWriteNode).returns(::T.nilable(Node)) } def visit_global_variable_write_node(arg0); end - sig { params(arg0: HashNode).returns(T.nilable(Node)) } + sig { params(arg0: HashNode).returns(::T.nilable(Node)) } def visit_hash_node(arg0); end - sig { params(arg0: HashPatternNode).returns(T.nilable(Node)) } + sig { params(arg0: HashPatternNode).returns(::T.nilable(Node)) } def visit_hash_pattern_node(arg0); end - sig { params(arg0: IfNode).returns(T.nilable(Node)) } + sig { params(arg0: IfNode).returns(::T.nilable(Node)) } def visit_if_node(arg0); end - sig { params(arg0: ImaginaryNode).returns(T.nilable(Node)) } + sig { params(arg0: ImaginaryNode).returns(::T.nilable(Node)) } def visit_imaginary_node(arg0); end - sig { params(arg0: ImplicitNode).returns(T.nilable(Node)) } + sig { params(arg0: ImplicitNode).returns(::T.nilable(Node)) } def visit_implicit_node(arg0); end - sig { params(arg0: ImplicitRestNode).returns(T.nilable(Node)) } + sig { params(arg0: ImplicitRestNode).returns(::T.nilable(Node)) } def visit_implicit_rest_node(arg0); end - sig { params(arg0: InNode).returns(T.nilable(Node)) } + sig { params(arg0: InNode).returns(::T.nilable(Node)) } def visit_in_node(arg0); end - sig { params(arg0: IndexAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: IndexAndWriteNode).returns(::T.nilable(Node)) } def visit_index_and_write_node(arg0); end - sig { params(arg0: IndexOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: IndexOperatorWriteNode).returns(::T.nilable(Node)) } def visit_index_operator_write_node(arg0); end - sig { params(arg0: IndexOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: IndexOrWriteNode).returns(::T.nilable(Node)) } def visit_index_or_write_node(arg0); end - sig { params(arg0: IndexTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: IndexTargetNode).returns(::T.nilable(Node)) } def visit_index_target_node(arg0); end - sig { params(arg0: InstanceVariableAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: InstanceVariableAndWriteNode).returns(::T.nilable(Node)) } def visit_instance_variable_and_write_node(arg0); end - sig { params(arg0: InstanceVariableOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: InstanceVariableOperatorWriteNode).returns(::T.nilable(Node)) } def visit_instance_variable_operator_write_node(arg0); end - sig { params(arg0: InstanceVariableOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: InstanceVariableOrWriteNode).returns(::T.nilable(Node)) } def visit_instance_variable_or_write_node(arg0); end - sig { params(arg0: InstanceVariableReadNode).returns(T.nilable(Node)) } + sig { params(arg0: InstanceVariableReadNode).returns(::T.nilable(Node)) } def visit_instance_variable_read_node(arg0); end - sig { params(arg0: InstanceVariableTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: InstanceVariableTargetNode).returns(::T.nilable(Node)) } def visit_instance_variable_target_node(arg0); end - sig { params(arg0: InstanceVariableWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: InstanceVariableWriteNode).returns(::T.nilable(Node)) } def visit_instance_variable_write_node(arg0); end - sig { params(arg0: IntegerNode).returns(T.nilable(Node)) } + sig { params(arg0: IntegerNode).returns(::T.nilable(Node)) } def visit_integer_node(arg0); end - sig { params(arg0: InterpolatedMatchLastLineNode).returns(T.nilable(Node)) } + sig { params(arg0: InterpolatedMatchLastLineNode).returns(::T.nilable(Node)) } def visit_interpolated_match_last_line_node(arg0); end - sig { params(arg0: InterpolatedRegularExpressionNode).returns(T.nilable(Node)) } + sig { params(arg0: InterpolatedRegularExpressionNode).returns(::T.nilable(Node)) } def visit_interpolated_regular_expression_node(arg0); end - sig { params(arg0: InterpolatedStringNode).returns(T.nilable(Node)) } + sig { params(arg0: InterpolatedStringNode).returns(::T.nilable(Node)) } def visit_interpolated_string_node(arg0); end - sig { params(arg0: InterpolatedSymbolNode).returns(T.nilable(Node)) } + sig { params(arg0: InterpolatedSymbolNode).returns(::T.nilable(Node)) } def visit_interpolated_symbol_node(arg0); end - sig { params(arg0: InterpolatedXStringNode).returns(T.nilable(Node)) } + sig { params(arg0: InterpolatedXStringNode).returns(::T.nilable(Node)) } def visit_interpolated_x_string_node(arg0); end - sig { params(arg0: ItLocalVariableReadNode).returns(T.nilable(Node)) } + sig { params(arg0: ItLocalVariableReadNode).returns(::T.nilable(Node)) } def visit_it_local_variable_read_node(arg0); end - sig { params(arg0: ItParametersNode).returns(T.nilable(Node)) } + sig { params(arg0: ItParametersNode).returns(::T.nilable(Node)) } def visit_it_parameters_node(arg0); end - sig { params(arg0: KeywordHashNode).returns(T.nilable(Node)) } + sig { params(arg0: KeywordHashNode).returns(::T.nilable(Node)) } def visit_keyword_hash_node(arg0); end - sig { params(arg0: KeywordRestParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: KeywordRestParameterNode).returns(::T.nilable(Node)) } def visit_keyword_rest_parameter_node(arg0); end - sig { params(arg0: LambdaNode).returns(T.nilable(Node)) } + sig { params(arg0: LambdaNode).returns(::T.nilable(Node)) } def visit_lambda_node(arg0); end - sig { params(arg0: LocalVariableAndWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: LocalVariableAndWriteNode).returns(::T.nilable(Node)) } def visit_local_variable_and_write_node(arg0); end - sig { params(arg0: LocalVariableOperatorWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: LocalVariableOperatorWriteNode).returns(::T.nilable(Node)) } def visit_local_variable_operator_write_node(arg0); end - sig { params(arg0: LocalVariableOrWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: LocalVariableOrWriteNode).returns(::T.nilable(Node)) } def visit_local_variable_or_write_node(arg0); end - sig { params(arg0: LocalVariableReadNode).returns(T.nilable(Node)) } + sig { params(arg0: LocalVariableReadNode).returns(::T.nilable(Node)) } def visit_local_variable_read_node(arg0); end - sig { params(arg0: LocalVariableTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: LocalVariableTargetNode).returns(::T.nilable(Node)) } def visit_local_variable_target_node(arg0); end - sig { params(arg0: LocalVariableWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: LocalVariableWriteNode).returns(::T.nilable(Node)) } def visit_local_variable_write_node(arg0); end - sig { params(arg0: MatchLastLineNode).returns(T.nilable(Node)) } + sig { params(arg0: MatchLastLineNode).returns(::T.nilable(Node)) } def visit_match_last_line_node(arg0); end - sig { params(arg0: MatchPredicateNode).returns(T.nilable(Node)) } + sig { params(arg0: MatchPredicateNode).returns(::T.nilable(Node)) } def visit_match_predicate_node(arg0); end - sig { params(arg0: MatchRequiredNode).returns(T.nilable(Node)) } + sig { params(arg0: MatchRequiredNode).returns(::T.nilable(Node)) } def visit_match_required_node(arg0); end - sig { params(arg0: MatchWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: MatchWriteNode).returns(::T.nilable(Node)) } def visit_match_write_node(arg0); end - sig { params(arg0: MissingNode).returns(T.nilable(Node)) } + sig { params(arg0: MissingNode).returns(::T.nilable(Node)) } def visit_missing_node(arg0); end - sig { params(arg0: ModuleNode).returns(T.nilable(Node)) } + sig { params(arg0: ModuleNode).returns(::T.nilable(Node)) } def visit_module_node(arg0); end - sig { params(arg0: MultiTargetNode).returns(T.nilable(Node)) } + sig { params(arg0: MultiTargetNode).returns(::T.nilable(Node)) } def visit_multi_target_node(arg0); end - sig { params(arg0: MultiWriteNode).returns(T.nilable(Node)) } + sig { params(arg0: MultiWriteNode).returns(::T.nilable(Node)) } def visit_multi_write_node(arg0); end - sig { params(arg0: NextNode).returns(T.nilable(Node)) } + sig { params(arg0: NextNode).returns(::T.nilable(Node)) } def visit_next_node(arg0); end - sig { params(arg0: NilNode).returns(T.nilable(Node)) } + sig { params(arg0: NilNode).returns(::T.nilable(Node)) } def visit_nil_node(arg0); end - sig { params(arg0: NoBlockParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: NoBlockParameterNode).returns(::T.nilable(Node)) } def visit_no_block_parameter_node(arg0); end - sig { params(arg0: NoKeywordsParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: NoKeywordsParameterNode).returns(::T.nilable(Node)) } def visit_no_keywords_parameter_node(arg0); end - sig { params(arg0: NumberedParametersNode).returns(T.nilable(Node)) } + sig { params(arg0: NumberedParametersNode).returns(::T.nilable(Node)) } def visit_numbered_parameters_node(arg0); end - sig { params(arg0: NumberedReferenceReadNode).returns(T.nilable(Node)) } + sig { params(arg0: NumberedReferenceReadNode).returns(::T.nilable(Node)) } def visit_numbered_reference_read_node(arg0); end - sig { params(arg0: OptionalKeywordParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: OptionalKeywordParameterNode).returns(::T.nilable(Node)) } def visit_optional_keyword_parameter_node(arg0); end - sig { params(arg0: OptionalParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: OptionalParameterNode).returns(::T.nilable(Node)) } def visit_optional_parameter_node(arg0); end - sig { params(arg0: OrNode).returns(T.nilable(Node)) } + sig { params(arg0: OrNode).returns(::T.nilable(Node)) } def visit_or_node(arg0); end - sig { params(arg0: ParametersNode).returns(T.nilable(Node)) } + sig { params(arg0: ParametersNode).returns(::T.nilable(Node)) } def visit_parameters_node(arg0); end - sig { params(arg0: ParenthesesNode).returns(T.nilable(Node)) } + sig { params(arg0: ParenthesesNode).returns(::T.nilable(Node)) } def visit_parentheses_node(arg0); end - sig { params(arg0: PinnedExpressionNode).returns(T.nilable(Node)) } + sig { params(arg0: PinnedExpressionNode).returns(::T.nilable(Node)) } def visit_pinned_expression_node(arg0); end - sig { params(arg0: PinnedVariableNode).returns(T.nilable(Node)) } + sig { params(arg0: PinnedVariableNode).returns(::T.nilable(Node)) } def visit_pinned_variable_node(arg0); end - sig { params(arg0: PostExecutionNode).returns(T.nilable(Node)) } + sig { params(arg0: PostExecutionNode).returns(::T.nilable(Node)) } def visit_post_execution_node(arg0); end - sig { params(arg0: PreExecutionNode).returns(T.nilable(Node)) } + sig { params(arg0: PreExecutionNode).returns(::T.nilable(Node)) } def visit_pre_execution_node(arg0); end - sig { params(arg0: ProgramNode).returns(T.nilable(Node)) } + sig { params(arg0: ProgramNode).returns(::T.nilable(Node)) } def visit_program_node(arg0); end - sig { params(arg0: RangeNode).returns(T.nilable(Node)) } + sig { params(arg0: RangeNode).returns(::T.nilable(Node)) } def visit_range_node(arg0); end - sig { params(arg0: RationalNode).returns(T.nilable(Node)) } + sig { params(arg0: RationalNode).returns(::T.nilable(Node)) } def visit_rational_node(arg0); end - sig { params(arg0: RedoNode).returns(T.nilable(Node)) } + sig { params(arg0: RedoNode).returns(::T.nilable(Node)) } def visit_redo_node(arg0); end - sig { params(arg0: RegularExpressionNode).returns(T.nilable(Node)) } + sig { params(arg0: RegularExpressionNode).returns(::T.nilable(Node)) } def visit_regular_expression_node(arg0); end - sig { params(arg0: RequiredKeywordParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: RequiredKeywordParameterNode).returns(::T.nilable(Node)) } def visit_required_keyword_parameter_node(arg0); end - sig { params(arg0: RequiredParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: RequiredParameterNode).returns(::T.nilable(Node)) } def visit_required_parameter_node(arg0); end - sig { params(arg0: RescueModifierNode).returns(T.nilable(Node)) } + sig { params(arg0: RescueModifierNode).returns(::T.nilable(Node)) } def visit_rescue_modifier_node(arg0); end - sig { params(arg0: RescueNode).returns(T.nilable(Node)) } + sig { params(arg0: RescueNode).returns(::T.nilable(Node)) } def visit_rescue_node(arg0); end - sig { params(arg0: RestParameterNode).returns(T.nilable(Node)) } + sig { params(arg0: RestParameterNode).returns(::T.nilable(Node)) } def visit_rest_parameter_node(arg0); end - sig { params(arg0: RetryNode).returns(T.nilable(Node)) } + sig { params(arg0: RetryNode).returns(::T.nilable(Node)) } def visit_retry_node(arg0); end - sig { params(arg0: ReturnNode).returns(T.nilable(Node)) } + sig { params(arg0: ReturnNode).returns(::T.nilable(Node)) } def visit_return_node(arg0); end - sig { params(arg0: SelfNode).returns(T.nilable(Node)) } + sig { params(arg0: SelfNode).returns(::T.nilable(Node)) } def visit_self_node(arg0); end - sig { params(arg0: ShareableConstantNode).returns(T.nilable(Node)) } + sig { params(arg0: ShareableConstantNode).returns(::T.nilable(Node)) } def visit_shareable_constant_node(arg0); end - sig { params(arg0: SingletonClassNode).returns(T.nilable(Node)) } + sig { params(arg0: SingletonClassNode).returns(::T.nilable(Node)) } def visit_singleton_class_node(arg0); end - sig { params(arg0: SourceEncodingNode).returns(T.nilable(Node)) } + sig { params(arg0: SourceEncodingNode).returns(::T.nilable(Node)) } def visit_source_encoding_node(arg0); end - sig { params(arg0: SourceFileNode).returns(T.nilable(Node)) } + sig { params(arg0: SourceFileNode).returns(::T.nilable(Node)) } def visit_source_file_node(arg0); end - sig { params(arg0: SourceLineNode).returns(T.nilable(Node)) } + sig { params(arg0: SourceLineNode).returns(::T.nilable(Node)) } def visit_source_line_node(arg0); end - sig { params(arg0: SplatNode).returns(T.nilable(Node)) } + sig { params(arg0: SplatNode).returns(::T.nilable(Node)) } def visit_splat_node(arg0); end - sig { params(arg0: StatementsNode).returns(T.nilable(Node)) } + sig { params(arg0: StatementsNode).returns(::T.nilable(Node)) } def visit_statements_node(arg0); end - sig { params(arg0: StringNode).returns(T.nilable(Node)) } + sig { params(arg0: StringNode).returns(::T.nilable(Node)) } def visit_string_node(arg0); end - sig { params(arg0: SuperNode).returns(T.nilable(Node)) } + sig { params(arg0: SuperNode).returns(::T.nilable(Node)) } def visit_super_node(arg0); end - sig { params(arg0: SymbolNode).returns(T.nilable(Node)) } + sig { params(arg0: SymbolNode).returns(::T.nilable(Node)) } def visit_symbol_node(arg0); end - sig { params(arg0: TrueNode).returns(T.nilable(Node)) } + sig { params(arg0: TrueNode).returns(::T.nilable(Node)) } def visit_true_node(arg0); end - sig { params(arg0: UndefNode).returns(T.nilable(Node)) } + sig { params(arg0: UndefNode).returns(::T.nilable(Node)) } def visit_undef_node(arg0); end - sig { params(arg0: UnlessNode).returns(T.nilable(Node)) } + sig { params(arg0: UnlessNode).returns(::T.nilable(Node)) } def visit_unless_node(arg0); end - sig { params(arg0: UntilNode).returns(T.nilable(Node)) } + sig { params(arg0: UntilNode).returns(::T.nilable(Node)) } def visit_until_node(arg0); end - sig { params(arg0: WhenNode).returns(T.nilable(Node)) } + sig { params(arg0: WhenNode).returns(::T.nilable(Node)) } def visit_when_node(arg0); end - sig { params(arg0: WhileNode).returns(T.nilable(Node)) } + sig { params(arg0: WhileNode).returns(::T.nilable(Node)) } def visit_while_node(arg0); end - sig { params(arg0: XStringNode).returns(T.nilable(Node)) } + sig { params(arg0: XStringNode).returns(::T.nilable(Node)) } def visit_x_string_node(arg0); end - sig { params(arg0: YieldNode).returns(T.nilable(Node)) } + sig { params(arg0: YieldNode).returns(::T.nilable(Node)) } def visit_yield_node(arg0); end end end diff --git a/rbi/generated/prism/node.rbi b/rbi/generated/prism/node.rbi index 324250b8c0..3b62926afb 100644 --- a/rbi/generated/prism/node.rbi +++ b/rbi/generated/prism/node.rbi @@ -18,7 +18,7 @@ module Prism attr_reader :node_id # Save this node using a saved source so that it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save(repository); end # A Location instance that represents the location of this node in the @@ -27,7 +27,7 @@ module Prism def location; end # Save the location using a saved source so that it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_location(repository); end # Delegates to [`start_line`](rdoc-ref:Location#start_line) of the associated location object. @@ -58,12 +58,12 @@ module Prism # Delegates to [`cached_start_code_units_offset`](rdoc-ref:Location#cached_start_code_units_offset) # of the associated location object. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_start_code_units_offset(cache); end # Delegates to [`cached_end_code_units_offset`](rdoc-ref:Location#cached_end_code_units_offset) # of the associated location object. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_end_code_units_offset(cache); end # Delegates to [`start_column`](rdoc-ref:Location#start_column) of the associated location object. @@ -86,12 +86,12 @@ module Prism # Delegates to [`cached_start_code_units_column`](rdoc-ref:Location#cached_start_code_units_column) # of the associated location object. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_start_code_units_column(cache); end # Delegates to [`cached_end_code_units_column`](rdoc-ref:Location#cached_end_code_units_column) # of the associated location object. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_end_code_units_column(cache); end # Delegates to [`leading_comments`](rdoc-ref:Location#leading_comments) of the associated location object. @@ -161,10 +161,10 @@ module Prism # particular condition. # # node.breadth_first_search { |node| node.node_id == node_id } - sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T.nilable(Node)) } + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(::T.nilable(Node)) } def breadth_first_search(&blk); end - sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T.nilable(Node)) } + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(::T.nilable(Node)) } def find(&blk); end # Returns all of the nodes that match the given block when visited in a @@ -172,10 +172,10 @@ module Prism # particular condition. # # node.breadth_first_search_all { |node| node.is_a?(Prism::CallNode) } - sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } def breadth_first_search_all(&blk); end - sig { params(blk: T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } + sig { params(blk: ::T.proc.params(arg0: Node).returns(T::Boolean)).returns(T::Array[Node]) } def find_all(&blk); end # Returns a list of the fields that exist for this node class. Fields @@ -185,22 +185,22 @@ module Prism def self.fields; end # Accepts a visitor and calls back into the specialized visit function. - sig { abstract.params(visitor: Visitor).returns(T.untyped) } + sig { abstract.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # Returns an array of child nodes, including `nil`s in the place of optional # nodes that were not present. - sig { abstract.returns(T::Array[T.nilable(Node)]) } + sig { abstract.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end - sig { abstract.returns(T::Array[T.nilable(Node)]) } + sig { abstract.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end # With a block given, yields each child node. Without a block, returns # an enumerator that contains each child node. Excludes any `nil`s in # the place of optional nodes that were not present. sig { abstract.returns(T::Enumerator[Node]) } - sig { abstract.params(blk: T.proc.params(arg0: Node).void).void } + sig { abstract.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # Returns an array of child nodes, excluding any `nil`s in the place of @@ -210,7 +210,7 @@ module Prism # Returns an array of child nodes and locations that could potentially have # comments attached to them. - sig { abstract.returns(T::Array[T.any(Node, Location)]) } + sig { abstract.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Returns a string representation of the node. @@ -246,20 +246,20 @@ module Prism # ^^^^^^^^^^^^^^^ class AliasGlobalVariableNode < Node # Initialize a new AliasGlobalVariableNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).void } def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -267,17 +267,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, new_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode), old_name: ::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode), keyword_loc: Location).returns(AliasGlobalVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -295,14 +295,14 @@ module Prism # # alias $foo $bar # ^^^^ - sig { returns(T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } + sig { returns(::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } def new_name; end # Represents the old name of the global variable that can be used before aliasing. # # alias $foo $bar # ^^^^ - sig { returns(T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode)) } + sig { returns(::T.any(GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, SymbolNode, MissingNode)) } def old_name; end # The Location of the `alias` keyword. @@ -314,14 +314,14 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of keyword_loc from the source. sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -331,20 +331,20 @@ module Prism # ^^^^^^^^^^^^^ class AliasMethodNode < Node # Initialize a new AliasMethodNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: T.any(SymbolNode, InterpolatedSymbolNode), old_name: T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(SymbolNode, InterpolatedSymbolNode), old_name: ::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).void } def initialize(source, node_id, location, flags, new_name, old_name, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -352,17 +352,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, new_name: T.any(SymbolNode, InterpolatedSymbolNode), old_name: T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, new_name: ::T.any(SymbolNode, InterpolatedSymbolNode), old_name: ::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode), keyword_loc: Location).returns(AliasMethodNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), new_name: T.unsafe(nil), old_name: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -386,7 +386,7 @@ module Prism # # alias :"#{foo}" :"#{bar}" # ^^^^^^^^^ - sig { returns(T.any(SymbolNode, InterpolatedSymbolNode)) } + sig { returns(::T.any(SymbolNode, InterpolatedSymbolNode)) } def new_name; end # Represents the old name of the method that will be aliased. @@ -399,7 +399,7 @@ module Prism # # alias :"#{foo}" :"#{bar}" # ^^^^^^^^^ - sig { returns(T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode)) } + sig { returns(::T.any(SymbolNode, InterpolatedSymbolNode, GlobalVariableReadNode, MissingNode)) } def old_name; end # Represents the Location of the `alias` keyword. @@ -411,14 +411,14 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of keyword_loc from the source. sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -432,16 +432,16 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -449,17 +449,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AlternationPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -496,14 +496,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -517,16 +517,16 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -534,17 +534,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(AndNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -587,14 +587,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -608,16 +608,16 @@ module Prism def initialize(source, node_id, location, flags, arguments); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -625,17 +625,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T::Array[Node]).returns(ArgumentsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -676,7 +676,7 @@ module Prism sig { returns(T::Array[Node]) } def arguments; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -686,20 +686,20 @@ module Prism # ^^^^^^^^^ class ArrayNode < Node # Initialize a new ArrayNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, elements, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -707,17 +707,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -745,12 +745,12 @@ module Prism # %w[foo bar baz] # "%w[" # %I(apple orange banana) # "%I(" # foo = 1, 2, 3 # nil - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Represents the optional source Location for the closing token. @@ -759,23 +759,23 @@ module Prism # %w[foo bar baz] # "]" # %I(apple orange banana) # ")" # foo = 1, 2, 3 # nil - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -797,20 +797,20 @@ module Prism # ^^^^^^^^^^^^ class ArrayPatternNode < Node # Initialize a new ArrayPatternNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: ::T.nilable(Node), posts: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, constant, requireds, rest, posts, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -818,17 +818,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: T.nilable(Node), posts: T::Array[Node], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(ArrayPatternNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), requireds: T::Array[Node], rest: ::T.nilable(Node), posts: T::Array[Node], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(ArrayPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), requireds: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -852,7 +852,7 @@ module Prism # # foo in Bar::Baz[1, 2, 3] # ^^^^^^^^ - sig { returns(T.nilable(T.any(ConstantPathNode, ConstantReadNode))) } + sig { returns(::T.nilable(::T.any(ConstantPathNode, ConstantReadNode))) } def constant; end # Represents the required elements of the array pattern. @@ -866,7 +866,7 @@ module Prism # # foo in *bar # ^^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def rest; end # Represents the elements after the rest element of the array pattern. @@ -880,35 +880,35 @@ module Prism # # foo in [1, 2] # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Represents the closing Location of the array pattern. # # foo in [1, 2] # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -918,20 +918,20 @@ module Prism # ^^^^^^ class AssocNode < Node # Initialize a new AssocNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, key, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -939,17 +939,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: T.nilable(Location)).returns(AssocNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, key: Node, value: Node, operator_loc: ::T.nilable(Location)).returns(AssocNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), key: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -990,19 +990,19 @@ module Prism # # { foo => bar } # ^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def operator_loc; end # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1012,20 +1012,20 @@ module Prism # ^^^^^ class AssocSplatNode < Node # Initialize a new AssocSplatNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.nilable(Node), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.nilable(Node), operator_loc: Location).void } def initialize(source, node_id, location, flags, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1033,17 +1033,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, value: T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, value: ::T.nilable(Node), operator_loc: Location).returns(AssocSplatNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1061,7 +1061,7 @@ module Prism # # { **foo } # ^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def value; end # The Location of the `**` operator. @@ -1073,14 +1073,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1094,16 +1094,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1111,17 +1111,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BackReferenceReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1143,7 +1143,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1155,20 +1155,20 @@ module Prism # ^^^^^ class BeginNode < Node # Initialize a new BeginNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), rescue_clause: T.nilable(RescueNode), else_clause: T.nilable(ElseNode), ensure_clause: T.nilable(EnsureNode), end_keyword_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), rescue_clause: ::T.nilable(RescueNode), else_clause: ::T.nilable(ElseNode), ensure_clause: ::T.nilable(EnsureNode), end_keyword_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, begin_keyword_loc, statements, rescue_clause, else_clause, ensure_clause, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1176,17 +1176,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), rescue_clause: T.nilable(RescueNode), else_clause: T.nilable(ElseNode), ensure_clause: T.nilable(EnsureNode), end_keyword_loc: T.nilable(Location)).returns(BeginNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, begin_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), rescue_clause: ::T.nilable(RescueNode), else_clause: ::T.nilable(ElseNode), ensure_clause: ::T.nilable(EnsureNode), end_keyword_loc: ::T.nilable(Location)).returns(BeginNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), begin_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), rescue_clause: T.unsafe(nil), else_clause: T.unsafe(nil), ensure_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1204,63 +1204,63 @@ module Prism # # begin x end # ^^^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def begin_keyword_loc; end # Save the begin_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_begin_keyword_loc(repository); end # Represents the statements within the begin block. # # begin x end # ^ - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Represents the rescue clause within the begin block. # # begin x; rescue y; end # ^^^^^^^^ - sig { returns(T.nilable(RescueNode)) } + sig { returns(::T.nilable(RescueNode)) } def rescue_clause; end # Represents the else clause within the begin block. # # begin x; rescue y; else z; end # ^^^^^^^^^^^ - sig { returns(T.nilable(ElseNode)) } + sig { returns(::T.nilable(ElseNode)) } def else_clause; end # Represents the ensure clause within the begin block. # # begin x; ensure y; end # ^^^^^^^^ - sig { returns(T.nilable(EnsureNode)) } + sig { returns(::T.nilable(EnsureNode)) } def ensure_clause; end # Represents the Location of the `end` keyword. # # begin x end # ^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def end_keyword_loc; end # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_end_keyword_loc(repository); end # Slice the location of begin_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def begin_keyword; end # Slice the location of end_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1270,20 +1270,20 @@ module Prism # ^^^^^ class BlockArgumentNode < Node # Initialize a new BlockArgumentNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, expression: ::T.nilable(Node), operator_loc: Location).void } def initialize(source, node_id, location, flags, expression, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1291,17 +1291,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, expression: T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, expression: ::T.nilable(Node), operator_loc: Location).returns(BlockArgumentNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1319,7 +1319,7 @@ module Prism # # foo(&args) # ^^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def expression; end # Represents the Location of the `&` operator. @@ -1331,14 +1331,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1352,16 +1352,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1369,17 +1369,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(BlockLocalVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1404,7 +1404,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1414,20 +1414,20 @@ module Prism # ^^^^^^^^^^^^^^ class BlockNode < Node # Initialize a new BlockNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).void } def initialize(source, node_id, location, flags, locals, parameters, body, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1435,17 +1435,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), opening_loc: Location, closing_loc: Location).returns(BlockNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1474,14 +1474,14 @@ module Prism # ^^^^^^^^^^^ # [1, 2, 3].each { puts it } # ^^^^^^^^^^^ - sig { returns(T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } + sig { returns(::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } def parameters; end # The body of the block. # # [1, 2, 3].each { |i| puts x } # ^^^^^^ - sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } def body; end # Represents the Location of the opening `{` or `do`. @@ -1493,7 +1493,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Represents the Location of the closing `}` or `end`. @@ -1505,7 +1505,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. @@ -1516,7 +1516,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1527,20 +1527,20 @@ module Prism # end class BlockParameterNode < Node # Initialize a new BlockParameterNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).void } def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1548,17 +1548,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(BlockParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1581,19 +1581,19 @@ module Prism # def a(&b) # name `:b` # ^ # end - sig { returns(T.nilable(Symbol)) } + sig { returns(::T.nilable(Symbol)) } def name; end # Represents the Location of the block parameter name. # # def a(&b) # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def name_loc; end # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_name_loc(repository); end # Represents the Location of the `&` operator. @@ -1606,14 +1606,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1627,20 +1627,20 @@ module Prism # end class BlockParametersNode < Node # Initialize a new BlockParametersNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parameters: ::T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, parameters, locals, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1648,17 +1648,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, parameters: T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(BlockParametersNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, parameters: ::T.nilable(ParametersNode), locals: T::Array[BlockLocalVariableNode], opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(BlockParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parameters: T.unsafe(nil), locals: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1680,7 +1680,7 @@ module Prism # foo do |a, b = 1; local| # ^^^^^^^^ # end - sig { returns(T.nilable(ParametersNode)) } + sig { returns(::T.nilable(ParametersNode)) } def parameters; end # Represents the local variables of the block. @@ -1702,12 +1702,12 @@ module Prism # foo do |a, b = 1; local| # ^ # end - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Represents the closing Location of the block parameters. @@ -1718,23 +1718,23 @@ module Prism # foo do |a, b = 1; local| # ^ # end - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1744,20 +1744,20 @@ module Prism # ^^^^^^^^^ class BreakNode < Node # Initialize a new BreakNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).void } def initialize(source, node_id, location, flags, arguments, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1765,17 +1765,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(BreakNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1793,7 +1793,7 @@ module Prism # # break foo # ^^^ - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # The Location of the `break` keyword. @@ -1805,14 +1805,14 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of keyword_loc from the source. sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1822,20 +1822,20 @@ module Prism # ^^^^^^^^^^^^^^^^^ class CallAndWriteNode < Node # Initialize a new CallAndWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -1843,17 +1843,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -1887,31 +1887,31 @@ module Prism # # foo.bar &&= value # ^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Represents the Location of the call operator. # # foo.bar &&= value # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def call_operator_loc; end # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_call_operator_loc(repository); end # Represents the Location of the message. # # foo.bar &&= value # ^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def message_loc; end # Save the message_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_message_loc(repository); end # Represents the name of the method being called. @@ -1937,7 +1937,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Represents the value being assigned. @@ -1948,18 +1948,18 @@ module Prism def value; end # Slice the location of call_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def call_operator; end # Slice the location of message_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def message; end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -1984,20 +1984,20 @@ module Prism # ^^^^^^^^ class CallNode < Node # Initialize a new CallNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), name: Symbol, message_loc: T.nilable(Location), opening_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), closing_loc: T.nilable(Location), equal_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), name: Symbol, message_loc: ::T.nilable(Location), opening_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), closing_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).void } def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc, opening_loc, arguments, closing_loc, equal_loc, block); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2005,17 +2005,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), name: Symbol, message_loc: T.nilable(Location), opening_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), closing_loc: T.nilable(Location), equal_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), name: Symbol, message_loc: ::T.nilable(Location), opening_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), closing_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(CallNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), block: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2055,7 +2055,7 @@ module Prism # # foo + bar # ^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Represents the Location of the call operator. @@ -2065,12 +2065,12 @@ module Prism # # foo&.bar # ^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def call_operator_loc; end # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_call_operator_loc(repository); end # Represents the name of the method being called. @@ -2084,43 +2084,43 @@ module Prism # # foo.bar # ^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def message_loc; end # Save the message_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_message_loc(repository); end # Represents the Location of the left parenthesis. # # foo(bar) # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). # # foo(bar) # ^^^ - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Represents the Location of the right parenthesis. # # foo(bar) # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Represents the Location of the equal sign, in the case that this is an attribute write. @@ -2130,42 +2130,42 @@ module Prism # # foo[bar] = value # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def equal_loc; end # Save the equal_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_equal_loc(repository); end # Represents the block that is being passed to the method. # # foo { |a| a } # ^^^^^^^^^ - sig { returns(T.nilable(T.any(BlockNode, BlockArgumentNode))) } + sig { returns(::T.nilable(::T.any(BlockNode, BlockArgumentNode))) } def block; end # Slice the location of call_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def call_operator; end # Slice the location of message_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def message; end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end # Slice the location of equal_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def equal; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -2175,20 +2175,20 @@ module Prism # ^^^^^^^^^^^^^^ class CallOperatorWriteNode < Node # Initialize a new CallOperatorWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, binary_operator, binary_operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2196,17 +2196,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(CallOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2240,31 +2240,31 @@ module Prism # # foo.bar += value # ^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Represents the Location of the call operator. # # foo.bar += value # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def call_operator_loc; end # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_call_operator_loc(repository); end # Represents the Location of the message. # # foo.bar += value # ^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def message_loc; end # Save the message_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_message_loc(repository); end # Represents the name of the method being called. @@ -2297,7 +2297,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Represents the value being assigned. @@ -2308,14 +2308,14 @@ module Prism def value; end # Slice the location of call_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def call_operator; end # Slice the location of message_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def message; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -2325,20 +2325,20 @@ module Prism # ^^^^^^^^^^^^^^^^^ class CallOrWriteNode < Node # Initialize a new CallOrWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).void } def initialize(source, node_id, location, flags, receiver, call_operator_loc, message_loc, read_name, write_name, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2346,17 +2346,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), message_loc: T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), message_loc: ::T.nilable(Location), read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node).returns(CallOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), message_loc: T.unsafe(nil), read_name: T.unsafe(nil), write_name: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2390,31 +2390,31 @@ module Prism # # foo.bar ||= value # ^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Represents the Location of the call operator. # # foo.bar ||= value # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def call_operator_loc; end # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_call_operator_loc(repository); end # Represents the Location of the message. # # foo.bar ||= value # ^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def message_loc; end # Save the message_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_message_loc(repository); end # Represents the name of the method being called. @@ -2440,7 +2440,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Represents the value being assigned. @@ -2451,18 +2451,18 @@ module Prism def value; end # Slice the location of call_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def call_operator; end # Slice the location of message_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def message; end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -2484,16 +2484,16 @@ module Prism def initialize(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2501,17 +2501,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, call_operator_loc: Location, name: Symbol, message_loc: Location).returns(CallTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), name: T.unsafe(nil), message_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2557,7 +2557,7 @@ module Prism # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_call_operator_loc(repository); end # Represents the name of the method being called. @@ -2576,7 +2576,7 @@ module Prism # Save the message_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_message_loc(repository); end # Slice the location of call_operator_loc from the source. @@ -2587,7 +2587,7 @@ module Prism sig { returns(String) } def message; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -2601,16 +2601,16 @@ module Prism def initialize(source, node_id, location, flags, value, target, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2618,17 +2618,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, target: LocalVariableTargetNode, operator_loc: Location).returns(CapturePatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2665,14 +2665,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -2684,20 +2684,20 @@ module Prism # ^^^^^^^^^ class CaseMatchNode < Node # Initialize a new CaseMatchNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[InNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[InNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2705,17 +2705,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[InNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[InNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseMatchNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2733,7 +2733,7 @@ module Prism # # case true; in false; end # ^^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def predicate; end # Represents the conditions of the case match. @@ -2747,7 +2747,7 @@ module Prism # # case true; in false; else; end # ^^^^^^^^^ - sig { returns(T.nilable(ElseNode)) } + sig { returns(::T.nilable(ElseNode)) } def else_clause; end # Represents the Location of the `case` keyword. @@ -2759,7 +2759,7 @@ module Prism # Save the case_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_case_keyword_loc(repository); end # Represents the Location of the `end` keyword. @@ -2771,7 +2771,7 @@ module Prism # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_end_keyword_loc(repository); end # Slice the location of case_keyword_loc from the source. @@ -2782,7 +2782,7 @@ module Prism sig { returns(String) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -2794,20 +2794,20 @@ module Prism # ^^^^^^^^^^ class CaseNode < Node # Initialize a new CaseNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[WhenNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[WhenNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).void } def initialize(source, node_id, location, flags, predicate, conditions, else_clause, case_keyword_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2815,17 +2815,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, predicate: T.nilable(Node), conditions: T::Array[WhenNode], else_clause: T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, predicate: ::T.nilable(Node), conditions: T::Array[WhenNode], else_clause: ::T.nilable(ElseNode), case_keyword_loc: Location, end_keyword_loc: Location).returns(CaseNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), predicate: T.unsafe(nil), conditions: T.unsafe(nil), else_clause: T.unsafe(nil), case_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2843,7 +2843,7 @@ module Prism # # case true; when false; end # ^^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def predicate; end # Represents the conditions of the case statement. @@ -2857,7 +2857,7 @@ module Prism # # case true; when false; else; end # ^^^^^^^^^ - sig { returns(T.nilable(ElseNode)) } + sig { returns(::T.nilable(ElseNode)) } def else_clause; end # Represents the Location of the `case` keyword. @@ -2869,7 +2869,7 @@ module Prism # Save the case_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_case_keyword_loc(repository); end # Represents the Location of the `end` keyword. @@ -2881,7 +2881,7 @@ module Prism # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_end_keyword_loc(repository); end # Slice the location of case_keyword_loc from the source. @@ -2892,7 +2892,7 @@ module Prism sig { returns(String) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -2902,20 +2902,20 @@ module Prism # ^^^^^^^^^^^^^ class ClassNode < Node # Initialize a new ClassNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: T.nilable(Location), superclass: T.nilable(Node), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: ::T.nilable(Location), superclass: ::T.nilable(Node), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } def initialize(source, node_id, location, flags, locals, class_keyword_loc, constant_path, inheritance_operator_loc, superclass, body, end_keyword_loc, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -2923,17 +2923,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: T.nilable(Location), superclass: T.nilable(Node), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, CallNode), inheritance_operator_loc: ::T.nilable(Location), superclass: ::T.nilable(Node), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ClassNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), inheritance_operator_loc: T.unsafe(nil), superclass: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -2960,37 +2960,37 @@ module Prism # Save the class_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_class_keyword_loc(repository); end # Returns the `constant_path` attribute. - sig { returns(T.any(ConstantReadNode, ConstantPathNode, CallNode)) } + sig { returns(::T.any(ConstantReadNode, ConstantPathNode, CallNode)) } def constant_path; end # Represents the Location of the `<` operator. # # class Foo < Bar # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def inheritance_operator_loc; end # Save the inheritance_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_inheritance_operator_loc(repository); end # Represents the superclass of the class. # # class Foo < Bar # ^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def superclass; end # Represents the body of the class. # # class Foo; bar; end # ^^^ - sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } def body; end # Represents the Location of the `end` keyword. @@ -3002,7 +3002,7 @@ module Prism # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_end_keyword_loc(repository); end # The name of the class. @@ -3016,14 +3016,14 @@ module Prism def class_keyword; end # Slice the location of inheritance_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def inheritance_operator; end # Slice the location of end_keyword_loc from the source. sig { returns(String) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3037,16 +3037,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3054,17 +3054,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3094,7 +3094,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Represents the Location of the `&&=` operator. @@ -3106,7 +3106,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -3120,7 +3120,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3134,16 +3134,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3151,17 +3151,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ClassVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3185,7 +3185,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `binary_operator_loc`. @@ -3194,7 +3194,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Returns the `value` attribute. @@ -3205,7 +3205,7 @@ module Prism sig { returns(Symbol) } def binary_operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3219,16 +3219,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3236,17 +3236,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ClassVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3270,7 +3270,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -3279,7 +3279,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -3290,7 +3290,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3304,16 +3304,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3321,17 +3321,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3353,7 +3353,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3367,16 +3367,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3384,17 +3384,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ClassVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3412,7 +3412,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3426,16 +3426,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3443,17 +3443,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ClassVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3484,7 +3484,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # The value to write to the class variable. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -3506,14 +3506,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3527,16 +3527,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3544,17 +3544,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3578,7 +3578,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -3587,7 +3587,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -3598,7 +3598,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3612,16 +3612,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3629,17 +3629,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3663,7 +3663,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `binary_operator_loc`. @@ -3672,7 +3672,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Returns the `value` attribute. @@ -3683,7 +3683,7 @@ module Prism sig { returns(Symbol) } def binary_operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3697,16 +3697,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3714,17 +3714,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(ConstantOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3748,7 +3748,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -3757,7 +3757,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -3768,7 +3768,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3782,16 +3782,16 @@ module Prism def initialize(source, node_id, location, flags, target, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3799,17 +3799,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3833,7 +3833,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -3844,7 +3844,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3854,20 +3854,20 @@ module Prism # ^^^^^^^^ class ConstantPathNode < Node # Initialize a new ConstantPathNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3875,17 +3875,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -3909,11 +3909,11 @@ module Prism # # a.b::C # ^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def parent; end # The name of the constant being accessed. This could be `nil` in the event of a syntax error. - sig { returns(T.nilable(Symbol)) } + sig { returns(::T.nilable(Symbol)) } def name; end # The Location of the `::` delimiter. @@ -3928,7 +3928,7 @@ module Prism # Save the delimiter_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_delimiter_loc(repository); end # The Location of the name of the constant. @@ -3943,14 +3943,14 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Slice the location of delimiter_loc from the source. sig { returns(String) } def delimiter; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -3964,16 +3964,16 @@ module Prism def initialize(source, node_id, location, flags, target, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -3981,17 +3981,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(ConstantPathOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4015,7 +4015,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Returns the `value` attribute. @@ -4026,7 +4026,7 @@ module Prism sig { returns(Symbol) } def binary_operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4040,16 +4040,16 @@ module Prism def initialize(source, node_id, location, flags, target, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4057,17 +4057,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4091,7 +4091,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -4102,7 +4102,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4112,20 +4112,20 @@ module Prism # ^^^^^^^^ ^^^^^^^^ class ConstantPathTargetNode < Node # Initialize a new ConstantPathTargetNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).void } def initialize(source, node_id, location, flags, parent, name, delimiter_loc, name_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4133,17 +4133,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, parent: T.nilable(Node), name: T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, parent: ::T.nilable(Node), name: ::T.nilable(Symbol), delimiter_loc: Location, name_loc: Location).returns(ConstantPathTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), parent: T.unsafe(nil), name: T.unsafe(nil), delimiter_loc: T.unsafe(nil), name_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4158,11 +4158,11 @@ module Prism def inspect; end # Returns the `parent` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def parent; end # Returns the `name` attribute. - sig { returns(T.nilable(Symbol)) } + sig { returns(::T.nilable(Symbol)) } def name; end # Returns the Location represented by `delimiter_loc`. @@ -4171,7 +4171,7 @@ module Prism # Save the delimiter_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_delimiter_loc(repository); end # Returns the Location represented by `name_loc`. @@ -4180,14 +4180,14 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Slice the location of delimiter_loc from the source. sig { returns(String) } def delimiter; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4207,16 +4207,16 @@ module Prism def initialize(source, node_id, location, flags, target, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4224,17 +4224,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, target: ConstantPathNode, operator_loc: Location, value: Node).returns(ConstantPathWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), target: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4267,7 +4267,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # The value to write to the constant path. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -4281,7 +4281,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4295,16 +4295,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4312,17 +4312,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4344,7 +4344,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4358,16 +4358,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4375,17 +4375,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(ConstantTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4403,7 +4403,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4417,16 +4417,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4434,17 +4434,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(ConstantWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4475,7 +4475,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # The value to write to the constant. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -4497,14 +4497,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4515,20 +4515,20 @@ module Prism # ^^^^^^^^^^ class DefNode < Node # Initialize a new DefNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: T.nilable(Node), parameters: T.nilable(ParametersNode), body: T.nilable(T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: T.nilable(Location), lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), equal_loc: T.nilable(Location), end_keyword_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: ::T.nilable(Node), parameters: ::T.nilable(ParametersNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: ::T.nilable(Location), lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), end_keyword_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, name, name_loc, receiver, parameters, body, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4536,17 +4536,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: T.nilable(Node), parameters: T.nilable(ParametersNode), body: T.nilable(T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: T.nilable(Location), lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), equal_loc: T.nilable(Location), end_keyword_loc: T.nilable(Location)).returns(DefNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, receiver: ::T.nilable(Node), parameters: ::T.nilable(ParametersNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), locals: T::Array[Symbol], def_keyword_loc: Location, operator_loc: ::T.nilable(Location), lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), equal_loc: ::T.nilable(Location), end_keyword_loc: ::T.nilable(Location)).returns(DefNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), receiver: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil), locals: T.unsafe(nil), def_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), equal_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4570,19 +4570,19 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the `receiver` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Returns the `parameters` attribute. - sig { returns(T.nilable(ParametersNode)) } + sig { returns(::T.nilable(ParametersNode)) } def parameters; end # Returns the `body` attribute. - sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } def body; end # Returns the `locals` attribute. @@ -4595,52 +4595,52 @@ module Prism # Save the def_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_def_keyword_loc(repository); end # Returns the Location represented by `operator_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def operator_loc; end # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_operator_loc(repository); end # Returns the Location represented by `lparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def lparen_loc; end # Save the lparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_lparen_loc(repository); end # Returns the Location represented by `rparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def rparen_loc; end # Save the rparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_rparen_loc(repository); end # Returns the Location represented by `equal_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def equal_loc; end # Save the equal_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_equal_loc(repository); end # Returns the Location represented by `end_keyword_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def end_keyword_loc; end # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_end_keyword_loc(repository); end # Slice the location of def_keyword_loc from the source. @@ -4648,26 +4648,26 @@ module Prism def def_keyword; end # Slice the location of operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def operator; end # Slice the location of lparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def lparen; end # Slice the location of rparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def rparen; end # Slice the location of equal_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def equal; end # Slice the location of end_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4677,20 +4677,20 @@ module Prism # ^^^^^^^^^^^ class DefinedNode < Node # Initialize a new DefinedNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: T.nilable(Location), value: Node, rparen_loc: T.nilable(Location), keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lparen_loc: ::T.nilable(Location), value: Node, rparen_loc: ::T.nilable(Location), keyword_loc: Location).void } def initialize(source, node_id, location, flags, lparen_loc, value, rparen_loc, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4698,17 +4698,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, lparen_loc: T.nilable(Location), value: Node, rparen_loc: T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, lparen_loc: ::T.nilable(Location), value: Node, rparen_loc: ::T.nilable(Location), keyword_loc: Location).returns(DefinedNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lparen_loc: T.unsafe(nil), value: T.unsafe(nil), rparen_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4723,12 +4723,12 @@ module Prism def inspect; end # Returns the Location represented by `lparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def lparen_loc; end # Save the lparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_lparen_loc(repository); end # Returns the `value` attribute. @@ -4736,12 +4736,12 @@ module Prism def value; end # Returns the Location represented by `rparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def rparen_loc; end # Save the rparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_rparen_loc(repository); end # Returns the Location represented by `keyword_loc`. @@ -4750,22 +4750,22 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of lparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def lparen; end # Slice the location of rparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def rparen; end # Slice the location of keyword_loc from the source. sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4775,20 +4775,20 @@ module Prism # ^^^^^^^^^^ class ElseNode < Node # Initialize a new ElseNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, else_keyword_loc, statements, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4796,17 +4796,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: T.nilable(Location)).returns(ElseNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, else_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: ::T.nilable(Location)).returns(ElseNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), else_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4826,20 +4826,20 @@ module Prism # Save the else_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_else_keyword_loc(repository); end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Returns the Location represented by `end_keyword_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def end_keyword_loc; end # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_end_keyword_loc(repository); end # Slice the location of else_keyword_loc from the source. @@ -4847,10 +4847,10 @@ module Prism def else_keyword; end # Slice the location of end_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4860,20 +4860,20 @@ module Prism # ^^^^^^ class EmbeddedStatementsNode < Node # Initialize a new EmbeddedStatementsNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: T.nilable(StatementsNode), closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: ::T.nilable(StatementsNode), closing_loc: Location).void } def initialize(source, node_id, location, flags, opening_loc, statements, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4881,17 +4881,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, statements: ::T.nilable(StatementsNode), closing_loc: Location).returns(EmbeddedStatementsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), statements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4911,11 +4911,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Returns the Location represented by `closing_loc`. @@ -4924,7 +4924,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. @@ -4935,7 +4935,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -4945,20 +4945,20 @@ module Prism # ^^^^^ class EmbeddedVariableNode < Node # Initialize a new EmbeddedVariableNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: ::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).void } def initialize(source, node_id, location, flags, operator_loc, variable); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -4966,17 +4966,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, variable: ::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)).returns(EmbeddedVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), variable: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -4996,18 +4996,18 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `variable` attribute. - sig { returns(T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } + sig { returns(::T.any(InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode)) } def variable; end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5021,20 +5021,20 @@ module Prism # end class EnsureNode < Node # Initialize a new EnsureNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: Location).void } def initialize(source, node_id, location, flags, ensure_keyword_loc, statements, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5042,17 +5042,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, ensure_keyword_loc: Location, statements: ::T.nilable(StatementsNode), end_keyword_loc: Location).returns(EnsureNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), ensure_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5072,11 +5072,11 @@ module Prism # Save the ensure_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_ensure_keyword_loc(repository); end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Returns the Location represented by `end_keyword_loc`. @@ -5085,7 +5085,7 @@ module Prism # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_end_keyword_loc(repository); end # Slice the location of ensure_keyword_loc from the source. @@ -5096,7 +5096,7 @@ module Prism sig { returns(String) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5110,16 +5110,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5127,17 +5127,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(FalseNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5151,7 +5151,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5170,20 +5170,20 @@ module Prism # ^^^^^^^^^^^^^^^ class FindPatternNode < Node # Initialize a new FindPatternNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: T.any(SplatNode, MissingNode), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: ::T.any(SplatNode, MissingNode), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, constant, left, requireds, right, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5191,17 +5191,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: T.any(SplatNode, MissingNode), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(FindPatternNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), left: SplatNode, requireds: T::Array[Node], right: ::T.any(SplatNode, MissingNode), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(FindPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), left: T.unsafe(nil), requireds: T.unsafe(nil), right: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5219,7 +5219,7 @@ module Prism # # foo in Foo(*bar, baz, *qux) # ^^^ - sig { returns(T.nilable(T.any(ConstantPathNode, ConstantReadNode))) } + sig { returns(::T.nilable(::T.any(ConstantPathNode, ConstantReadNode))) } def constant; end # Represents the first wildcard node in the pattern. @@ -5249,7 +5249,7 @@ module Prism # # foo in Foo(*bar, baz, *qux) # ^^^^ - sig { returns(T.any(SplatNode, MissingNode)) } + sig { returns(::T.any(SplatNode, MissingNode)) } def right; end # The Location of the opening brace. @@ -5259,12 +5259,12 @@ module Prism # # foo in Foo(*bar, baz, *qux) # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # The Location of the closing brace. @@ -5274,23 +5274,23 @@ module Prism # # foo in Foo(*bar, baz, *qux) # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5300,20 +5300,20 @@ module Prism # ^^^^^^^^^^ class FlipFlopNode < Node # Initialize a new FlipFlopNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).void } def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5321,17 +5321,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(FlipFlopNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5350,11 +5350,11 @@ module Prism def exclude_end?; end # Returns the `left` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def left; end # Returns the `right` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def right; end # Returns the Location represented by `operator_loc`. @@ -5363,14 +5363,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5384,16 +5384,16 @@ module Prism def initialize(source, node_id, location, flags, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5401,17 +5401,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, value: Float).returns(FloatNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5429,7 +5429,7 @@ module Prism sig { returns(Float) } def value; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5439,20 +5439,20 @@ module Prism # ^^^^^^^^^^^^^^ class ForNode < Node # Initialize a new ForNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: T.nilable(Location), end_keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, index: ::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: ::T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), end_keyword_loc: Location).void } def initialize(source, node_id, location, flags, index, collection, statements, for_keyword_loc, in_keyword_loc, do_keyword_loc, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5460,17 +5460,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, index: T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, index: ::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode), collection: Node, statements: ::T.nilable(StatementsNode), for_keyword_loc: Location, in_keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), end_keyword_loc: Location).returns(ForNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), index: T.unsafe(nil), collection: T.unsafe(nil), statements: T.unsafe(nil), for_keyword_loc: T.unsafe(nil), in_keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5488,7 +5488,7 @@ module Prism # # for i in a end # ^ - sig { returns(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)) } + sig { returns(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)) } def index; end # The collection to iterate over. @@ -5504,7 +5504,7 @@ module Prism # foo(i) # ^^^^^^ # end - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # The Location of the `for` keyword. @@ -5516,7 +5516,7 @@ module Prism # Save the for_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_for_keyword_loc(repository); end # The Location of the `in` keyword. @@ -5528,19 +5528,19 @@ module Prism # Save the in_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_in_keyword_loc(repository); end # The Location of the `do` keyword, if present. # # for i in a do end # ^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def do_keyword_loc; end # Save the do_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_do_keyword_loc(repository); end # The Location of the `end` keyword. @@ -5552,7 +5552,7 @@ module Prism # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_end_keyword_loc(repository); end # Slice the location of for_keyword_loc from the source. @@ -5564,14 +5564,14 @@ module Prism def in_keyword; end # Slice the location of do_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def do_keyword; end # Slice the location of end_keyword_loc from the source. sig { returns(String) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5587,16 +5587,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5604,17 +5604,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingArgumentsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5628,7 +5628,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5643,16 +5643,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5660,17 +5660,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(ForwardingParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5684,7 +5684,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5699,20 +5699,20 @@ module Prism # If it has any other arguments, it would be a `SuperNode` instead. class ForwardingSuperNode < Node # Initialize a new ForwardingSuperNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: T.nilable(BlockNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, block: ::T.nilable(BlockNode)).void } def initialize(source, node_id, location, flags, block); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5720,17 +5720,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, block: T.nilable(BlockNode)).returns(ForwardingSuperNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, block: ::T.nilable(BlockNode)).returns(ForwardingSuperNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), block: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5745,10 +5745,10 @@ module Prism def inspect; end # All other arguments are forwarded as normal, except the original block is replaced with the new block. - sig { returns(T.nilable(BlockNode)) } + sig { returns(::T.nilable(BlockNode)) } def block; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5762,16 +5762,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5779,17 +5779,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5813,7 +5813,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -5822,7 +5822,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -5833,7 +5833,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5847,16 +5847,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5864,17 +5864,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(GlobalVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5898,7 +5898,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `binary_operator_loc`. @@ -5907,7 +5907,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Returns the `value` attribute. @@ -5918,7 +5918,7 @@ module Prism sig { returns(Symbol) } def binary_operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -5932,16 +5932,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -5949,17 +5949,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(GlobalVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -5983,7 +5983,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -5992,7 +5992,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -6003,7 +6003,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6017,16 +6017,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6034,17 +6034,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6066,7 +6066,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6080,16 +6080,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6097,17 +6097,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(GlobalVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6125,7 +6125,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6139,16 +6139,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6156,17 +6156,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(GlobalVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6197,7 +6197,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # The value to write to the global variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -6219,14 +6219,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6236,20 +6236,20 @@ module Prism # ^^^^^^^^^^ class HashNode < Node # Initialize a new HashNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[T.any(AssocNode, AssocSplatNode)], closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[::T.any(AssocNode, AssocSplatNode)], closing_loc: Location).void } def initialize(source, node_id, location, flags, opening_loc, elements, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6257,17 +6257,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, elements: T::Array[::T.any(AssocNode, AssocSplatNode)], closing_loc: Location).returns(HashNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), elements: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6290,7 +6290,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s. @@ -6300,7 +6300,7 @@ module Prism # # { **foo } # ^^^^^ - sig { returns(T::Array[T.any(AssocNode, AssocSplatNode)]) } + sig { returns(T::Array[::T.any(AssocNode, AssocSplatNode)]) } def elements; end # The Location of the closing brace. @@ -6312,7 +6312,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. @@ -6323,7 +6323,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6342,20 +6342,20 @@ module Prism # ^^^^^^^^^^^^^^ class HashPatternNode < Node # Initialize a new HashPatternNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: ::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, constant, elements, rest, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6363,17 +6363,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, constant: T.nilable(T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: T.nilable(Location), closing_loc: T.nilable(Location)).returns(HashPatternNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, constant: ::T.nilable(::T.any(ConstantPathNode, ConstantReadNode)), elements: T::Array[AssocNode], rest: ::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode)), opening_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location)).returns(HashPatternNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), constant: T.unsafe(nil), elements: T.unsafe(nil), rest: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6394,7 +6394,7 @@ module Prism # # foo => Bar::Baz[a: 1, b: 2] # ^^^^^^^^ - sig { returns(T.nilable(T.any(ConstantPathNode, ConstantReadNode))) } + sig { returns(::T.nilable(::T.any(ConstantPathNode, ConstantReadNode))) } def constant; end # Represents the explicit named hash keys and values. @@ -6414,7 +6414,7 @@ module Prism # # foo => { a: 1, b:, **nil } # ^^^^^ - sig { returns(T.nilable(T.any(AssocSplatNode, NoKeywordsParameterNode))) } + sig { returns(::T.nilable(::T.any(AssocSplatNode, NoKeywordsParameterNode))) } def rest; end # The Location of the opening brace. @@ -6424,12 +6424,12 @@ module Prism # # foo => Bar[a: 1] # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # The Location of the closing brace. @@ -6439,23 +6439,23 @@ module Prism # # foo => Bar[a: 1] # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6471,20 +6471,20 @@ module Prism # ^^^^^^^^^^^^^^^ class IfNode < Node # Initialize a new IfNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: T.nilable(Location), predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(T.any(ElseNode, IfNode)), end_keyword_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, if_keyword_loc: ::T.nilable(Location), predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(::T.any(ElseNode, IfNode)), end_keyword_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, if_keyword_loc, predicate, then_keyword_loc, statements, subsequent, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6492,17 +6492,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, if_keyword_loc: T.nilable(Location), predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(T.any(ElseNode, IfNode)), end_keyword_loc: T.nilable(Location)).returns(IfNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, if_keyword_loc: ::T.nilable(Location), predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(::T.any(ElseNode, IfNode)), end_keyword_loc: ::T.nilable(Location)).returns(IfNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), if_keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6522,12 +6522,12 @@ module Prism # ^^ # # The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def if_keyword_loc; end # Save the if_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_if_keyword_loc(repository); end # The node for the condition the `IfNode` is testing. @@ -6552,12 +6552,12 @@ module Prism # # a ? b : c # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def then_keyword_loc; end # Save the then_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_then_keyword_loc(repository); end # Represents the body of statements that will be executed when the predicate is evaluated as truthy. Will be `nil` when no body is provided. @@ -6568,7 +6568,7 @@ module Prism # baz # ^^^ # end - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement. @@ -6584,7 +6584,7 @@ module Prism # # if foo then bar else baz end # ^^^^^^^^^^^^ - sig { returns(T.nilable(T.any(ElseNode, IfNode))) } + sig { returns(::T.nilable(::T.any(ElseNode, IfNode))) } def subsequent; end # The Location of the `end` keyword if present, `nil` otherwise. @@ -6593,27 +6593,27 @@ module Prism # bar # end # ^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def end_keyword_loc; end # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_end_keyword_loc(repository); end # Slice the location of if_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def if_keyword; end # Slice the location of then_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def then_keyword; end # Slice the location of end_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6623,20 +6623,20 @@ module Prism # ^^^^ class ImaginaryNode < Node # Initialize a new ImaginaryNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: T.any(FloatNode, IntegerNode, RationalNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, numeric: ::T.any(FloatNode, IntegerNode, RationalNode)).void } def initialize(source, node_id, location, flags, numeric); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6644,17 +6644,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, numeric: T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, numeric: ::T.any(FloatNode, IntegerNode, RationalNode)).returns(ImaginaryNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numeric: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6669,10 +6669,10 @@ module Prism def inspect; end # Returns the `numeric` attribute. - sig { returns(T.any(FloatNode, IntegerNode, RationalNode)) } + sig { returns(::T.any(FloatNode, IntegerNode, RationalNode)) } def numeric; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6688,20 +6688,20 @@ module Prism # ^^^^ class ImplicitNode < Node # Initialize a new ImplicitNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, value: ::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).void } def initialize(source, node_id, location, flags, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6709,17 +6709,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, value: T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, value: ::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)).returns(ImplicitNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6734,10 +6734,10 @@ module Prism def inspect; end # Returns the `value` attribute. - sig { returns(T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)) } + sig { returns(::T.any(LocalVariableReadNode, CallNode, ConstantReadNode, LocalVariableTargetNode)) } def value; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6760,16 +6760,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6777,17 +6777,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(ImplicitRestNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6801,7 +6801,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6811,20 +6811,20 @@ module Prism # ^^^^^^^^^^^ class InNode < Node # Initialize a new InNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: T.nilable(StatementsNode), in_loc: Location, then_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: ::T.nilable(StatementsNode), in_loc: Location, then_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, pattern, statements, in_loc, then_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6832,17 +6832,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: T.nilable(StatementsNode), in_loc: Location, then_loc: T.nilable(Location)).returns(InNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, pattern: Node, statements: ::T.nilable(StatementsNode), in_loc: Location, then_loc: ::T.nilable(Location)).returns(InNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), pattern: T.unsafe(nil), statements: T.unsafe(nil), in_loc: T.unsafe(nil), then_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6861,7 +6861,7 @@ module Prism def pattern; end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Returns the Location represented by `in_loc`. @@ -6870,16 +6870,16 @@ module Prism # Save the in_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_in_loc(repository); end # Returns the Location represented by `then_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def then_loc; end # Save the then_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_then_loc(repository); end # Slice the location of in_loc from the source. @@ -6887,10 +6887,10 @@ module Prism def in; end # Slice the location of then_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def then; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -6900,20 +6900,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^^^ class IndexAndWriteNode < Node # Initialize a new IndexAndWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -6921,17 +6921,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -6962,16 +6962,16 @@ module Prism def ignore_visibility?; end # Returns the `receiver` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Returns the Location represented by `call_operator_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def call_operator_loc; end # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_call_operator_loc(repository); end # Returns the Location represented by `opening_loc`. @@ -6980,11 +6980,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `arguments` attribute. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Returns the Location represented by `closing_loc`. @@ -6993,11 +6993,11 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `block` attribute. - sig { returns(T.nilable(BlockArgumentNode)) } + sig { returns(::T.nilable(BlockArgumentNode)) } def block; end # Returns the Location represented by `operator_loc`. @@ -7006,7 +7006,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -7014,7 +7014,7 @@ module Prism def value; end # Slice the location of call_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def call_operator; end # Slice the location of opening_loc from the source. @@ -7029,7 +7029,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7039,20 +7039,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^^ class IndexOperatorWriteNode < Node # Initialize a new IndexOperatorWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).void } def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, binary_operator, binary_operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7060,17 +7060,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), binary_operator: Symbol, binary_operator_loc: Location, value: Node).returns(IndexOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), binary_operator: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7101,16 +7101,16 @@ module Prism def ignore_visibility?; end # Returns the `receiver` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Returns the Location represented by `call_operator_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def call_operator_loc; end # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_call_operator_loc(repository); end # Returns the Location represented by `opening_loc`. @@ -7119,11 +7119,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `arguments` attribute. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Returns the Location represented by `closing_loc`. @@ -7132,11 +7132,11 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `block` attribute. - sig { returns(T.nilable(BlockArgumentNode)) } + sig { returns(::T.nilable(BlockArgumentNode)) } def block; end # Returns the `binary_operator` attribute. @@ -7149,7 +7149,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Returns the `value` attribute. @@ -7157,7 +7157,7 @@ module Prism def value; end # Slice the location of call_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def call_operator; end # Slice the location of opening_loc from the source. @@ -7168,7 +7168,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7178,20 +7178,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^^^ class IndexOrWriteNode < Node # Initialize a new IndexOrWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).void } def initialize(source, node_id, location, flags, receiver, call_operator_loc, opening_loc, arguments, closing_loc, block, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7199,17 +7199,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: T.nilable(Node), call_operator_loc: T.nilable(Location), opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: ::T.nilable(Node), call_operator_loc: ::T.nilable(Location), opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode), operator_loc: Location, value: Node).returns(IndexOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), call_operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7240,16 +7240,16 @@ module Prism def ignore_visibility?; end # Returns the `receiver` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def receiver; end # Returns the Location represented by `call_operator_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def call_operator_loc; end # Save the call_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_call_operator_loc(repository); end # Returns the Location represented by `opening_loc`. @@ -7258,11 +7258,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `arguments` attribute. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Returns the Location represented by `closing_loc`. @@ -7271,11 +7271,11 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `block` attribute. - sig { returns(T.nilable(BlockArgumentNode)) } + sig { returns(::T.nilable(BlockArgumentNode)) } def block; end # Returns the Location represented by `operator_loc`. @@ -7284,7 +7284,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -7292,7 +7292,7 @@ module Prism def value; end # Slice the location of call_operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def call_operator; end # Slice the location of opening_loc from the source. @@ -7307,7 +7307,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7325,20 +7325,20 @@ module Prism # ^^^^^^^^ class IndexTargetNode < Node # Initialize a new IndexTargetNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode)).void } def initialize(source, node_id, location, flags, receiver, opening_loc, arguments, closing_loc, block); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7346,17 +7346,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: T.nilable(ArgumentsNode), closing_loc: Location, block: T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, receiver: Node, opening_loc: Location, arguments: ::T.nilable(ArgumentsNode), closing_loc: Location, block: ::T.nilable(BlockArgumentNode)).returns(IndexTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), receiver: T.unsafe(nil), opening_loc: T.unsafe(nil), arguments: T.unsafe(nil), closing_loc: T.unsafe(nil), block: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7396,11 +7396,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `arguments` attribute. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Returns the Location represented by `closing_loc`. @@ -7409,11 +7409,11 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `block` attribute. - sig { returns(T.nilable(BlockArgumentNode)) } + sig { returns(::T.nilable(BlockArgumentNode)) } def block; end # Slice the location of opening_loc from the source. @@ -7424,7 +7424,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7438,16 +7438,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7455,17 +7455,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7489,7 +7489,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -7498,7 +7498,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -7509,7 +7509,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7523,16 +7523,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, binary_operator_loc, value, binary_operator); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7540,17 +7540,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, binary_operator_loc: Location, value: Node, binary_operator: Symbol).returns(InstanceVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), binary_operator: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7574,7 +7574,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `binary_operator_loc`. @@ -7583,7 +7583,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Returns the `value` attribute. @@ -7594,7 +7594,7 @@ module Prism sig { returns(Symbol) } def binary_operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7608,16 +7608,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7625,17 +7625,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(InstanceVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7659,7 +7659,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -7668,7 +7668,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -7679,7 +7679,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7693,16 +7693,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7710,17 +7710,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7742,7 +7742,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7756,16 +7756,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7773,17 +7773,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(InstanceVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7801,7 +7801,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7815,16 +7815,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7832,17 +7832,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node, operator_loc: Location).returns(InstanceVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7873,7 +7873,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # The value to write to the instance variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -7895,14 +7895,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7916,16 +7916,16 @@ module Prism def initialize(source, node_id, location, flags, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -7933,17 +7933,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, value: Integer).returns(IntegerNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -7977,7 +7977,7 @@ module Prism sig { returns(Integer) } def value; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -7987,20 +7987,20 @@ module Prism # ^^^^^^^^^^^^^^^^ class InterpolatedMatchLastLineNode < Node # Initialize a new InterpolatedMatchLastLineNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8008,17 +8008,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedMatchLastLineNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8082,11 +8082,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `parts` attribute. - sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } def parts; end # Returns the Location represented by `closing_loc`. @@ -8095,7 +8095,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. @@ -8106,7 +8106,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8116,20 +8116,20 @@ module Prism # ^^^^^^^^^^^^^^^^ class InterpolatedRegularExpressionNode < Node # Initialize a new InterpolatedRegularExpressionNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8137,17 +8137,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedRegularExpressionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8211,11 +8211,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `parts` attribute. - sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } def parts; end # Returns the Location represented by `closing_loc`. @@ -8224,7 +8224,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. @@ -8235,7 +8235,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8245,20 +8245,20 @@ module Prism # ^^^^^^^^^^^^^^^^ class InterpolatedStringNode < Node # Initialize a new InterpolatedStringNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8266,17 +8266,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: T.nilable(Location)).returns(InterpolatedStringNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedStringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8299,36 +8299,36 @@ module Prism def mutable?; end # Returns the Location represented by `opening_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Returns the `parts` attribute. - sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)]) } + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode, InterpolatedStringNode, XStringNode, InterpolatedXStringNode, SymbolNode, InterpolatedSymbolNode)]) } def parts; end # Returns the Location represented by `closing_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8338,20 +8338,20 @@ module Prism # ^^^^^^^^^^^^^^^^^ class InterpolatedSymbolNode < Node # Initialize a new InterpolatedSymbolNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8359,17 +8359,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: T.nilable(Location)).returns(InterpolatedSymbolNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: ::T.nilable(Location)).returns(InterpolatedSymbolNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8384,36 +8384,36 @@ module Prism def inspect; end # Returns the Location represented by `opening_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Returns the `parts` attribute. - sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } def parts; end # Returns the Location represented by `closing_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8423,20 +8423,20 @@ module Prism # ^^^^^^^^^^^^^^^^ class InterpolatedXStringNode < Node # Initialize a new InterpolatedXStringNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).void } def initialize(source, node_id, location, flags, opening_loc, parts, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8444,17 +8444,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, parts: T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)], closing_loc: Location).returns(InterpolatedXStringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), parts: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8474,11 +8474,11 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the `parts` attribute. - sig { returns(T::Array[T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } + sig { returns(T::Array[::T.any(StringNode, EmbeddedStatementsNode, EmbeddedVariableNode)]) } def parts; end # Returns the Location represented by `closing_loc`. @@ -8487,7 +8487,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. @@ -8498,7 +8498,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8512,16 +8512,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8529,17 +8529,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItLocalVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8553,7 +8553,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8567,16 +8567,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8584,17 +8584,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(ItParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8608,7 +8608,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8618,20 +8618,20 @@ module Prism # ^^^^ class KeywordHashNode < Node # Initialize a new KeywordHashNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[T.any(AssocNode, AssocSplatNode)]).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, elements: T::Array[::T.any(AssocNode, AssocSplatNode)]).void } def initialize(source, node_id, location, flags, elements); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8639,17 +8639,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, elements: T::Array[::T.any(AssocNode, AssocSplatNode)]).returns(KeywordHashNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), elements: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8668,10 +8668,10 @@ module Prism def symbol_keys?; end # Returns the `elements` attribute. - sig { returns(T::Array[T.any(AssocNode, AssocSplatNode)]) } + sig { returns(T::Array[::T.any(AssocNode, AssocSplatNode)]) } def elements; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8682,20 +8682,20 @@ module Prism # end class KeywordRestParameterNode < Node # Initialize a new KeywordRestParameterNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).void } def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8703,17 +8703,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(KeywordRestParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8732,16 +8732,16 @@ module Prism def repeated_parameter?; end # Returns the `name` attribute. - sig { returns(T.nilable(Symbol)) } + sig { returns(::T.nilable(Symbol)) } def name; end # Returns the Location represented by `name_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def name_loc; end # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -8750,14 +8750,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8767,20 +8767,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^^^^ class LambdaNode < Node # Initialize a new LambdaNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode))).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode))).void } def initialize(source, node_id, location, flags, locals, operator_loc, opening_loc, closing_loc, parameters, body); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8788,17 +8788,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: T.nilable(T.any(StatementsNode, BeginNode))).returns(LambdaNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], operator_loc: Location, opening_loc: Location, closing_loc: Location, parameters: ::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode)), body: ::T.nilable(::T.any(StatementsNode, BeginNode))).returns(LambdaNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), operator_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), parameters: T.unsafe(nil), body: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8822,7 +8822,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the Location represented by `opening_loc`. @@ -8831,7 +8831,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the Location represented by `closing_loc`. @@ -8840,15 +8840,15 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `parameters` attribute. - sig { returns(T.nilable(T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } + sig { returns(::T.nilable(::T.any(BlockParametersNode, NumberedParametersNode, ItParametersNode))) } def parameters; end # Returns the `body` attribute. - sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } def body; end # Slice the location of operator_loc from the source. @@ -8863,7 +8863,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8877,16 +8877,16 @@ module Prism def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8894,17 +8894,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableAndWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -8924,7 +8924,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -8933,7 +8933,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -8952,7 +8952,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -8966,16 +8966,16 @@ module Prism def initialize(source, node_id, location, flags, name_loc, binary_operator_loc, value, name, binary_operator, depth); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -8983,17 +8983,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, binary_operator_loc: Location, value: Node, name: Symbol, binary_operator: Symbol, depth: Integer).returns(LocalVariableOperatorWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), binary_operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), binary_operator: T.unsafe(nil), depth: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9013,7 +9013,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `binary_operator_loc`. @@ -9022,7 +9022,7 @@ module Prism # Save the binary_operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_binary_operator_loc(repository); end # Returns the `value` attribute. @@ -9041,7 +9041,7 @@ module Prism sig { returns(Integer) } def depth; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9055,16 +9055,16 @@ module Prism def initialize(source, node_id, location, flags, name_loc, operator_loc, value, name, depth); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9072,17 +9072,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name_loc: Location, operator_loc: Location, value: Node, name: Symbol, depth: Integer).returns(LocalVariableOrWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9102,7 +9102,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -9111,7 +9111,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -9130,7 +9130,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9144,16 +9144,16 @@ module Prism def initialize(source, node_id, location, flags, name, depth); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9161,17 +9161,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9207,7 +9207,7 @@ module Prism sig { returns(Integer) } def depth; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9224,16 +9224,16 @@ module Prism def initialize(source, node_id, location, flags, name, depth); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9241,17 +9241,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer).returns(LocalVariableTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9273,7 +9273,7 @@ module Prism sig { returns(Integer) } def depth; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9287,16 +9287,16 @@ module Prism def initialize(source, node_id, location, flags, name, depth, name_loc, value, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9304,17 +9304,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, depth: Integer, name_loc: Location, value: Node, operator_loc: Location).returns(LocalVariableWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), depth: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9355,7 +9355,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # The value to write to the local variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -9381,14 +9381,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9402,16 +9402,16 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9419,17 +9419,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(MatchLastLineNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9493,7 +9493,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the Location represented by `content_loc`. @@ -9502,7 +9502,7 @@ module Prism # Save the content_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_content_loc(repository); end # Returns the Location represented by `closing_loc`. @@ -9511,7 +9511,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `unescaped` attribute. @@ -9530,7 +9530,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9544,16 +9544,16 @@ module Prism def initialize(source, node_id, location, flags, value, pattern, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9561,17 +9561,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchPredicateNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9599,14 +9599,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9620,16 +9620,16 @@ module Prism def initialize(source, node_id, location, flags, value, pattern, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9637,17 +9637,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, value: Node, pattern: Node, operator_loc: Location).returns(MatchRequiredNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), value: T.unsafe(nil), pattern: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9723,14 +9723,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9744,16 +9744,16 @@ module Prism def initialize(source, node_id, location, flags, call, targets); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9761,17 +9761,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, call: CallNode, targets: T::Array[LocalVariableTargetNode]).returns(MatchWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), call: T.unsafe(nil), targets: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9793,7 +9793,7 @@ module Prism sig { returns(T::Array[LocalVariableTargetNode]) } def targets; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9804,16 +9804,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9821,17 +9821,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(MissingNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9845,7 +9845,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9855,20 +9855,20 @@ module Prism # ^^^^^^^^^^^^^^ class ModuleNode < Node # Initialize a new ModuleNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).void } def initialize(source, node_id, location, flags, locals, module_keyword_loc, constant_path, body, end_keyword_loc, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9876,17 +9876,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], module_keyword_loc: Location, constant_path: ::T.any(ConstantReadNode, ConstantPathNode, MissingNode), body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location, name: Symbol).returns(ModuleNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), module_keyword_loc: T.unsafe(nil), constant_path: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -9910,15 +9910,15 @@ module Prism # Save the module_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_module_keyword_loc(repository); end # Returns the `constant_path` attribute. - sig { returns(T.any(ConstantReadNode, ConstantPathNode, MissingNode)) } + sig { returns(::T.any(ConstantReadNode, ConstantPathNode, MissingNode)) } def constant_path; end # Returns the `body` attribute. - sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } def body; end # Returns the Location represented by `end_keyword_loc`. @@ -9927,7 +9927,7 @@ module Prism # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_end_keyword_loc(repository); end # Returns the `name` attribute. @@ -9942,7 +9942,7 @@ module Prism sig { returns(String) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -9957,20 +9957,20 @@ module Prism # ^^^^ class MultiTargetNode < Node # Initialize a new MultiTargetNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -9978,17 +9978,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location)).returns(MultiTargetNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location)).returns(MultiTargetNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10011,7 +10011,7 @@ module Prism # # a, (b, c) = 1, 2, 3, 4, 5 # ^^^^ - sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } def lefts; end # Represents a splat node in the target expression. @@ -10028,49 +10028,49 @@ module Prism # # a, (b,) = 1, 2, 3, 4 # ^ - sig { returns(T.nilable(T.any(ImplicitRestNode, SplatNode))) } + sig { returns(::T.nilable(::T.any(ImplicitRestNode, SplatNode))) } def rest; end # Represents the targets expressions after a splat node. # # a, (*, b, c) = 1, 2, 3, 4, 5 # ^^^^ - sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, RequiredParameterNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } def rights; end # The Location of the opening parenthesis. # # a, (b, c) = 1, 2, 3 # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def lparen_loc; end # Save the lparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_lparen_loc(repository); end # The Location of the closing parenthesis. # # a, (b, c) = 1, 2, 3 # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def rparen_loc; end # Save the rparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_rparen_loc(repository); end # Slice the location of lparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def lparen; end # Slice the location of rparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def rparen; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10080,20 +10080,20 @@ module Prism # ^^^^^^^^^^^^^^^^^ class MultiWriteNode < Node # Initialize a new MultiWriteNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), operator_loc: Location, value: Node).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), operator_loc: Location, value: Node).void } def initialize(source, node_id, location, flags, lefts, rest, rights, lparen_loc, rparen_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10101,17 +10101,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: T.nilable(T.any(ImplicitRestNode, SplatNode)), rights: T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: T.nilable(Location), rparen_loc: T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, lefts: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], rest: ::T.nilable(::T.any(ImplicitRestNode, SplatNode)), rights: T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)], lparen_loc: ::T.nilable(Location), rparen_loc: ::T.nilable(Location), operator_loc: Location, value: Node).returns(MultiWriteNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), lefts: T.unsafe(nil), rest: T.unsafe(nil), rights: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10134,7 +10134,7 @@ module Prism # # a, b, c = 1, 2, 3, 4, 5 # ^^^^^^^ - sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } def lefts; end # Represents a splat node in the target expression. @@ -10151,38 +10151,38 @@ module Prism # # a, b, = 1, 2, 3, 4 # ^ - sig { returns(T.nilable(T.any(ImplicitRestNode, SplatNode))) } + sig { returns(::T.nilable(::T.any(ImplicitRestNode, SplatNode))) } def rest; end # Represents the targets expressions after a splat node. # # a, *, b, c = 1, 2, 3, 4, 5 # ^^^^ - sig { returns(T::Array[T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } + sig { returns(T::Array[::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, MultiTargetNode, BackReferenceReadNode, NumberedReferenceReadNode)]) } def rights; end # The Location of the opening parenthesis. # # (a, b, c) = 1, 2, 3 # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def lparen_loc; end # Save the lparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_lparen_loc(repository); end # The Location of the closing parenthesis. # # (a, b, c) = 1, 2, 3 # ^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def rparen_loc; end # Save the rparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_rparen_loc(repository); end # The Location of the operator. @@ -10194,7 +10194,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # The value to write to the targets. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -10205,18 +10205,18 @@ module Prism def value; end # Slice the location of lparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def lparen; end # Slice the location of rparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def rparen; end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10226,20 +10226,20 @@ module Prism # ^^^^^^ class NextNode < Node # Initialize a new NextNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).void } def initialize(source, node_id, location, flags, arguments, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10247,17 +10247,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, arguments: T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, arguments: ::T.nilable(ArgumentsNode), keyword_loc: Location).returns(NextNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), arguments: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10272,7 +10272,7 @@ module Prism def inspect; end # Returns the `arguments` attribute. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Returns the Location represented by `keyword_loc`. @@ -10281,14 +10281,14 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of keyword_loc from the source. sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10302,16 +10302,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10319,17 +10319,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(NilNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10343,7 +10343,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10358,16 +10358,16 @@ module Prism def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10375,17 +10375,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoBlockParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10405,7 +10405,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the Location represented by `keyword_loc`. @@ -10414,7 +10414,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of operator_loc from the source. @@ -10425,7 +10425,7 @@ module Prism sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10440,16 +10440,16 @@ module Prism def initialize(source, node_id, location, flags, operator_loc, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10457,17 +10457,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, keyword_loc: Location).returns(NoKeywordsParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10487,7 +10487,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the Location represented by `keyword_loc`. @@ -10496,7 +10496,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of operator_loc from the source. @@ -10507,7 +10507,7 @@ module Prism sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10521,16 +10521,16 @@ module Prism def initialize(source, node_id, location, flags, maximum); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10538,17 +10538,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, maximum: Integer).returns(NumberedParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), maximum: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10566,7 +10566,7 @@ module Prism sig { returns(Integer) } def maximum; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10580,16 +10580,16 @@ module Prism def initialize(source, node_id, location, flags, number); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10597,17 +10597,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, number: Integer).returns(NumberedReferenceReadNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), number: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10631,7 +10631,7 @@ module Prism sig { returns(Integer) } def number; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10646,16 +10646,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10663,17 +10663,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, value: Node).returns(OptionalKeywordParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10701,14 +10701,14 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the `value` attribute. sig { returns(Node) } def value; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10723,16 +10723,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc, operator_loc, value); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10740,17 +10740,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location, operator_loc: Location, value: Node).returns(OptionalParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), value: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10778,7 +10778,7 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -10787,7 +10787,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `value` attribute. @@ -10798,7 +10798,7 @@ module Prism sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10812,16 +10812,16 @@ module Prism def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10829,17 +10829,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, left: Node, right: Node, operator_loc: Location).returns(OrNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10882,14 +10882,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10900,20 +10900,20 @@ module Prism # end class ParametersNode < Node # Initialize a new ParametersNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: T.nilable(T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, requireds: T::Array[::T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: ::T.nilable(::T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: ::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: ::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))).void } def initialize(source, node_id, location, flags, requireds, optionals, rest, posts, keywords, keyword_rest, block); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -10921,17 +10921,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, requireds: T::Array[T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: T.nilable(T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, requireds: T::Array[::T.any(RequiredParameterNode, MultiTargetNode)], optionals: T::Array[OptionalParameterNode], rest: ::T.nilable(::T.any(RestParameterNode, ImplicitRestNode)), posts: T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)], keywords: T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)], keyword_rest: ::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode)), block: ::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))).returns(ParametersNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), requireds: T.unsafe(nil), optionals: T.unsafe(nil), rest: T.unsafe(nil), posts: T.unsafe(nil), keywords: T.unsafe(nil), keyword_rest: T.unsafe(nil), block: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -10946,7 +10946,7 @@ module Prism def inspect; end # Returns the `requireds` attribute. - sig { returns(T::Array[T.any(RequiredParameterNode, MultiTargetNode)]) } + sig { returns(T::Array[::T.any(RequiredParameterNode, MultiTargetNode)]) } def requireds; end # Returns the `optionals` attribute. @@ -10954,26 +10954,26 @@ module Prism def optionals; end # Returns the `rest` attribute. - sig { returns(T.nilable(T.any(RestParameterNode, ImplicitRestNode))) } + sig { returns(::T.nilable(::T.any(RestParameterNode, ImplicitRestNode))) } def rest; end # Returns the `posts` attribute. - sig { returns(T::Array[T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)]) } + sig { returns(T::Array[::T.any(RequiredParameterNode, MultiTargetNode, KeywordRestParameterNode, NoKeywordsParameterNode, ForwardingParameterNode, BlockParameterNode, NoBlockParameterNode)]) } def posts; end # Returns the `keywords` attribute. - sig { returns(T::Array[T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)]) } + sig { returns(T::Array[::T.any(RequiredKeywordParameterNode, OptionalKeywordParameterNode)]) } def keywords; end # Returns the `keyword_rest` attribute. - sig { returns(T.nilable(T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode))) } + sig { returns(::T.nilable(::T.any(KeywordRestParameterNode, ForwardingParameterNode, NoKeywordsParameterNode))) } def keyword_rest; end # Returns the `block` attribute. - sig { returns(T.nilable(T.any(BlockParameterNode, NoBlockParameterNode))) } + sig { returns(::T.nilable(::T.any(BlockParameterNode, NoBlockParameterNode))) } def block; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -10983,20 +10983,20 @@ module Prism # ^^^^^^^^^ class ParenthesesNode < Node # Initialize a new ParenthesesNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: T.nilable(Node), opening_loc: Location, closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, body: ::T.nilable(Node), opening_loc: Location, closing_loc: Location).void } def initialize(source, node_id, location, flags, body, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11004,17 +11004,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, body: T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, body: ::T.nilable(Node), opening_loc: Location, closing_loc: Location).returns(ParenthesesNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11033,7 +11033,7 @@ module Prism def multiple_statements?; end # Returns the `body` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def body; end # Returns the Location represented by `opening_loc`. @@ -11042,7 +11042,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the Location represented by `closing_loc`. @@ -11051,7 +11051,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of opening_loc from the source. @@ -11062,7 +11062,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11076,16 +11076,16 @@ module Prism def initialize(source, node_id, location, flags, expression, operator_loc, lparen_loc, rparen_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11093,17 +11093,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, operator_loc: Location, lparen_loc: Location, rparen_loc: Location).returns(PinnedExpressionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), operator_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11133,7 +11133,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # The Location of the opening parenthesis. @@ -11145,7 +11145,7 @@ module Prism # Save the lparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_lparen_loc(repository); end # The Location of the closing parenthesis. @@ -11157,7 +11157,7 @@ module Prism # Save the rparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_rparen_loc(repository); end # Slice the location of operator_loc from the source. @@ -11172,7 +11172,7 @@ module Prism sig { returns(String) } def rparen; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11182,20 +11182,20 @@ module Prism # ^^^^ class PinnedVariableNode < Node # Initialize a new PinnedVariableNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, variable: ::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).void } def initialize(source, node_id, location, flags, variable, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11203,17 +11203,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, variable: T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, variable: ::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode), operator_loc: Location).returns(PinnedVariableNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), variable: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11231,7 +11231,7 @@ module Prism # # foo in ^bar # ^^^ - sig { returns(T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode)) } + sig { returns(::T.any(LocalVariableReadNode, InstanceVariableReadNode, ClassVariableReadNode, GlobalVariableReadNode, BackReferenceReadNode, NumberedReferenceReadNode, ItLocalVariableReadNode, MissingNode)) } def variable; end # The Location of the `^` operator @@ -11243,14 +11243,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11260,20 +11260,20 @@ module Prism # ^^^^^^^^^^^ class PostExecutionNode < Node # Initialize a new PostExecutionNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11281,17 +11281,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PostExecutionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11306,7 +11306,7 @@ module Prism def inspect; end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Returns the Location represented by `keyword_loc`. @@ -11315,7 +11315,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the Location represented by `opening_loc`. @@ -11324,7 +11324,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the Location represented by `closing_loc`. @@ -11333,7 +11333,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of keyword_loc from the source. @@ -11348,7 +11348,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11358,20 +11358,20 @@ module Prism # ^^^^^^^^^^^^^ class PreExecutionNode < Node # Initialize a new PreExecutionNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).void } def initialize(source, node_id, location, flags, statements, keyword_loc, opening_loc, closing_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11379,17 +11379,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, statements: T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, statements: ::T.nilable(StatementsNode), keyword_loc: Location, opening_loc: Location, closing_loc: Location).returns(PreExecutionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), statements: T.unsafe(nil), keyword_loc: T.unsafe(nil), opening_loc: T.unsafe(nil), closing_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11404,7 +11404,7 @@ module Prism def inspect; end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Returns the Location represented by `keyword_loc`. @@ -11413,7 +11413,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the Location represented by `opening_loc`. @@ -11422,7 +11422,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the Location represented by `closing_loc`. @@ -11431,7 +11431,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Slice the location of keyword_loc from the source. @@ -11446,7 +11446,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11457,16 +11457,16 @@ module Prism def initialize(source, node_id, location, flags, locals, statements); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11474,17 +11474,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], statements: StatementsNode).returns(ProgramNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), statements: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11506,7 +11506,7 @@ module Prism sig { returns(StatementsNode) } def statements; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11519,20 +11519,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ class RangeNode < Node # Initialize a new RangeNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).void } def initialize(source, node_id, location, flags, left, right, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11540,17 +11540,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, left: T.nilable(Node), right: T.nilable(Node), operator_loc: Location).returns(RangeNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, left: ::T.nilable(Node), right: ::T.nilable(Node), operator_loc: Location).returns(RangeNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11575,7 +11575,7 @@ module Prism # # hello...goodbye # ^^^^^ - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def left; end # The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -11586,7 +11586,7 @@ module Prism # 1...foo # ^^^ # If neither right-hand or left-hand side was included, this will be a MissingNode. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def right; end # The Location of the `..` or `...` operator. @@ -11595,14 +11595,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11616,16 +11616,16 @@ module Prism def initialize(source, node_id, location, flags, numerator, denominator); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11633,17 +11633,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, numerator: Integer, denominator: Integer).returns(RationalNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), numerator: T.unsafe(nil), denominator: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11685,7 +11685,7 @@ module Prism sig { returns(Integer) } def denominator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11699,16 +11699,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11716,17 +11716,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(RedoNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11740,7 +11740,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11754,16 +11754,16 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11771,17 +11771,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(RegularExpressionNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11845,7 +11845,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the Location represented by `content_loc`. @@ -11854,7 +11854,7 @@ module Prism # Save the content_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_content_loc(repository); end # Returns the Location represented by `closing_loc`. @@ -11863,7 +11863,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `unescaped` attribute. @@ -11882,7 +11882,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11897,16 +11897,16 @@ module Prism def initialize(source, node_id, location, flags, name, name_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11914,17 +11914,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol, name_loc: Location).returns(RequiredKeywordParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -11952,10 +11952,10 @@ module Prism # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_name_loc(repository); end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -11970,16 +11970,16 @@ module Prism def initialize(source, node_id, location, flags, name); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -11987,17 +11987,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, name: Symbol).returns(RequiredParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12019,7 +12019,7 @@ module Prism sig { returns(Symbol) } def name; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12033,16 +12033,16 @@ module Prism def initialize(source, node_id, location, flags, expression, keyword_loc, rescue_expression); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12050,17 +12050,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, expression: Node, keyword_loc: Location, rescue_expression: Node).returns(RescueModifierNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), expression: T.unsafe(nil), keyword_loc: T.unsafe(nil), rescue_expression: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12084,7 +12084,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the `rescue_expression` attribute. @@ -12095,7 +12095,7 @@ module Prism sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12110,20 +12110,20 @@ module Prism # `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field. class RescueNode < Node # Initialize a new RescueNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: T.nilable(Location), reference: T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(RescueNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: ::T.nilable(Location), reference: ::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(RescueNode)).void } def initialize(source, node_id, location, flags, keyword_loc, exceptions, operator_loc, reference, then_keyword_loc, statements, subsequent); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12131,17 +12131,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: T.nilable(Location), reference: T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), subsequent: T.nilable(RescueNode)).returns(RescueNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, exceptions: T::Array[Node], operator_loc: ::T.nilable(Location), reference: ::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode)), then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), subsequent: ::T.nilable(RescueNode)).returns(RescueNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), exceptions: T.unsafe(nil), operator_loc: T.unsafe(nil), reference: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), subsequent: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12161,7 +12161,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the `exceptions` attribute. @@ -12169,33 +12169,33 @@ module Prism def exceptions; end # Returns the Location represented by `operator_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def operator_loc; end # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_operator_loc(repository); end # Returns the `reference` attribute. - sig { returns(T.nilable(T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode))) } + sig { returns(::T.nilable(::T.any(LocalVariableTargetNode, InstanceVariableTargetNode, ClassVariableTargetNode, GlobalVariableTargetNode, ConstantTargetNode, ConstantPathTargetNode, CallTargetNode, IndexTargetNode, BackReferenceReadNode, NumberedReferenceReadNode, MissingNode))) } def reference; end # Returns the Location represented by `then_keyword_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def then_keyword_loc; end # Save the then_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_then_keyword_loc(repository); end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Returns the `subsequent` attribute. - sig { returns(T.nilable(RescueNode)) } + sig { returns(::T.nilable(RescueNode)) } def subsequent; end # Slice the location of keyword_loc from the source. @@ -12203,14 +12203,14 @@ module Prism def keyword; end # Slice the location of operator_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def operator; end # Slice the location of then_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def then_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12221,20 +12221,20 @@ module Prism # end class RestParameterNode < Node # Initialize a new RestParameterNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).void } def initialize(source, node_id, location, flags, name, name_loc, operator_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12242,17 +12242,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, name: T.nilable(Symbol), name_loc: T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, name: ::T.nilable(Symbol), name_loc: ::T.nilable(Location), operator_loc: Location).returns(RestParameterNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), name: T.unsafe(nil), name_loc: T.unsafe(nil), operator_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12271,16 +12271,16 @@ module Prism def repeated_parameter?; end # Returns the `name` attribute. - sig { returns(T.nilable(Symbol)) } + sig { returns(::T.nilable(Symbol)) } def name; end # Returns the Location represented by `name_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def name_loc; end # Save the name_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_name_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -12289,14 +12289,14 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12310,16 +12310,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12327,17 +12327,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(RetryNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12351,7 +12351,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12361,20 +12361,20 @@ module Prism # ^^^^^^^^ class ReturnNode < Node # Initialize a new ReturnNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: T.nilable(ArgumentsNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: ::T.nilable(ArgumentsNode)).void } def initialize(source, node_id, location, flags, keyword_loc, arguments); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12382,17 +12382,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: T.nilable(ArgumentsNode)).returns(ReturnNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, arguments: ::T.nilable(ArgumentsNode)).returns(ReturnNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), arguments: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12412,18 +12412,18 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the `arguments` attribute. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Slice the location of keyword_loc from the source. sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12437,16 +12437,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12454,17 +12454,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(SelfNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12478,7 +12478,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12489,20 +12489,20 @@ module Prism # ^^^^^^^^^^^^ class ShareableConstantNode < Node # Initialize a new ShareableConstantNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, write: ::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).void } def initialize(source, node_id, location, flags, write); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12510,17 +12510,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, write: T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, write: ::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)).returns(ShareableConstantNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), write: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12547,10 +12547,10 @@ module Prism def experimental_copy?; end # The constant write that should be modified with the shareability state. - sig { returns(T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)) } + sig { returns(::T.any(ConstantWriteNode, ConstantAndWriteNode, ConstantOrWriteNode, ConstantOperatorWriteNode, ConstantPathWriteNode, ConstantPathAndWriteNode, ConstantPathOrWriteNode, ConstantPathOperatorWriteNode)) } def write; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12560,20 +12560,20 @@ module Prism # ^^^^^^^^^^^^^^^^^ class SingletonClassNode < Node # Initialize a new SingletonClassNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).void } def initialize(source, node_id, location, flags, locals, class_keyword_loc, operator_loc, expression, body, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12581,17 +12581,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: T.nilable(T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, locals: T::Array[Symbol], class_keyword_loc: Location, operator_loc: Location, expression: Node, body: ::T.nilable(::T.any(StatementsNode, BeginNode)), end_keyword_loc: Location).returns(SingletonClassNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), locals: T.unsafe(nil), class_keyword_loc: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil), body: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12615,7 +12615,7 @@ module Prism # Save the class_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_class_keyword_loc(repository); end # Returns the Location represented by `operator_loc`. @@ -12624,7 +12624,7 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `expression` attribute. @@ -12632,7 +12632,7 @@ module Prism def expression; end # Returns the `body` attribute. - sig { returns(T.nilable(T.any(StatementsNode, BeginNode))) } + sig { returns(::T.nilable(::T.any(StatementsNode, BeginNode))) } def body; end # Returns the Location represented by `end_keyword_loc`. @@ -12641,7 +12641,7 @@ module Prism # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_end_keyword_loc(repository); end # Slice the location of class_keyword_loc from the source. @@ -12656,7 +12656,7 @@ module Prism sig { returns(String) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12670,16 +12670,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12687,17 +12687,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceEncodingNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12711,7 +12711,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12725,16 +12725,16 @@ module Prism def initialize(source, node_id, location, flags, filepath); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12742,17 +12742,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, filepath: String).returns(SourceFileNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), filepath: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12786,7 +12786,7 @@ module Prism sig { returns(String) } def filepath; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12800,16 +12800,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12817,17 +12817,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(SourceLineNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12841,7 +12841,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12851,20 +12851,20 @@ module Prism # ^^ class SplatNode < Node # Initialize a new SplatNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: T.nilable(Node)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: ::T.nilable(Node)).void } def initialize(source, node_id, location, flags, operator_loc, expression); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12872,17 +12872,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: T.nilable(Node)).returns(SplatNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, operator_loc: Location, expression: ::T.nilable(Node)).returns(SplatNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), operator_loc: T.unsafe(nil), expression: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12902,18 +12902,18 @@ module Prism # Save the operator_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_operator_loc(repository); end # Returns the `expression` attribute. - sig { returns(T.nilable(Node)) } + sig { returns(::T.nilable(Node)) } def expression; end # Slice the location of operator_loc from the source. sig { returns(String) } def operator; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12927,16 +12927,16 @@ module Prism def initialize(source, node_id, location, flags, body); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -12944,17 +12944,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, body: T::Array[Node]).returns(StatementsNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), body: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -12972,7 +12972,7 @@ module Prism sig { returns(T::Array[Node]) } def body; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -12988,20 +12988,20 @@ module Prism # ^^^^ ^^^^ class StringNode < Node # Initialize a new StringNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), content_loc: Location, closing_loc: T.nilable(Location), unescaped: String).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), content_loc: Location, closing_loc: ::T.nilable(Location), unescaped: String).void } def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13009,17 +13009,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), content_loc: Location, closing_loc: T.nilable(Location), unescaped: String).returns(StringNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), content_loc: Location, closing_loc: ::T.nilable(Location), unescaped: String).returns(StringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13050,12 +13050,12 @@ module Prism def mutable?; end # Returns the Location represented by `opening_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Returns the Location represented by `content_loc`. @@ -13064,16 +13064,16 @@ module Prism # Save the content_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_content_loc(repository); end # Returns the Location represented by `closing_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Returns the `unescaped` attribute. @@ -13081,7 +13081,7 @@ module Prism def unescaped; end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of content_loc from the source. @@ -13089,10 +13089,10 @@ module Prism def content; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13107,20 +13107,20 @@ module Prism # If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead. class SuperNode < Node # Initialize a new SuperNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).void } def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc, block); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13128,17 +13128,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location), block: T.nilable(T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location), block: ::T.nilable(::T.any(BlockNode, BlockArgumentNode))).returns(SuperNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil), block: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13158,33 +13158,33 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the Location represented by `lparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def lparen_loc; end # Save the lparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_lparen_loc(repository); end # Can be only `nil` when there are empty parentheses, like `super()`. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Returns the Location represented by `rparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def rparen_loc; end # Save the rparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_rparen_loc(repository); end # Returns the `block` attribute. - sig { returns(T.nilable(T.any(BlockNode, BlockArgumentNode))) } + sig { returns(::T.nilable(::T.any(BlockNode, BlockArgumentNode))) } def block; end # Slice the location of keyword_loc from the source. @@ -13192,14 +13192,14 @@ module Prism def keyword; end # Slice the location of lparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def lparen; end # Slice the location of rparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def rparen; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13212,20 +13212,20 @@ module Prism # ^^^ class SymbolNode < Node # Initialize a new SymbolNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), value_loc: T.nilable(Location), closing_loc: T.nilable(Location), unescaped: String).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), value_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), unescaped: String).void } def initialize(source, node_id, location, flags, opening_loc, value_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13233,17 +13233,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: T.nilable(Location), value_loc: T.nilable(Location), closing_loc: T.nilable(Location), unescaped: String).returns(SymbolNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: ::T.nilable(Location), value_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), unescaped: String).returns(SymbolNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), value_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13270,30 +13270,30 @@ module Prism def forced_us_ascii_encoding?; end # Returns the Location represented by `opening_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def opening_loc; end # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_opening_loc(repository); end # Returns the Location represented by `value_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def value_loc; end # Save the value_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_value_loc(repository); end # Returns the Location represented by `closing_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Returns the `unescaped` attribute. @@ -13301,18 +13301,18 @@ module Prism def unescaped; end # Slice the location of opening_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def opening; end # Slice the location of value_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def value; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13326,16 +13326,16 @@ module Prism def initialize(source, node_id, location, flags); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13343,17 +13343,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer).returns(TrueNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13367,7 +13367,7 @@ module Prism sig { override.returns(String) } def inspect; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13377,20 +13377,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^^^ class UndefNode < Node # Initialize a new UndefNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, names: T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).void } def initialize(source, node_id, location, flags, names, keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13398,17 +13398,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, names: T::Array[T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, names: T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)], keyword_loc: Location).returns(UndefNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), names: T.unsafe(nil), keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13423,7 +13423,7 @@ module Prism def inspect; end # Returns the `names` attribute. - sig { returns(T::Array[T.any(SymbolNode, InterpolatedSymbolNode)]) } + sig { returns(T::Array[::T.any(SymbolNode, InterpolatedSymbolNode)]) } def names; end # Returns the Location represented by `keyword_loc`. @@ -13432,14 +13432,14 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Slice the location of keyword_loc from the source. sig { returns(String) } def keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13452,20 +13452,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^^^^ class UnlessNode < Node # Initialize a new UnlessNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), else_clause: T.nilable(ElseNode), end_keyword_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), else_clause: ::T.nilable(ElseNode), end_keyword_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, keyword_loc, predicate, then_keyword_loc, statements, else_clause, end_keyword_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13473,17 +13473,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode), else_clause: T.nilable(ElseNode), end_keyword_loc: T.nilable(Location)).returns(UnlessNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, predicate: Node, then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode), else_clause: ::T.nilable(ElseNode), end_keyword_loc: ::T.nilable(Location)).returns(UnlessNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), predicate: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil), else_clause: T.unsafe(nil), end_keyword_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13509,7 +13509,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # The condition to be evaluated for the unless expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). @@ -13526,12 +13526,12 @@ module Prism # # unless cond then bar end # ^^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def then_keyword_loc; end # Save the then_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_then_keyword_loc(repository); end # The body of statements that will executed if the unless condition is @@ -13539,26 +13539,26 @@ module Prism # # unless cond then bar end # ^^^ - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # The else clause of the unless expression, if present. # # unless cond then bar else baz end # ^^^^^^^^^^^^ - sig { returns(T.nilable(ElseNode)) } + sig { returns(::T.nilable(ElseNode)) } def else_clause; end # The Location of the `end` keyword, if present. # # unless cond then bar end # ^^^ - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def end_keyword_loc; end # Save the end_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_end_keyword_loc(repository); end # Slice the location of keyword_loc from the source. @@ -13566,14 +13566,14 @@ module Prism def keyword; end # Slice the location of then_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def then_keyword; end # Slice the location of end_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def end_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13586,20 +13586,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^ class UntilNode < Node # Initialize a new UntilNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).void } def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13607,17 +13607,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(UntilNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(UntilNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13641,25 +13641,25 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the Location represented by `do_keyword_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def do_keyword_loc; end # Save the do_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_do_keyword_loc(repository); end # Returns the Location represented by `closing_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Returns the `predicate` attribute. @@ -13667,7 +13667,7 @@ module Prism def predicate; end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Slice the location of keyword_loc from the source. @@ -13675,14 +13675,14 @@ module Prism def keyword; end # Slice the location of do_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def do_keyword; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13694,20 +13694,20 @@ module Prism # end class WhenNode < Node # Initialize a new WhenNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode)).void } def initialize(source, node_id, location, flags, keyword_loc, conditions, then_keyword_loc, statements); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13715,17 +13715,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: T.nilable(Location), statements: T.nilable(StatementsNode)).returns(WhenNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, conditions: T::Array[Node], then_keyword_loc: ::T.nilable(Location), statements: ::T.nilable(StatementsNode)).returns(WhenNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), conditions: T.unsafe(nil), then_keyword_loc: T.unsafe(nil), statements: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13745,7 +13745,7 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the `conditions` attribute. @@ -13753,16 +13753,16 @@ module Prism def conditions; end # Returns the Location represented by `then_keyword_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def then_keyword_loc; end # Save the then_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_then_keyword_loc(repository); end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Slice the location of keyword_loc from the source. @@ -13770,10 +13770,10 @@ module Prism def keyword; end # Slice the location of then_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def then_keyword; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13786,20 +13786,20 @@ module Prism # ^^^^^^^^^^^^^^^^^^^^ class WhileNode < Node # Initialize a new WhileNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).void } def initialize(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13807,17 +13807,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: T.nilable(Location), closing_loc: T.nilable(Location), predicate: Node, statements: T.nilable(StatementsNode)).returns(WhileNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, do_keyword_loc: ::T.nilable(Location), closing_loc: ::T.nilable(Location), predicate: Node, statements: ::T.nilable(StatementsNode)).returns(WhileNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), do_keyword_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), predicate: T.unsafe(nil), statements: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13841,25 +13841,25 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the Location represented by `do_keyword_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def do_keyword_loc; end # Save the do_keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_do_keyword_loc(repository); end # Returns the Location represented by `closing_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def closing_loc; end # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_closing_loc(repository); end # Returns the `predicate` attribute. @@ -13867,7 +13867,7 @@ module Prism def predicate; end # Returns the `statements` attribute. - sig { returns(T.nilable(StatementsNode)) } + sig { returns(::T.nilable(StatementsNode)) } def statements; end # Slice the location of keyword_loc from the source. @@ -13875,14 +13875,14 @@ module Prism def keyword; end # Slice the location of do_keyword_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def do_keyword; end # Slice the location of closing_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13896,16 +13896,16 @@ module Prism def initialize(source, node_id, location, flags, opening_loc, content_loc, closing_loc, unescaped); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -13913,17 +13913,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. sig { params(node_id: Integer, location: Location, flags: Integer, opening_loc: Location, content_loc: Location, closing_loc: Location, unescaped: String).returns(XStringNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), opening_loc: T.unsafe(nil), content_loc: T.unsafe(nil), closing_loc: T.unsafe(nil), unescaped: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -13951,7 +13951,7 @@ module Prism # Save the opening_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_opening_loc(repository); end # Returns the Location represented by `content_loc`. @@ -13960,7 +13960,7 @@ module Prism # Save the content_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_content_loc(repository); end # Returns the Location represented by `closing_loc`. @@ -13969,7 +13969,7 @@ module Prism # Save the closing_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_closing_loc(repository); end # Returns the `unescaped` attribute. @@ -13988,7 +13988,7 @@ module Prism sig { returns(String) } def closing; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end @@ -13998,20 +13998,20 @@ module Prism # ^^^^^^^ class YieldNode < Node # Initialize a new YieldNode node. - sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location)).void } + sig { params(source: Source, node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location)).void } def initialize(source, node_id, location, flags, keyword_loc, lparen_loc, arguments, rparen_loc); end # See Node.accept. - sig { override.params(visitor: Visitor).returns(T.untyped) } + sig { override.params(visitor: Visitor).returns(::T.untyped) } def accept(visitor); end # See Node.child_nodes. - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def child_nodes; end # See Node.each_child_node. sig { override.returns(T::Enumerator[Node]) } - sig { override.params(blk: T.proc.params(arg0: Node).void).void } + sig { override.params(blk: ::T.proc.params(arg0: Node).void).void } def each_child_node(&blk); end # See Node.compact_child_nodes. @@ -14019,17 +14019,17 @@ module Prism def compact_child_nodes; end # See Node.comment_targets. - sig { override.returns(T::Array[T.any(Node, Location)]) } + sig { override.returns(T::Array[::T.any(Node, Location)]) } def comment_targets; end # Creates a copy of self with the given fields, using self as the template. - sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: T.nilable(Location), arguments: T.nilable(ArgumentsNode), rparen_loc: T.nilable(Location)).returns(YieldNode) } + sig { params(node_id: Integer, location: Location, flags: Integer, keyword_loc: Location, lparen_loc: ::T.nilable(Location), arguments: ::T.nilable(ArgumentsNode), rparen_loc: ::T.nilable(Location)).returns(YieldNode) } def copy(node_id: T.unsafe(nil), location: T.unsafe(nil), flags: T.unsafe(nil), keyword_loc: T.unsafe(nil), lparen_loc: T.unsafe(nil), arguments: T.unsafe(nil), rparen_loc: T.unsafe(nil)); end - sig { override.returns(T::Array[T.nilable(Node)]) } + sig { override.returns(T::Array[::T.nilable(Node)]) } def deconstruct; end - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # See `Node#type`. @@ -14049,29 +14049,29 @@ module Prism # Save the keyword_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(Relocation::Entry) } + sig { params(repository: ::T.untyped).returns(Relocation::Entry) } def save_keyword_loc(repository); end # Returns the Location represented by `lparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def lparen_loc; end # Save the lparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_lparen_loc(repository); end # Returns the `arguments` attribute. - sig { returns(T.nilable(ArgumentsNode)) } + sig { returns(::T.nilable(ArgumentsNode)) } def arguments; end # Returns the Location represented by `rparen_loc`. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def rparen_loc; end # Save the rparen_loc location using the given saved source so that # it can be retrieved later. - sig { params(repository: T.untyped).returns(T.nilable(Relocation::Entry)) } + sig { params(repository: ::T.untyped).returns(::T.nilable(Relocation::Entry)) } def save_rparen_loc(repository); end # Slice the location of keyword_loc from the source. @@ -14079,192 +14079,192 @@ module Prism def keyword; end # Slice the location of lparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def lparen; end # Slice the location of rparen_loc from the source. - sig { returns(T.nilable(String)) } + sig { returns(::T.nilable(String)) } def rparen; end - sig { params(other: T.untyped).returns(T.nilable(T::Boolean)) } + sig { params(other: ::T.untyped).returns(::T.nilable(T::Boolean)) } def ===(other); end end # Flags for arguments nodes. module ArgumentsNodeFlags # if the arguments contain forwarding - CONTAINS_FORWARDING = T.let(nil, T.untyped) + CONTAINS_FORWARDING = T.let(nil, ::T.untyped) # if the arguments contain keywords - CONTAINS_KEYWORDS = T.let(nil, T.untyped) + CONTAINS_KEYWORDS = T.let(nil, ::T.untyped) # if the arguments contain a keyword splat - CONTAINS_KEYWORD_SPLAT = T.let(nil, T.untyped) + CONTAINS_KEYWORD_SPLAT = T.let(nil, ::T.untyped) # if the arguments contain a splat - CONTAINS_SPLAT = T.let(nil, T.untyped) + CONTAINS_SPLAT = T.let(nil, ::T.untyped) # if the arguments contain multiple splats - CONTAINS_MULTIPLE_SPLATS = T.let(nil, T.untyped) + CONTAINS_MULTIPLE_SPLATS = T.let(nil, ::T.untyped) end # Flags for array nodes. module ArrayNodeFlags # if array contains splat nodes - CONTAINS_SPLAT = T.let(nil, T.untyped) + CONTAINS_SPLAT = T.let(nil, ::T.untyped) end # Flags for call nodes. module CallNodeFlags # &. operator - SAFE_NAVIGATION = T.let(nil, T.untyped) + SAFE_NAVIGATION = T.let(nil, ::T.untyped) # a call that could have been a local variable - VARIABLE_CALL = T.let(nil, T.untyped) + VARIABLE_CALL = T.let(nil, ::T.untyped) # a call that is an attribute write, so the value being written should be returned - ATTRIBUTE_WRITE = T.let(nil, T.untyped) + ATTRIBUTE_WRITE = T.let(nil, ::T.untyped) # a call that ignores method visibility - IGNORE_VISIBILITY = T.let(nil, T.untyped) + IGNORE_VISIBILITY = T.let(nil, ::T.untyped) end # Flags for nodes that have unescaped content. module EncodingFlags # internal bytes forced the encoding to UTF-8 - FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) # internal bytes forced the encoding to binary - FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) end # Flags for integer nodes that correspond to the base of the integer. module IntegerBaseFlags # 0b prefix - BINARY = T.let(nil, T.untyped) + BINARY = T.let(nil, ::T.untyped) # 0d or no prefix - DECIMAL = T.let(nil, T.untyped) + DECIMAL = T.let(nil, ::T.untyped) # 0o or 0 prefix - OCTAL = T.let(nil, T.untyped) + OCTAL = T.let(nil, ::T.untyped) # 0x prefix - HEXADECIMAL = T.let(nil, T.untyped) + HEXADECIMAL = T.let(nil, ::T.untyped) end # Flags for interpolated string nodes that indicated mutability if they are also marked as literals. module InterpolatedStringNodeFlags # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` - FROZEN = T.let(nil, T.untyped) + FROZEN = T.let(nil, ::T.untyped) # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` - MUTABLE = T.let(nil, T.untyped) + MUTABLE = T.let(nil, ::T.untyped) end # Flags for keyword hash nodes. module KeywordHashNodeFlags # a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments - SYMBOL_KEYS = T.let(nil, T.untyped) + SYMBOL_KEYS = T.let(nil, ::T.untyped) end # Flags for while and until loop nodes. module LoopFlags # a loop after a begin statement, so the body is executed first before the condition - BEGIN_MODIFIER = T.let(nil, T.untyped) + BEGIN_MODIFIER = T.let(nil, ::T.untyped) end # Flags for parameter nodes. module ParameterFlags # a parameter name that has been repeated in the method signature - REPEATED_PARAMETER = T.let(nil, T.untyped) + REPEATED_PARAMETER = T.let(nil, ::T.untyped) end # Flags for parentheses nodes. module ParenthesesNodeFlags # parentheses that contain multiple potentially void statements - MULTIPLE_STATEMENTS = T.let(nil, T.untyped) + MULTIPLE_STATEMENTS = T.let(nil, ::T.untyped) end # Flags for range and flip-flop nodes. module RangeFlags # ... operator - EXCLUDE_END = T.let(nil, T.untyped) + EXCLUDE_END = T.let(nil, ::T.untyped) end # Flags for regular expression and match last line nodes. module RegularExpressionFlags # i - ignores the case of characters when matching - IGNORE_CASE = T.let(nil, T.untyped) + IGNORE_CASE = T.let(nil, ::T.untyped) # x - ignores whitespace and allows comments in regular expressions - EXTENDED = T.let(nil, T.untyped) + EXTENDED = T.let(nil, ::T.untyped) # m - allows $ to match the end of lines within strings - MULTI_LINE = T.let(nil, T.untyped) + MULTI_LINE = T.let(nil, ::T.untyped) # o - only interpolates values into the regular expression once - ONCE = T.let(nil, T.untyped) + ONCE = T.let(nil, ::T.untyped) # e - forces the EUC-JP encoding - EUC_JP = T.let(nil, T.untyped) + EUC_JP = T.let(nil, ::T.untyped) # n - forces the ASCII-8BIT encoding - ASCII_8BIT = T.let(nil, T.untyped) + ASCII_8BIT = T.let(nil, ::T.untyped) # s - forces the Windows-31J encoding - WINDOWS_31J = T.let(nil, T.untyped) + WINDOWS_31J = T.let(nil, ::T.untyped) # u - forces the UTF-8 encoding - UTF_8 = T.let(nil, T.untyped) + UTF_8 = T.let(nil, ::T.untyped) # internal bytes forced the encoding to UTF-8 - FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) # internal bytes forced the encoding to binary - FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) # internal bytes forced the encoding to US-ASCII - FORCED_US_ASCII_ENCODING = T.let(nil, T.untyped) + FORCED_US_ASCII_ENCODING = T.let(nil, ::T.untyped) end # Flags for shareable constant nodes. module ShareableConstantNodeFlags # constant writes that should be modified with shareable constant value literal - LITERAL = T.let(nil, T.untyped) + LITERAL = T.let(nil, ::T.untyped) # constant writes that should be modified with shareable constant value experimental everything - EXPERIMENTAL_EVERYTHING = T.let(nil, T.untyped) + EXPERIMENTAL_EVERYTHING = T.let(nil, ::T.untyped) # constant writes that should be modified with shareable constant value experimental copy - EXPERIMENTAL_COPY = T.let(nil, T.untyped) + EXPERIMENTAL_COPY = T.let(nil, ::T.untyped) end # Flags for string nodes. module StringFlags # internal bytes forced the encoding to UTF-8 - FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) # internal bytes forced the encoding to binary - FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) # frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` - FROZEN = T.let(nil, T.untyped) + FROZEN = T.let(nil, ::T.untyped) # mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` - MUTABLE = T.let(nil, T.untyped) + MUTABLE = T.let(nil, ::T.untyped) end # Flags for symbol nodes. module SymbolFlags # internal bytes forced the encoding to UTF-8 - FORCED_UTF8_ENCODING = T.let(nil, T.untyped) + FORCED_UTF8_ENCODING = T.let(nil, ::T.untyped) # internal bytes forced the encoding to binary - FORCED_BINARY_ENCODING = T.let(nil, T.untyped) + FORCED_BINARY_ENCODING = T.let(nil, ::T.untyped) # internal bytes forced the encoding to US-ASCII - FORCED_US_ASCII_ENCODING = T.let(nil, T.untyped) + FORCED_US_ASCII_ENCODING = T.let(nil, ::T.untyped) end # The flags that are common to all nodes. diff --git a/rbi/generated/prism/node_ext.rbi b/rbi/generated/prism/node_ext.rbi index 925fd8dd7a..25255d073b 100644 --- a/rbi/generated/prism/node_ext.rbi +++ b/rbi/generated/prism/node_ext.rbi @@ -45,25 +45,25 @@ module Prism module HeredocQuery # Returns true if this node was represented as a heredoc in the source code. - sig { params(opening: T.nilable(String)).returns(T.nilable(T::Boolean)) } + sig { params(opening: ::T.nilable(String)).returns(::T.nilable(T::Boolean)) } def self.heredoc?(opening); end end class InterpolatedStringNode < Node # Returns true if this node was represented as a heredoc in the source code. - sig { returns(T.nilable(T::Boolean)) } + sig { returns(::T.nilable(T::Boolean)) } def heredoc?; end end class InterpolatedXStringNode < Node # Returns true if this node was represented as a heredoc in the source code. - sig { returns(T.nilable(T::Boolean)) } + sig { returns(::T.nilable(T::Boolean)) } def heredoc?; end end class StringNode < Node # Returns true if this node was represented as a heredoc in the source code. - sig { returns(T.nilable(T::Boolean)) } + sig { returns(::T.nilable(T::Boolean)) } def heredoc?; end # Occasionally it's helpful to treat a string as if it were interpolated so @@ -74,7 +74,7 @@ module Prism class XStringNode < Node # Returns true if this node was represented as a heredoc in the source code. - sig { returns(T.nilable(T::Boolean)) } + sig { returns(::T.nilable(T::Boolean)) } def heredoc?; end # Occasionally it's helpful to treat a string as if it were interpolated so @@ -96,7 +96,7 @@ module Prism # Returns the value of the node as an IntegerNode or a FloatNode. This # method is deprecated in favor of #value or #numerator/#denominator. - sig { returns(T.any(IntegerNode, FloatNode)) } + sig { returns(::T.any(IntegerNode, FloatNode)) } def numeric; end end @@ -148,7 +148,7 @@ module Prism # Previously, we had a child node on this class that contained either a # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. - sig { returns(T.any(ConstantReadNode, MissingNode)) } + sig { returns(::T.any(ConstantReadNode, MissingNode)) } def child; end end @@ -165,7 +165,7 @@ module Prism # Previously, we had a child node on this class that contained either a # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. - sig { returns(T.any(ConstantReadNode, MissingNode)) } + sig { returns(::T.any(ConstantReadNode, MissingNode)) } def child; end end @@ -182,7 +182,7 @@ module Prism class ParametersNode < Node # Mirrors the Method#parameters method. - sig { returns(T::Array[T.any([Symbol, Symbol], [Symbol])]) } + sig { returns(T::Array[::T.any([Symbol, Symbol], [Symbol])]) } def signature; end end @@ -196,7 +196,7 @@ module Prism # can be any amount of space between the message and the = sign. However, # sometimes you want the location of the full message including the inner # space and the = sign. This method provides that. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } def full_message_loc; end end @@ -299,35 +299,35 @@ module Prism class CaseMatchNode < Node # Returns the else clause of the case match node. This method is deprecated # in favor of #else_clause. - sig { returns(T.nilable(ElseNode)) } + sig { returns(::T.nilable(ElseNode)) } def consequent; end end class CaseNode < Node # Returns the else clause of the case node. This method is deprecated in # favor of #else_clause. - sig { returns(T.nilable(ElseNode)) } + sig { returns(::T.nilable(ElseNode)) } def consequent; end end class IfNode < Node # Returns the subsequent if/elsif/else clause of the if node. This method is # deprecated in favor of #subsequent. - sig { returns(T.nilable(T.any(IfNode, ElseNode))) } + sig { returns(::T.nilable(::T.any(IfNode, ElseNode))) } def consequent; end end class RescueNode < Node # Returns the subsequent rescue clause of the rescue node. This method is # deprecated in favor of #subsequent. - sig { returns(T.nilable(RescueNode)) } + sig { returns(::T.nilable(RescueNode)) } def consequent; end end class UnlessNode < Node # Returns the else clause of the unless node. This method is deprecated in # favor of #else_clause. - sig { returns(T.nilable(ElseNode)) } + sig { returns(::T.nilable(ElseNode)) } def consequent; end end end diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi index 51297530c3..4a904e85e1 100644 --- a/rbi/generated/prism/parse_result.rbi +++ b/rbi/generated/prism/parse_result.rbi @@ -192,7 +192,7 @@ module Prism # Returns a cache that is the identity function in order to maintain the # same interface. We can do this because code units are always equivalent to # byte offsets for ASCII-only sources. - sig { params(encoding: Encoding).returns(T.untyped) } + sig { params(encoding: Encoding).returns(::T.untyped) } def code_units_cache(encoding); end # Specialized version of `code_units_column` that does not depend on @@ -283,7 +283,7 @@ module Prism # The start offset from the start of the file in code units using the given # cache to fetch or calculate the value. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_start_code_units_offset(cache); end # The byte offset from the beginning of the source where this location ends. @@ -301,7 +301,7 @@ module Prism # The end offset from the start of the file in code units using the given # cache to fetch or calculate the value. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_end_code_units_offset(cache); end # The line number where this location starts. @@ -333,7 +333,7 @@ module Prism # The start column in code units using the given cache to fetch or calculate # the value. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_start_code_units_column(cache); end # The column in bytes where this location ends from the start of the @@ -353,11 +353,11 @@ module Prism # The end column in code units using the given cache to fetch or calculate # the value. - sig { params(cache: T.untyped).returns(Integer) } + sig { params(cache: ::T.untyped).returns(Integer) } def cached_end_code_units_column(cache); end # Implement the hash pattern matching interface for Location. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # Implement the pretty print interface for Location. @@ -365,7 +365,7 @@ module Prism def pretty_print(q); end # Returns true if the given other location is equal to this location. - sig { params(other: T.untyped).returns(T::Boolean) } + sig { params(other: ::T.untyped).returns(T::Boolean) } def ==(other); end # Returns a new location that stretches from this location to the given @@ -393,7 +393,7 @@ module Prism def initialize(location); end # Implement the hash pattern matching interface for Comment. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # Returns the content of the comment by slicing it from the source code. @@ -455,7 +455,7 @@ module Prism def value; end # Implement the hash pattern matching interface for MagicComment. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # Returns a string representation of this magic comment. @@ -487,7 +487,7 @@ module Prism def initialize(type, message, location, level); end # Implement the hash pattern matching interface for ParseError. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # Returns a string representation of this error. @@ -519,7 +519,7 @@ module Prism def initialize(type, message, location, level); end # Implement the hash pattern matching interface for ParseWarning. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # Returns a string representation of this warning. @@ -542,7 +542,7 @@ module Prism # An optional location that represents the location of the __END__ marker # and the rest of the content of the file. This content is loaded into the # DATA constant when the file being parsed is the main file being executed. - sig { returns(T.nilable(Location)) } + sig { returns(::T.nilable(Location)) } attr_reader :data_loc # The list of errors that were generated during parsing. @@ -558,11 +558,11 @@ module Prism attr_reader :source # Create a new result object with the given values. - sig { params(comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + sig { params(comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } def initialize(comments, magic_comments, data_loc, errors, warnings, source); end # Implement the hash pattern matching interface for Result. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # Returns the encoding of the source code that was parsed. @@ -606,10 +606,10 @@ module Prism # token of an unclosed construct rather than at the end of the source. These # errors always indicate incomplete input regardless of their byte position, # so they are checked by type rather than by location. - CONTINUABLE = T.let(nil, T.untyped) + CONTINUABLE = T.let(nil, ::T.untyped) # Create a code units cache for the given encoding. - sig { params(encoding: Encoding).returns(T.untyped) } + sig { params(encoding: Encoding).returns(::T.untyped) } def code_units_cache(encoding); end end @@ -620,11 +620,11 @@ module Prism attr_reader :value # Create a new parse result object with the given values. - sig { params(value: ProgramNode, comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + sig { params(value: ProgramNode, comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end # Implement the hash pattern matching interface for ParseResult. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # Attach the list of comments to their respective locations in the tree. @@ -649,11 +649,11 @@ module Prism attr_reader :value # Create a new lex result object with the given values. - sig { params(value: T::Array[[Token, Integer]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + sig { params(value: T::Array[[Token, Integer]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end # Implement the hash pattern matching interface for LexResult. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end end @@ -665,11 +665,11 @@ module Prism attr_reader :value # Create a new parse lex result object with the given values. - sig { params(value: [ProgramNode, T::Array[[Token, Integer]]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } + sig { params(value: [ProgramNode, T::Array[[Token, Integer]]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end # Implement the hash pattern matching interface for ParseLexResult. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end end @@ -688,11 +688,11 @@ module Prism attr_reader :value # Create a new token object with the given type, value, and location. - sig { params(source: Source, type: Symbol, value: String, location: T.any(Location, Integer)).void } + sig { params(source: Source, type: Symbol, value: String, location: ::T.any(Location, Integer)).void } def initialize(source, type, value, location); end # Implement the hash pattern matching interface for Token. - sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) } + sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } def deconstruct_keys(keys); end # A Location object representing the location of this token in the source. @@ -704,7 +704,7 @@ module Prism def pretty_print(q); end # Returns true if the given other token is equal to this token. - sig { params(other: T.untyped).returns(T::Boolean) } + sig { params(other: ::T.untyped).returns(T::Boolean) } def ==(other); end # Returns a string representation of this token. diff --git a/rbi/generated/prism/parse_result/comments.rbi b/rbi/generated/prism/parse_result/comments.rbi index 4220d23d9d..f386d03f34 100644 --- a/rbi/generated/prism/parse_result/comments.rbi +++ b/rbi/generated/prism/parse_result/comments.rbi @@ -83,7 +83,7 @@ module Prism # Responsible for finding the nearest targets to the given comment within # the context of the given encapsulating node. - sig { params(node: Node, comment: Comment).returns([T.untyped, T.untyped, T.untyped]) } + sig { params(node: Node, comment: Comment).returns([::T.untyped, ::T.untyped, ::T.untyped]) } private def nearest_targets(node, comment); end end end diff --git a/rbi/generated/prism/pattern.rbi b/rbi/generated/prism/pattern.rbi index cc74c54d5e..375518b8f7 100644 --- a/rbi/generated/prism/pattern.rbi +++ b/rbi/generated/prism/pattern.rbi @@ -63,7 +63,7 @@ module Prism # matches the pattern. If no block is given, an enumerator will be returned # that will yield each node that matches the pattern. sig { params(root: Node).returns(T::Enumerator[Node]) } - sig { params(root: Node, blk: T.proc.params(arg0: Node).void).void } + sig { params(root: Node, blk: ::T.proc.params(arg0: Node).void).void } def scan(root, &blk); end # Shortcut for combining two procs into one that returns true if both return @@ -79,7 +79,7 @@ module Prism # Raise an error because the given node is not supported. Note purposefully # not typing this method since it is a no return method that Steep does not # understand. - sig { params(node: Node).returns(T.noreturn) } + sig { params(node: Node).returns(::T.noreturn) } private def compile_error(node); end # in [foo, bar, baz] @@ -100,7 +100,7 @@ module Prism private def compile_constant_read_node(node); end # Compile a name associated with a constant. - sig { params(node: T.any(ConstantPathNode, ConstantReadNode), name: Symbol).returns(Proc) } + sig { params(node: ::T.any(ConstantPathNode, ConstantReadNode), name: Symbol).returns(Proc) } private def compile_constant_name(node, name); end # in InstanceVariableReadNode[name: Symbol] diff --git a/rbi/generated/prism/reflection.rbi b/rbi/generated/prism/reflection.rbi index 7a4cd1bb43..1094c461f4 100644 --- a/rbi/generated/prism/reflection.rbi +++ b/rbi/generated/prism/reflection.rbi @@ -83,7 +83,7 @@ module Prism end # Returns the fields for the given node. - sig { params(node: T.class_of(Node)).returns(T::Array[Field]) } + sig { params(node: ::T.class_of(Node)).returns(T::Array[Field]) } def self.fields_for(node); end end end diff --git a/rbi/generated/prism/relocation.rbi b/rbi/generated/prism/relocation.rbi index e1c0a5bd40..7868d065b0 100644 --- a/rbi/generated/prism/relocation.rbi +++ b/rbi/generated/prism/relocation.rbi @@ -102,26 +102,26 @@ module Prism # Reify the values on this entry with the given values. This is an # internal-only API that is called from the repository when it is time to # reify the values. - sig { params(values: T::Hash[Symbol, T.untyped]).void } + sig { params(values: T::Hash[Symbol, ::T.untyped]).void } def reify!(values); end # Fetch a value from the entry, raising an error if it is missing. - sig { params(name: Symbol).returns(T.untyped) } + sig { params(name: Symbol).returns(::T.untyped) } private def fetch_value(name); end # Return the values from the repository, reifying them if necessary. - sig { returns(T::Hash[Symbol, T.untyped]) } + sig { returns(T::Hash[Symbol, ::T.untyped]) } private def values; end end # Represents the source of a repository that will be reparsed. class Source # The value that will need to be reparsed. - sig { returns(T.untyped) } + sig { returns(::T.untyped) } attr_reader :value # Initialize the source with the given value. - sig { params(value: T.untyped).void } + sig { params(value: ::T.untyped).void } def initialize(value); end # Reparse the value and return the parse result. @@ -129,7 +129,7 @@ module Prism def result; end # Create a code units cache for the given encoding. - sig { params(encoding: Encoding).returns(T.untyped) } + sig { params(encoding: Encoding).returns(::T.untyped) } def code_units_cache(encoding); end end @@ -158,28 +158,28 @@ module Prism def initialize(value); end # Fetch the file path. - sig { params(_value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(_value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(_value); end end # A field representing the start and end lines. class LinesField # Fetches the start and end line of a value. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end end # A field representing the start and end byte offsets. class OffsetsField # Fetches the start and end byte offset of a value. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end end # A field representing the start and end character offsets. class CharacterOffsetsField # Fetches the start and end character offset of a value. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end end @@ -200,25 +200,25 @@ module Prism # Fetches the start and end code units offset of a value for a particular # encoding. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end # Lazily create a code units cache for the associated encoding. - sig { returns(T.untyped) } + sig { returns(::T.untyped) } private def cache; end end # A field representing the start and end byte columns. class ColumnsField # Fetches the start and end byte column of a value. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end end # A field representing the start and end character columns. class CharacterColumnsField # Fetches the start and end character column of a value. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end end @@ -240,11 +240,11 @@ module Prism # Fetches the start and end code units column of a value for a particular # encoding. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end # Lazily create a code units cache for the associated encoding. - sig { returns(T.untyped) } + sig { returns(::T.untyped) } private def cache; end end @@ -263,21 +263,21 @@ module Prism end # Create comment objects from the given values. - sig { params(values: T.untyped).returns(T::Array[Comment]) } + sig { params(values: ::T.untyped).returns(T::Array[Comment]) } private def comments(values); end end # A field representing the leading comments. class LeadingCommentsField < CommentsField # Fetches the leading comments of a value. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end end # A field representing the trailing comments. class TrailingCommentsField < CommentsField # Fetches the trailing comments of a value. - sig { params(value: T.untyped).returns(T::Hash[Symbol, T.untyped]) } + sig { params(value: ::T.untyped).returns(T::Hash[Symbol, ::T.untyped]) } def fields(value); end end @@ -294,7 +294,7 @@ module Prism attr_reader :source # The fields that have been configured on this repository. - sig { returns(T::Hash[Symbol, T.untyped]) } + sig { returns(T::Hash[Symbol, ::T.untyped]) } attr_reader :fields # The entries that have been saved on this repository. @@ -306,58 +306,58 @@ module Prism def initialize(source); end # Create a code units cache for the given encoding from the source. - sig { params(encoding: Encoding).returns(T.untyped) } + sig { params(encoding: Encoding).returns(::T.untyped) } def code_units_cache(encoding); end # Configure the filepath field for this repository and return self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def filepath; end # Configure the lines field for this repository and return self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def lines; end # Configure the offsets field for this repository and return self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def offsets; end # Configure the character offsets field for this repository and return # self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def character_offsets; end # Configure the code unit offsets field for this repository for a specific # encoding and return self. - sig { params(encoding: Encoding).returns(T.self_type) } + sig { params(encoding: Encoding).returns(::T.self_type) } def code_unit_offsets(encoding); end # Configure the columns field for this repository and return self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def columns; end # Configure the character columns field for this repository and return # self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def character_columns; end # Configure the code unit columns field for this repository for a specific # encoding and return self. - sig { params(encoding: Encoding).returns(T.self_type) } + sig { params(encoding: Encoding).returns(::T.self_type) } def code_unit_columns(encoding); end # Configure the leading comments field for this repository and return # self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def leading_comments; end # Configure the trailing comments field for this repository and return # self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def trailing_comments; end # Configure both the leading and trailing comment fields for this # repository and return self. - sig { returns(T.self_type) } + sig { returns(::T.self_type) } def comments; end # This method is called from nodes and locations when they want to enter @@ -374,7 +374,7 @@ module Prism # Append the given field to the repository and return the repository so # that these calls can be chained. - sig { params(name: Symbol, arg0: T.untyped).returns(T.self_type) } + sig { params(name: Symbol, arg0: ::T.untyped).returns(::T.self_type) } private def field(name, arg0); end end diff --git a/rbi/generated/prism/serialize.rbi b/rbi/generated/prism/serialize.rbi index 9957fc9858..80bf9be1da 100644 --- a/rbi/generated/prism/serialize.rbi +++ b/rbi/generated/prism/serialize.rbi @@ -49,14 +49,14 @@ module Prism sig { returns(Integer) } attr_reader :size - sig { params(input: String, serialized: String, base: Integer, size: Integer).void } - def initialize(input, serialized, base, size); end + sig { params(serialized: String, base: Integer, size: Integer).void } + def initialize(serialized, base, size); end sig { params(index: Integer, encoding: Encoding).returns(Symbol) } def get(index, encoding); end end - FastStringIO = T.let(nil, T.untyped) + FastStringIO = T.let(nil, ::T.untyped) class Loader sig { returns(String) } @@ -126,12 +126,9 @@ module Prism sig { returns(Integer) } def load_uint32; end - sig { params(constant_pool: ConstantPool, encoding: Encoding, freeze: T::Boolean).returns(T.nilable(Node)) } + sig { params(constant_pool: ConstantPool, encoding: Encoding, freeze: T::Boolean).returns(::T.nilable(Node)) } def load_optional_node(constant_pool, encoding, freeze); end - sig { params(encoding: Encoding).returns(String) } - def load_embedded_string(encoding); end - sig { params(encoding: Encoding).returns(String) } def load_string(encoding); end @@ -147,16 +144,16 @@ module Prism # Load an optional location object from the serialized data if it is # present. Note that we are lying about the signature a bit here, because # we sometimes load it as a packed integer instead of an object. - sig { params(freeze: T::Boolean).returns(T.nilable(Location)) } + sig { params(freeze: T::Boolean).returns(::T.nilable(Location)) } def load_optional_location(freeze); end - sig { params(freeze: T::Boolean).returns(T.nilable(Location)) } + sig { params(freeze: T::Boolean).returns(::T.nilable(Location)) } def load_optional_location_object(freeze); end sig { params(constant_pool: ConstantPool, encoding: Encoding).returns(Symbol) } def load_constant(constant_pool, encoding); end - sig { params(constant_pool: ConstantPool, encoding: Encoding).returns(T.nilable(Symbol)) } + sig { params(constant_pool: ConstantPool, encoding: Encoding).returns(::T.nilable(Symbol)) } def load_optional_constant(constant_pool, encoding); end sig { params(constant_pool: ConstantPool, encoding: Encoding, freeze: T::Boolean).returns(Node) } @@ -167,6 +164,6 @@ module Prism end # The token types that can be indexed by their enum values. - TOKEN_TYPES = T.let(nil, T::Array[T.nilable(Symbol)]) + TOKEN_TYPES = T.let(nil, T::Array[::T.nilable(Symbol)]) end end diff --git a/rbi/generated/prism/visitor.rbi b/rbi/generated/prism/visitor.rbi index 5025dd4c10..53534f1dc6 100644 --- a/rbi/generated/prism/visitor.rbi +++ b/rbi/generated/prism/visitor.rbi @@ -8,11 +8,11 @@ module Prism class BasicVisitor # Calls `accept` on the given node if it is not `nil`, which in turn should # call back into this visitor by calling the appropriate `visit_*` method. - sig { params(node: T.nilable(Node)).void } + sig { params(node: ::T.nilable(Node)).void } def visit(node); end # Visits each node in `nodes` by calling `accept` on each one. - sig { params(nodes: T::Array[T.nilable(Node)]).void } + sig { params(nodes: T::Array[::T.nilable(Node)]).void } def visit_all(nodes); end # Visits the child nodes of `node` by calling `accept` on each one. diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs index af25241fdb..dc56214867 100644 --- a/sig/generated/prism/parse_result.rbs +++ b/sig/generated/prism/parse_result.rbs @@ -697,6 +697,8 @@ module Prism # token of an unclosed construct rather than at the end of the source. These # errors always indicate incomplete input regardless of their byte position, # so they are checked by type rather than by location. + # -- + # : Array[Symbol] CONTINUABLE: untyped # Create a code units cache for the given encoding. diff --git a/sig/generated/prism/serialize.rbs b/sig/generated/prism/serialize.rbs index 468f18dd56..e0b944856b 100644 --- a/sig/generated/prism/serialize.rbs +++ b/sig/generated/prism/serialize.rbs @@ -53,16 +53,14 @@ module Prism # :nodoc: attr_reader size: Integer - @input: String - @serialized: String @base: Integer @pool: Array[Symbol?] - # : (String input, String serialized, Integer base, Integer size) -> void - def initialize: (String input, String serialized, Integer base, Integer size) -> void + # : (String serialized, Integer base, Integer size) -> void + def initialize: (String serialized, Integer base, Integer size) -> void # : (Integer index, Encoding encoding) -> Symbol def get: (Integer index, Encoding encoding) -> Symbol @@ -140,9 +138,6 @@ module Prism # : (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? def load_optional_node: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node? - # : (Encoding encoding) -> String - def load_embedded_string: (Encoding encoding) -> String - # : (Encoding encoding) -> String def load_string: (Encoding encoding) -> String From 2675dc0ee4158076eb2a2fb6ca0189c4f66b7706 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sun, 8 Mar 2026 19:58:04 +0100 Subject: [PATCH 096/289] Use ByteBuffer#get(int index, byte[] dst) in Loader.java * This is an absolute bulk get which does not modify the position, and therefore saves from getting, setting and restoring the position. --- templates/java/org/ruby_lang/prism/Loader.java.erb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index b48dd4c1cb..3c2a0cfd09 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -59,10 +59,7 @@ public class Loader { int length = buffer.getInt(offset + 4); byte[] bytes = new byte[length]; - int position = buffer.position(); - buffer.position(start); - buffer.get(bytes, 0, length); - buffer.position(position); + buffer.get(start, bytes); constant = loader.bytesToName(bytes); cache[index] = constant; From 697c3f1fe75766d9acf5ce8749cf5a8dfac0efe7 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sun, 8 Mar 2026 20:13:12 +0100 Subject: [PATCH 097/289] Use javac --release to properly check compatibility with older version --- Rakefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index 6e79e08b7f..01c4c62755 100644 --- a/Rakefile +++ b/Rakefile @@ -45,8 +45,7 @@ elsif RUBY_ENGINE == "jruby" ext.name = "prism" ext.ext_dir = "java" ext.lib_dir = "tmp" - ext.source_version = "1.8" - ext.target_version = "1.8" + ext.release = "8" ext.gem_spec = Gem::Specification.load("prism.gemspec") end end From 964702319ddd827c433ea714081bfff8cf3c1391 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sun, 8 Mar 2026 20:13:50 +0100 Subject: [PATCH 098/289] Compile Java files with compatibility 21+ * This is the minimum version that JRuby 10 requires. * It's also the minimum version that TruffleRuby 33 requires. --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 01c4c62755..80b00bd913 100644 --- a/Rakefile +++ b/Rakefile @@ -45,7 +45,7 @@ elsif RUBY_ENGINE == "jruby" ext.name = "prism" ext.ext_dir = "java" ext.lib_dir = "tmp" - ext.release = "8" + ext.release = "21" ext.gem_spec = Gem::Specification.load("prism.gemspec") end end From c28810fe931c64fd5087129b5bc2ea28ab73ba3c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 12:58:19 -0400 Subject: [PATCH 099/289] Refine continuable? with algorithm in C --- docs/serialization.md | 1 + ext/prism/extension.c | 3 +- include/prism/parser.h | 8 + java/org/ruby_lang/prism/ParseResult.java | 4 +- lib/prism/lex_compat.rb | 8 +- lib/prism/parse_result.rb | 73 ++------ rbi/generated/prism/lex_compat.rbi | 4 +- rbi/generated/prism/parse_result.rbi | 22 +-- rbi/generated/prism/serialize.rbi | 3 + sig/generated/prism/lex_compat.rbs | 4 +- sig/generated/prism/parse_result.rbs | 24 +-- sig/generated/prism/serialize.rbs | 3 + src/prism.c | 167 +++++++++++++++++- .../java/org/ruby_lang/prism/Loader.java.erb | 3 +- templates/javascript/src/deserialize.js.erb | 4 +- templates/lib/prism/serialize.rb.erb | 14 +- templates/src/serialize.c.erb | 1 + test/prism/errors_test.rb | 35 ---- test/prism/result/continuable_test.rb | 124 +++++++++++++ 19 files changed, 365 insertions(+), 140 deletions(-) create mode 100644 test/prism/result/continuable_test.rb diff --git a/docs/serialization.md b/docs/serialization.md index 8c1b47c690..a7ba533566 100644 --- a/docs/serialization.md +++ b/docs/serialization.md @@ -106,6 +106,7 @@ The header is structured like the following table: | error* | errors | | varuint | number of warnings | | warning* | warnings | +| `1` | `1` if the source is continuable (incomplete but could become valid with more input), `0` otherwise | | `4` | content pool offset | | varuint | content pool size | diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 7c90e48845..147434c975 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -641,10 +641,11 @@ parse_result_create(VALUE class, const pm_parser_t *parser, VALUE value, rb_enco parser_data_loc(parser, source, freeze), parser_errors(parser, encoding, source, freeze), parser_warnings(parser, encoding, source, freeze), + parser->continuable ? Qtrue : Qfalse, source }; - return rb_class_new_instance_freeze(7, result_argv, class, freeze); + return rb_class_new_instance_freeze(8, result_argv, class, freeze); } /******************************************************************************/ diff --git a/include/prism/parser.h b/include/prism/parser.h index ed4871197c..5ebace10c6 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -895,6 +895,14 @@ struct pm_parser { /** Whether or not we're currently recovering from a syntax error. */ bool recovering; + /** + * Whether or not the source being parsed could become valid if more input + * were appended. This is set to false when the parser encounters a token + * that is definitively wrong (e.g., a stray `end` or `]`) as opposed to + * merely incomplete. + */ + bool continuable; + /** * This is very specialized behavior for when you want to parse in a context * that does not respect encoding comments. Its main use case is translating diff --git a/java/org/ruby_lang/prism/ParseResult.java b/java/org/ruby_lang/prism/ParseResult.java index aad05a892d..7931327b9a 100644 --- a/java/org/ruby_lang/prism/ParseResult.java +++ b/java/org/ruby_lang/prism/ParseResult.java @@ -69,14 +69,16 @@ public Warning(Nodes.WarningType type, String message, Nodes.Location location, public final Nodes.Location dataLocation; public final Error[] errors; public final Warning[] warnings; + public final boolean continuable; public final Nodes.Source source; - public ParseResult(Nodes.Node value, MagicComment[] magicComments, Nodes.Location dataLocation, Error[] errors, Warning[] warnings, Nodes.Source source) { + public ParseResult(Nodes.Node value, MagicComment[] magicComments, Nodes.Location dataLocation, Error[] errors, Warning[] warnings, boolean continuable, Nodes.Source source) { this.value = value; this.magicComments = magicComments; this.dataLocation = dataLocation; this.errors = errors; this.warnings = warnings; + this.continuable = continuable; this.source = source; } } diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 0bc56ec592..e1b04fc6ce 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -43,10 +43,10 @@ class Result < Prism::Result # Create a new lex compat result object with the given values. #-- - #: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for Result. @@ -825,7 +825,7 @@ def result tokens = post_process_tokens(tokens, source, result.data_loc, bom, eof_token) - Result.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, source) + Result.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, result.continuable?, source) end private diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 4898fdd435..5c4d4fcb8a 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -898,13 +898,14 @@ class Result # Create a new result object with the given values. #-- - #: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize(comments, magic_comments, data_loc, errors, warnings, source) + #: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(comments, magic_comments, data_loc, errors, warnings, continuable, source) @comments = comments @magic_comments = magic_comments @data_loc = data_loc @errors = errors @warnings = warnings + @continuable = continuable @source = source end @@ -961,54 +962,8 @@ def failure? #-- #: () -> bool def continuable? - return false if errors.empty? - - offset = source.source.bytesize - errors.all? { |error| CONTINUABLE.include?(error.type) || error.location.start_offset == offset } - end - - # The set of error types whose location the parser places at the opening - # token of an unclosed construct rather than at the end of the source. These - # errors always indicate incomplete input regardless of their byte position, - # so they are checked by type rather than by location. - #-- - #: Array[Symbol] - CONTINUABLE = %i[ - begin_term - begin_upcase_term - block_param_pipe_term - block_term_brace - block_term_end - case_missing_conditions - case_term - class_term - conditional_term - conditional_term_else - def_term - embdoc_term - end_upcase_term - for_term - hash_term - heredoc_term - lambda_term_brace - lambda_term_end - list_i_lower_term - list_i_upper_term - list_w_lower_term - list_w_upper_term - module_term - regexp_term - rescue_term - string_interpolated_term - string_literal_eof - symbol_term_dynamic - symbol_term_interpolated - until_term - while_term - xstring_term - ].freeze - - private_constant :CONTINUABLE + @continuable + end # Create a code units cache for the given encoding. #-- @@ -1033,10 +988,10 @@ class ParseResult < Result # Create a new parse result object with the given values. #-- - #: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for ParseResult. @@ -1077,10 +1032,10 @@ class LexResult < Result # Create a new lex result object with the given values. #-- - #: (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #: (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for LexResult. @@ -1099,10 +1054,10 @@ class ParseLexResult < Result # Create a new parse lex result object with the given values. #-- - #: ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + #: ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) @value = value - super(comments, magic_comments, data_loc, errors, warnings, source) + super(comments, magic_comments, data_loc, errors, warnings, continuable, source) end # Implement the hash pattern matching interface for ParseLexResult. diff --git a/rbi/generated/prism/lex_compat.rbi b/rbi/generated/prism/lex_compat.rbi index 5ce03767c8..ca479b7225 100644 --- a/rbi/generated/prism/lex_compat.rbi +++ b/rbi/generated/prism/lex_compat.rbi @@ -36,8 +36,8 @@ module Prism attr_reader :value # Create a new lex compat result object with the given values. - sig { params(value: T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + sig { params(value: T::Array[[[Integer, Integer], Symbol, String, ::T.untyped]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end # Implement the hash pattern matching interface for Result. sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi index 4a904e85e1..ddced69934 100644 --- a/rbi/generated/prism/parse_result.rbi +++ b/rbi/generated/prism/parse_result.rbi @@ -558,8 +558,8 @@ module Prism attr_reader :source # Create a new result object with the given values. - sig { params(comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } - def initialize(comments, magic_comments, data_loc, errors, warnings, source); end + sig { params(comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(comments, magic_comments, data_loc, errors, warnings, continuable, source); end # Implement the hash pattern matching interface for Result. sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } @@ -602,12 +602,6 @@ module Prism sig { returns(T::Boolean) } def continuable?; end - # The set of error types whose location the parser places at the opening - # token of an unclosed construct rather than at the end of the source. These - # errors always indicate incomplete input regardless of their byte position, - # so they are checked by type rather than by location. - CONTINUABLE = T.let(nil, ::T.untyped) - # Create a code units cache for the given encoding. sig { params(encoding: Encoding).returns(::T.untyped) } def code_units_cache(encoding); end @@ -620,8 +614,8 @@ module Prism attr_reader :value # Create a new parse result object with the given values. - sig { params(value: ProgramNode, comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + sig { params(value: ProgramNode, comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end # Implement the hash pattern matching interface for ParseResult. sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } @@ -649,8 +643,8 @@ module Prism attr_reader :value # Create a new lex result object with the given values. - sig { params(value: T::Array[[Token, Integer]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + sig { params(value: T::Array[[Token, Integer]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end # Implement the hash pattern matching interface for LexResult. sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } @@ -665,8 +659,8 @@ module Prism attr_reader :value # Create a new parse lex result object with the given values. - sig { params(value: [ProgramNode, T::Array[[Token, Integer]]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], source: Source).void } - def initialize(value, comments, magic_comments, data_loc, errors, warnings, source); end + sig { params(value: [ProgramNode, T::Array[[Token, Integer]]], comments: T::Array[Comment], magic_comments: T::Array[MagicComment], data_loc: ::T.nilable(Location), errors: T::Array[ParseError], warnings: T::Array[ParseWarning], continuable: T::Boolean, source: Source).void } + def initialize(value, comments, magic_comments, data_loc, errors, warnings, continuable, source); end # Implement the hash pattern matching interface for ParseLexResult. sig { params(keys: ::T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, ::T.untyped]) } diff --git a/rbi/generated/prism/serialize.rbi b/rbi/generated/prism/serialize.rbi index 80bf9be1da..57b4c61acb 100644 --- a/rbi/generated/prism/serialize.rbi +++ b/rbi/generated/prism/serialize.rbi @@ -123,6 +123,9 @@ module Prism sig { returns(Float) } def load_double; end + sig { returns(T::Boolean) } + def load_bool; end + sig { returns(Integer) } def load_uint32; end diff --git a/sig/generated/prism/lex_compat.rbs b/sig/generated/prism/lex_compat.rbs index d6bf985b0a..707a96b9a8 100644 --- a/sig/generated/prism/lex_compat.rbs +++ b/sig/generated/prism/lex_compat.rbs @@ -38,8 +38,8 @@ module Prism # Create a new lex compat result object with the given values. # -- - # : (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + # : (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (Array[lex_compat_token] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void # Implement the hash pattern matching interface for Result. # -- diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs index dc56214867..d2b4035960 100644 --- a/sig/generated/prism/parse_result.rbs +++ b/sig/generated/prism/parse_result.rbs @@ -644,8 +644,8 @@ module Prism # Create a new result object with the given values. # -- - # : (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + # : (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void # Implement the hash pattern matching interface for Result. # -- @@ -693,14 +693,6 @@ module Prism # : () -> bool def continuable?: () -> bool - # The set of error types whose location the parser places at the opening - # token of an unclosed construct rather than at the end of the source. These - # errors always indicate incomplete input regardless of their byte position, - # so they are checked by type rather than by location. - # -- - # : Array[Symbol] - CONTINUABLE: untyped - # Create a code units cache for the given encoding. # -- # : (Encoding encoding) -> _CodeUnitsCache @@ -714,8 +706,8 @@ module Prism # Create a new parse result object with the given values. # -- - # : (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + # : (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (ProgramNode value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void # Implement the hash pattern matching interface for ParseResult. # -- @@ -747,8 +739,8 @@ module Prism # Create a new lex result object with the given values. # -- - # : (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize: (Array[[ Token, Integer ]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + # : (Array[[Token, Integer]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: (Array[[ Token, Integer ]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void # Implement the hash pattern matching interface for LexResult. # -- @@ -764,8 +756,8 @@ module Prism # Create a new parse lex result object with the given values. # -- - # : ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void - def initialize: ([ ProgramNode, Array[[ Token, Integer ]] ] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, Source source) -> void + # : ([ProgramNode, Array[[Token, Integer]]] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void + def initialize: ([ ProgramNode, Array[[ Token, Integer ]] ] value, Array[Comment] comments, Array[MagicComment] magic_comments, Location? data_loc, Array[ParseError] errors, Array[ParseWarning] warnings, bool continuable, Source source) -> void # Implement the hash pattern matching interface for ParseLexResult. # -- diff --git a/sig/generated/prism/serialize.rbs b/sig/generated/prism/serialize.rbs index e0b944856b..a83dae70d8 100644 --- a/sig/generated/prism/serialize.rbs +++ b/sig/generated/prism/serialize.rbs @@ -132,6 +132,9 @@ module Prism # : () -> Float def load_double: () -> Float + # : () -> bool + def load_bool: () -> bool + # : () -> Integer def load_uint32: () -> Integer diff --git a/src/prism.c b/src/prism.c index 18aa841ec9..6edc67b627 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22016,6 +22016,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si .partial_script = false, .command_start = true, .recovering = false, + .continuable = true, .encoding_locked = false, .encoding_changed = false, .pattern_matching_newlines = false, @@ -22292,12 +22293,176 @@ pm_parser_free(pm_parser_t *parser) { } } +/** + * Returns true if the given diagnostic ID represents an error that cannot be + * fixed by appending more input. These are errors where the existing source + * contains definitively invalid syntax (as opposed to merely incomplete input). + */ +static bool +pm_parse_err_is_fatal(pm_diagnostic_id_t diag_id) { + switch (diag_id) { + case PM_ERR_ARRAY_EXPRESSION_AFTER_STAR: + case PM_ERR_BEGIN_UPCASE_BRACE: + case PM_ERR_CLASS_VARIABLE_BARE: + case PM_ERR_END_UPCASE_BRACE: + case PM_ERR_ESCAPE_INVALID_HEXADECIMAL: + case PM_ERR_ESCAPE_INVALID_UNICODE_LIST: + case PM_ERR_ESCAPE_INVALID_UNICODE_SHORT: + case PM_ERR_EXPRESSION_NOT_WRITABLE: + case PM_ERR_EXPRESSION_NOT_WRITABLE_SELF: + case PM_ERR_FLOAT_PARSE: + case PM_ERR_GLOBAL_VARIABLE_BARE: + case PM_ERR_HASH_KEY: + case PM_ERR_HEREDOC_IDENTIFIER: + case PM_ERR_INSTANCE_VARIABLE_BARE: + case PM_ERR_INVALID_BLOCK_EXIT: + case PM_ERR_INVALID_ENCODING_MAGIC_COMMENT: + case PM_ERR_INVALID_FLOAT_EXPONENT: + case PM_ERR_INVALID_NUMBER_BINARY: + case PM_ERR_INVALID_NUMBER_DECIMAL: + case PM_ERR_INVALID_NUMBER_HEXADECIMAL: + case PM_ERR_INVALID_NUMBER_OCTAL: + case PM_ERR_INVALID_NUMBER_UNDERSCORE_TRAILING: + case PM_ERR_NO_LOCAL_VARIABLE: + case PM_ERR_PARAMETER_ORDER: + case PM_ERR_STATEMENT_UNDEF: + case PM_ERR_VOID_EXPRESSION: + return true; + default: + return false; + } +} + +/** + * Determine whether the source parsed by the given parser could become valid if + * more input were appended. This is used by tools like IRB to decide whether to + * prompt for continuation or to display an error. + * + * The parser starts with continuable=true. This function scans all errors to + * detect two categories of non-continuable errors: + * + * 1. Fatal errors: errors like invalid number literals or bare global variables + * that indicate definitively invalid syntax. These are only considered fatal + * if they occur before EOF (at EOF they could be from truncated input, e.g. + * `"\x` is an incomplete hex escape). + * + * 2. Stray tokens: unexpected_token_ignore and unexpected_token_close_context + * errors indicate tokens that don't belong. A stray token is a cascade + * effect (and does not prevent continuability) if: + * + * a. A non-stray, non-fatal error appeared earlier in the error list at a + * strictly earlier source position (the stray was caused by a preceding + * parse failure, e.g. a truncated heredoc), OR + * b. The stray token is at EOF, starts after position 0 (there is valid + * code before it), and either is a single byte (likely a truncated + * token like `\`) or there are non-stray errors elsewhere. + * + * Closing delimiters (`)`, `]`, `}`) at EOF are always genuinely stray — + * they are complete tokens and cannot become part of a longer valid + * construct by appending more input. + * + * c. The stray token is `=` at the start of a line, which could be the + * beginning of `=begin` (an embedded document). The remaining bytes + * after `=` may parse as an identifier, so the error is not at EOF, + * but the construct is genuinely incomplete. + */ +static void +pm_parse_continuable(pm_parser_t *parser) { + // If there are no errors then there is nothing to continue. + if (parser->error_list.size == 0) { + parser->continuable = false; + return; + } + + if (!parser->continuable) return; + + size_t source_length = (size_t) (parser->end - parser->start); + + // First pass: check if there are any non-stray, non-fatal errors. + bool has_non_stray_error = false; + for (pm_diagnostic_t *error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) { + if (error->diag_id != PM_ERR_UNEXPECTED_TOKEN_IGNORE && error->diag_id != PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT && !pm_parse_err_is_fatal(error->diag_id)) { + has_non_stray_error = true; + break; + } + } + + // Second pass: check each error. We track the minimum source position + // among non-stray, non-fatal errors seen so far in list order, which + // lets us detect cascade stray tokens. + size_t non_stray_min_start = SIZE_MAX; + + for (pm_diagnostic_t *error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) { + size_t error_start = (size_t) error->location.start; + size_t error_end = error_start + (size_t) error->location.length; + bool at_eof = error_end >= source_length; + + // Fatal errors are non-continuable unless they occur at EOF. + if (pm_parse_err_is_fatal(error->diag_id) && !at_eof) { + parser->continuable = false; + return; + } + + // Track non-stray, non-fatal error positions in list order. + if (error->diag_id != PM_ERR_UNEXPECTED_TOKEN_IGNORE && + error->diag_id != PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT) { + if (error_start < non_stray_min_start) non_stray_min_start = error_start; + continue; + } + + // This is a stray token. Determine if it is a cascade effect + // of a preceding error or genuinely stray. + + // Rule (a): a non-stray error was seen earlier in the list at a + // strictly earlier position — this stray is a cascade effect. + if (non_stray_min_start < error_start) continue; + + // Rule (b): this stray is at EOF with valid code before it. + // Single-byte stray tokens at EOF (like `\` for line continuation) + // are likely truncated tokens. Multi-byte stray tokens (like the + // keyword `end`) need additional evidence that they are cascade + // effects (i.e. non-stray errors exist elsewhere). + if (at_eof && error_start > 0) { + // Exception: closing delimiters at EOF are genuinely stray. + if (error->location.length == 1) { + const uint8_t *byte = parser->start + error_start; + if (*byte == ')' || *byte == ']' || *byte == '}') { + parser->continuable = false; + return; + } + + // Single-byte non-delimiter stray at EOF: cascade. + continue; + } + + // Multi-byte stray at EOF: cascade only if there are + // non-stray errors (evidence of a preceding parse failure). + if (has_non_stray_error) continue; + } + + // Rule (c): a stray `=` at the start of a line could be the + // beginning of an embedded document (`=begin`). The remaining + // bytes after `=` parse as an identifier, so the error is not + // at EOF, but the construct is genuinely incomplete. + if (error->location.length == 1) { + const uint8_t *byte = parser->start + error_start; + if (*byte == '=' && (error_start == 0 || *(byte - 1) == '\n')) continue; + } + + // This stray token is genuinely non-continuable. + parser->continuable = false; + return; + } +} + /** * Parse the Ruby source associated with the given parser and return the tree. */ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser) { - return parse_program(parser); + pm_node_t *node = parse_program(parser); + pm_parse_continuable(parser); + return node; } /** diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 3c2a0cfd09..23ba5d8544 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -112,6 +112,7 @@ public class Loader { Nodes.Location dataLocation = loadOptionalLocation(); ParseResult.Error[] errors = loadErrors(); ParseResult.Warning[] warnings = loadWarnings(); + boolean continuable = buffer.get() != 0; int constantPoolBufferOffset = buffer.getInt(); int constantPoolLength = loadVarUInt(); @@ -133,7 +134,7 @@ public class Loader { node = null; } - return new ParseResult(node, magicComments, dataLocation, errors, warnings, source); + return new ParseResult(node, magicComments, dataLocation, errors, warnings, continuable, source); } private byte[] loadString() { diff --git a/templates/javascript/src/deserialize.js.erb b/templates/javascript/src/deserialize.js.erb index 2aeb142f8d..34ff1574da 100644 --- a/templates/javascript/src/deserialize.js.erb +++ b/templates/javascript/src/deserialize.js.erb @@ -334,10 +334,12 @@ export function deserialize(array) { level: warningLevels[buffer.readByte()] })); + const continuable = buffer.readByte() !== 0; + const constantPoolOffset = buffer.readUint32(); const constants = Array.from({ length: buffer.readVarInt() }, () => null); - return new ParseResult(readRequiredNode(), comments, magicComments, dataLoc, errors, warnings); + return new ParseResult(readRequiredNode(), comments, magicComments, dataLoc, errors, warnings, continuable); function readRequiredNode() { const type = buffer.readByte(); diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index 4e61c89a89..c272d84bb4 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -43,6 +43,7 @@ module Prism data_loc = loader.load_optional_location_object(freeze) errors = loader.load_errors(encoding, freeze) warnings = loader.load_warnings(encoding, freeze) + continuable = loader.load_bool cpool_base = loader.load_uint32 cpool_size = loader.load_varuint @@ -52,7 +53,7 @@ module Prism loader.load_constant_pool(constant_pool) raise unless loader.eof? - result = ParseResult.new(node, comments, magic_comments, data_loc, errors, warnings, source) + result = ParseResult.new(node, comments, magic_comments, data_loc, errors, warnings, continuable, source) result.freeze if freeze input.force_encoding(encoding) @@ -97,9 +98,10 @@ module Prism data_loc = loader.load_optional_location_object(freeze) errors = loader.load_errors(encoding, freeze) warnings = loader.load_warnings(encoding, freeze) + continuable = loader.load_bool raise unless loader.eof? - result = LexResult.new(tokens, comments, magic_comments, data_loc, errors, warnings, source) + result = LexResult.new(tokens, comments, magic_comments, data_loc, errors, warnings, continuable, source) tokens.each do |token| token[0].value.force_encoding(encoding) @@ -168,6 +170,7 @@ module Prism data_loc = loader.load_optional_location_object(freeze) errors = loader.load_errors(encoding, freeze) warnings = loader.load_warnings(encoding, freeze) + continuable = loader.load_bool cpool_base = loader.load_uint32 cpool_size = loader.load_varuint @@ -178,7 +181,7 @@ module Prism raise unless loader.eof? value = [node, tokens] #: [ProgramNode, Array[[Token, Integer]]] - result = ParseLexResult.new(value, comments, magic_comments, data_loc, errors, warnings, source) + result = ParseLexResult.new(value, comments, magic_comments, data_loc, errors, warnings, continuable, source) tokens.each do |token| token[0].value.force_encoding(encoding) @@ -488,6 +491,11 @@ module Prism (io.read(8) or raise).unpack1("D") #: Float end + #: () -> bool + def load_bool + (io.getbyte or raise) != 0 + end + #: () -> Integer def load_uint32 (io.read(4) or raise).unpack1("L") #: Integer diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 4fe0cb88c1..1f90a2160e 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -247,6 +247,7 @@ pm_serialize_metadata(pm_parser_t *parser, pm_buffer_t *buffer) { pm_serialize_data_loc(parser, buffer); pm_serialize_diagnostic_list(&parser->error_list, buffer); pm_serialize_diagnostic_list(&parser->warning_list, buffer); + pm_buffer_append_byte(buffer, (uint8_t) parser->continuable); } #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index c3362eaaf5..9a54203f74 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -105,41 +105,6 @@ def test_unclosed_heredoc_and_interpolation assert_nil(statement.parts[0].statements) end - def test_continuable - # Valid input is not continuable (nothing to continue). - refute_predicate Prism.parse("1 + 1"), :continuable? - refute_predicate Prism.parse(""), :continuable? - - # Stray closing tokens make input non-continuable regardless of what - # follows (matches the feature-request examples exactly). - refute_predicate Prism.parse("1 + ]"), :continuable? - refute_predicate Prism.parse("end.tap do"), :continuable? - - # Unclosed constructs are continuable. - assert_predicate Prism.parse("1 + ["), :continuable? - assert_predicate Prism.parse("tap do"), :continuable? - - # Unclosed keywords. - assert_predicate Prism.parse("def foo"), :continuable? - assert_predicate Prism.parse("class Foo"), :continuable? - assert_predicate Prism.parse("module Foo"), :continuable? - assert_predicate Prism.parse("if true"), :continuable? - assert_predicate Prism.parse("while true"), :continuable? - assert_predicate Prism.parse("begin"), :continuable? - assert_predicate Prism.parse("for x in [1]"), :continuable? - - # Unclosed delimiters. - assert_predicate Prism.parse("{"), :continuable? - assert_predicate Prism.parse("foo("), :continuable? - assert_predicate Prism.parse('"hello'), :continuable? - assert_predicate Prism.parse("'hello"), :continuable? - assert_predicate Prism.parse("<<~HEREDOC\nhello"), :continuable? - - # A mix: stray end plus an unclosed block is not continuable because the - # stray end cannot be fixed by appending more input. - refute_predicate Prism.parse("end\ntap do"), :continuable? - end - private def assert_errors(filepath, version) diff --git a/test/prism/result/continuable_test.rb b/test/prism/result/continuable_test.rb new file mode 100644 index 0000000000..3533552167 --- /dev/null +++ b/test/prism/result/continuable_test.rb @@ -0,0 +1,124 @@ +# frozen_string_literal: true + +require_relative "../test_helper" + +module Prism + class ContinuableTest < TestCase + def test_valid_input + # Valid input is not continuable (nothing to continue). + refute_predicate Prism.parse("1 + 1"), :continuable? + refute_predicate Prism.parse(""), :continuable? + end + + def test_stray_closing_tokens + # Stray closing tokens make input non-continuable regardless of what + # follows (matches the feature-request examples exactly). + refute_predicate Prism.parse("1 + ]"), :continuable? + refute_predicate Prism.parse("end.tap do"), :continuable? + + # A mix: stray end plus an unclosed block is not continuable because the + # stray end cannot be fixed by appending more input. + refute_predicate Prism.parse("end\ntap do"), :continuable? + end + + def test_unclosed_constructs + # Unclosed constructs are continuable. + assert_predicate Prism.parse("1 + ["), :continuable? + assert_predicate Prism.parse("tap do"), :continuable? + end + + def test_unclosed_keywords + assert_predicate Prism.parse("def foo"), :continuable? + assert_predicate Prism.parse("class Foo"), :continuable? + assert_predicate Prism.parse("module Foo"), :continuable? + assert_predicate Prism.parse("if true"), :continuable? + assert_predicate Prism.parse("while true"), :continuable? + assert_predicate Prism.parse("begin"), :continuable? + assert_predicate Prism.parse("for x in [1]"), :continuable? + end + + def test_unclosed_delimiters + assert_predicate Prism.parse("{"), :continuable? + assert_predicate Prism.parse("foo("), :continuable? + assert_predicate Prism.parse('"hello'), :continuable? + assert_predicate Prism.parse("'hello"), :continuable? + assert_predicate Prism.parse("<<~HEREDOC\nhello"), :continuable? + end + + def test_trailing_whitespace + # Trailing whitespace or newlines should not affect continuability. + assert_predicate Prism.parse("class A\n"), :continuable? + assert_predicate Prism.parse("def f "), :continuable? + assert_predicate Prism.parse("def f\n"), :continuable? + assert_predicate Prism.parse("def f\n "), :continuable? + assert_predicate Prism.parse("( "), :continuable? + assert_predicate Prism.parse("(\n"), :continuable? + assert_predicate Prism.parse("1 +\n"), :continuable? + end + + def test_incomplete_expressions + assert_predicate Prism.parse("-"), :continuable? + assert_predicate Prism.parse("[1,"), :continuable? + assert_predicate Prism.parse("f arg1,"), :continuable? + assert_predicate Prism.parse("def f ="), :continuable? + assert_predicate Prism.parse("def $a"), :continuable? + assert_predicate Prism.parse("a ="), :continuable? + assert_predicate Prism.parse("a,b"), :continuable? + end + + def test_modifier_keywords + assert_predicate Prism.parse("return if"), :continuable? + assert_predicate Prism.parse("return unless"), :continuable? + assert_predicate Prism.parse("while"), :continuable? + assert_predicate Prism.parse("until"), :continuable? + end + + def test_ternary_operator + assert_predicate Prism.parse("x ?"), :continuable? + assert_predicate Prism.parse("x ? y :"), :continuable? + end + + def test_class_with_superclass + assert_predicate Prism.parse("class Foo <"), :continuable? + end + + def test_keyword_expressions + assert_predicate Prism.parse("not"), :continuable? + assert_predicate Prism.parse("defined?"), :continuable? + assert_predicate Prism.parse("module"), :continuable? + end + + def test_for_loops + assert_predicate Prism.parse("for"), :continuable? + assert_predicate Prism.parse("for x in"), :continuable? + end + + def test_pattern_matching + assert_predicate Prism.parse("foo => ["), :continuable? + assert_predicate Prism.parse("case foo; when"), :continuable? + end + + def test_splat_and_block_pass + assert_predicate Prism.parse("[*"), :continuable? + assert_predicate Prism.parse("f(**"), :continuable? + assert_predicate Prism.parse("f(&"), :continuable? + end + + def test_default_parameter_value + assert_predicate Prism.parse("def f(x ="), :continuable? + end + + def test_line_continuation + assert_predicate Prism.parse("1 +\\"), :continuable? + assert_predicate Prism.parse("\"foo\" \\"), :continuable? + end + + def test_embedded_document + # Embedded document (=begin) truncated at various points. + assert_predicate Prism.parse("=b"), :continuable? + assert_predicate Prism.parse("=beg"), :continuable? + assert_predicate Prism.parse("=begin"), :continuable? + assert_predicate Prism.parse("foo\n=b"), :continuable? + end + end +end From fd0a20f8d8fdeae31bc042fdcf98b596ed31899c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 21:46:37 -0400 Subject: [PATCH 100/289] Fix binding for `in`, `not`, and `do` on/after command calls --- snapshots/command_method_call_2.txt | 76 +- src/prism.c | 678 ++++++++++-------- test/prism/errors/command_call_in.txt | 1 + test/prism/errors/command_call_value_and.txt | 3 + test/prism/errors/command_call_value_or.txt | 3 + test/prism/errors/command_calls_34.txt | 15 +- test/prism/errors/command_calls_35.txt | 6 +- .../destroy_call_operator_write_arguments.txt | 6 +- test/prism/fixtures/command_method_call_2.txt | 2 - 9 files changed, 429 insertions(+), 361 deletions(-) create mode 100644 test/prism/errors/command_call_value_and.txt create mode 100644 test/prism/errors/command_call_value_or.txt diff --git a/snapshots/command_method_call_2.txt b/snapshots/command_method_call_2.txt index ef3e73201c..8b52d4b368 100644 --- a/snapshots/command_method_call_2.txt +++ b/snapshots/command_method_call_2.txt @@ -1,95 +1,49 @@ -@ ProgramNode (location: (1,0)-(3,17)) +@ ProgramNode (location: (1,0)-(1,17)) ├── flags: ∅ ├── locals: [] └── statements: - @ StatementsNode (location: (1,0)-(3,17)) + @ StatementsNode (location: (1,0)-(1,17)) ├── flags: ∅ - └── body: (length: 2) - ├── @ CallNode (location: (1,0)-(1,19)) - │ ├── flags: newline, ignore_visibility - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :foo - │ ├── message_loc: (1,0)-(1,3) = "foo" - │ ├── opening_loc: (1,3)-(1,4) = "(" - │ ├── arguments: - │ │ @ ArgumentsNode (location: (1,4)-(1,18)) - │ │ ├── flags: ∅ - │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (1,4)-(1,18)) - │ │ ├── flags: ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :bar - │ │ ├── message_loc: (1,4)-(1,7) = "bar" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (1,8)-(1,11)) - │ │ │ ├── flags: ∅ - │ │ │ └── arguments: (length: 1) - │ │ │ └── @ CallNode (location: (1,8)-(1,11)) - │ │ │ ├── flags: variable_call, ignore_visibility - │ │ │ ├── receiver: ∅ - │ │ │ ├── call_operator_loc: ∅ - │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (1,8)-(1,11) = "baz" - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── arguments: ∅ - │ │ │ ├── closing_loc: ∅ - │ │ │ ├── equal_loc: ∅ - │ │ │ └── block: ∅ - │ │ ├── closing_loc: ∅ - │ │ ├── equal_loc: ∅ - │ │ └── block: - │ │ @ BlockNode (location: (1,12)-(1,18)) - │ │ ├── flags: ∅ - │ │ ├── locals: [] - │ │ ├── parameters: ∅ - │ │ ├── body: ∅ - │ │ ├── opening_loc: (1,12)-(1,14) = "do" - │ │ └── closing_loc: (1,15)-(1,18) = "end" - │ ├── closing_loc: (1,18)-(1,19) = ")" - │ ├── equal_loc: ∅ - │ └── block: ∅ - └── @ CallNode (location: (3,0)-(3,17)) + └── body: (length: 1) + └── @ CallNode (location: (1,0)-(1,17)) ├── flags: newline, ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo - ├── message_loc: (3,0)-(3,3) = "foo" - ├── opening_loc: (3,3)-(3,4) = "(" + ├── message_loc: (1,0)-(1,3) = "foo" + ├── opening_loc: (1,3)-(1,4) = "(" ├── arguments: - │ @ ArgumentsNode (location: (3,4)-(3,16)) + │ @ ArgumentsNode (location: (1,4)-(1,16)) │ ├── flags: ∅ │ └── arguments: (length: 1) - │ └── @ CallNode (location: (3,4)-(3,16)) + │ └── @ CallNode (location: (1,4)-(1,16)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :bar - │ ├── message_loc: (3,4)-(3,7) = "bar" + │ ├── message_loc: (1,4)-(1,7) = "bar" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (3,8)-(3,16)) + │ │ @ ArgumentsNode (location: (1,8)-(1,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (3,8)-(3,11)) + │ │ ├── @ CallNode (location: (1,8)-(1,11)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (3,8)-(3,11) = "baz" + │ │ │ ├── message_loc: (1,8)-(1,11) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ ├── equal_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (3,13)-(3,16)) + │ │ └── @ CallNode (location: (1,13)-(1,16)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bat - │ │ ├── message_loc: (3,13)-(3,16) = "bat" + │ │ ├── message_loc: (1,13)-(1,16) = "bat" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ @@ -98,6 +52,6 @@ │ ├── closing_loc: ∅ │ ├── equal_loc: ∅ │ └── block: ∅ - ├── closing_loc: (3,16)-(3,17) = ")" + ├── closing_loc: (1,16)-(1,17) = ")" ├── equal_loc: ∅ └── block: ∅ diff --git a/src/prism.c b/src/prism.c index 6edc67b627..3b2b03cdd5 100644 --- a/src/prism.c +++ b/src/prism.c @@ -12455,16 +12455,22 @@ expect1_opening(pm_parser_t *parser, pm_token_type_t type, pm_diagnostic_id_t di parser->previous.type = 0; } +/** Flags for controlling expression parsing behavior. */ +#define PM_PARSE_ACCEPTS_COMMAND_CALL ((uint8_t) 0x1) +#define PM_PARSE_ACCEPTS_LABEL ((uint8_t) 0x2) +#define PM_PARSE_ACCEPTS_DO_BLOCK ((uint8_t) 0x4) +#define PM_PARSE_IN_ENDLESS_DEF ((uint8_t) 0x8) + static pm_node_t * -parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth); +parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth); /** * This is a wrapper of parse_expression, which also checks whether the * resulting node is a value expression. */ static pm_node_t * -parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { - pm_node_t *node = parse_expression(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth); +parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { + pm_node_t *node = parse_expression(parser, binding_power, flags, diag_id, depth); pm_assert_value_expression(parser, node); return node; } @@ -12549,14 +12555,14 @@ token_begins_expression_p(pm_token_type_t type) { * prefixed by the * operator. */ static pm_node_t * -parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) { +parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { if (accept1(parser, PM_TOKEN_USTAR)) { pm_token_t operator = parser->previous; - pm_node_t *expression = parse_value_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, binding_power, (uint8_t) (flags & PM_PARSE_ACCEPTS_DO_BLOCK), PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); return UP(pm_splat_node_create(parser, &operator, expression)); } - return parse_value_expression(parser, binding_power, accepts_command_call, false, diag_id, depth); + return parse_value_expression(parser, binding_power, flags, diag_id, depth); } static bool @@ -13116,7 +13122,7 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b pm_node_t *name = NULL; if (token_begins_expression_p(parser->current.type)) { - name = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + name = parse_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); name = parse_target(parser, name, true, true); } @@ -13125,13 +13131,13 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b has_rest = true; } else if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { context_push(parser, PM_CONTEXT_MULTI_TARGET); - pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); + pm_node_t *target = parse_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); target = parse_target(parser, target, true, false); pm_multi_target_node_targets_append(parser, result, target); context_pop(parser); } else if (token_begins_expression_p(parser->current.type)) { - pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); + pm_node_t *target = parse_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); target = parse_target(parser, target, true, false); pm_multi_target_node_targets_append(parser, result, target); @@ -13183,7 +13189,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { context_push(parser, context); while (true) { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); pm_statements_node_body_append(parser, statements, node, true); // If we're recovering from a syntax error, then we need to stop parsing @@ -13248,6 +13254,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { } context_pop(parser); + bool last_value = true; switch (context) { case PM_CONTEXT_BEGIN_ENSURE: @@ -13331,9 +13338,9 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod // inner hash to share the static literals with the outer // hash. parser->current_hash_keys = literals; - value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); } else if (token_begins_expression_p(parser->current.type)) { - value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1)); } else { pm_parser_scope_forwarding_keywords_check(parser, &operator); } @@ -13352,7 +13359,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod pm_node_t *value = NULL; if (token_begins_expression_p(parser->current.type)) { - value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL, (uint16_t) (depth + 1)); + value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_HASH_EXPRESSION_AFTER_LABEL, (uint16_t) (depth + 1)); } else { if (parser->encoding->isupper_char(label.start, (label.end - 1) - label.start)) { pm_token_t constant = { .type = PM_TOKEN_CONSTANT, .start = label.start, .end = label.end - 1 }; @@ -13382,7 +13389,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod break; } default: { - pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, true, PM_ERR_HASH_KEY, (uint16_t) (depth + 1)); + pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_LABEL, PM_ERR_HASH_KEY, (uint16_t) (depth + 1)); // Hash keys that are strings are automatically frozen. We will // mark that here. @@ -13398,7 +13405,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod operator = parser->previous; } - pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); element = UP(pm_assoc_node_create(parser, key, NTOK2PTR(operator), value)); break; } @@ -13468,7 +13475,7 @@ parse_arguments_append(pm_parser_t *parser, pm_arguments_t *arguments, pm_node_t * Parse a list of arguments. */ static void -parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_forwarding, pm_token_type_t terminator, uint16_t depth) { +parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_forwarding, pm_token_type_t terminator, uint8_t flags, uint16_t depth) { pm_binding_power_t binding_power = pm_binding_powers[parser->current.type].left; // First we need to check if the next token is one that could be the start @@ -13508,9 +13515,9 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for parse_arguments_append(parser, arguments, argument); - pm_node_flags_t flags = PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; - if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; - pm_node_flag_set(UP(arguments->arguments), flags); + pm_node_flags_t node_flags = PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; + if (contains_keyword_splat) node_flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; + pm_node_flag_set(UP(arguments->arguments), node_flags); pm_static_literals_free(&hash_keys); parsed_bare_hash = true; @@ -13523,7 +13530,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_node_t *expression = NULL; if (token_begins_expression_p(parser->current.type)) { - expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); + expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); } else { pm_parser_scope_forwarding_block_check(parser, &operator); } @@ -13553,7 +13560,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_parser_err_previous(parser, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT); } } else { - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT, (uint16_t) (depth + 1)); if (parsed_bare_hash) { pm_parser_err(parser, PM_TOKEN_START(parser, &operator), PM_NODE_END(expression) - PM_TOKEN_START(parser, &operator), PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT); @@ -13574,7 +13581,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for // not actually argument forwarding but was instead a // range. pm_token_t operator = parser->previous; - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); // If we parse a range, we need to validate that we // didn't accidentally violate the nonassoc rules of the @@ -13603,7 +13610,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for PRISM_FALLTHROUGH default: { if (argument == NULL) { - argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, true, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); + argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (!parsed_first_argument ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0u) | PM_PARSE_ACCEPTS_LABEL, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); } bool contains_keywords = false; @@ -13627,7 +13634,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_hash_key_static_literals_add(parser, &hash_keys, argument); // Finish parsing the one we are part way through. - pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); argument = UP(pm_assoc_node_create(parser, argument, NTOK2PTR(operator), value)); pm_keyword_hash_node_elements_append(parser->arena, bare_hash, argument); @@ -13647,10 +13654,10 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for parse_arguments_append(parser, arguments, argument); - pm_node_flags_t flags = 0; - if (contains_keywords) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; - if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; - pm_node_flag_set(UP(arguments->arguments), flags); + pm_node_flags_t node_flags = 0; + if (contains_keywords) node_flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS; + if (contains_keyword_splat) node_flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT; + pm_node_flag_set(UP(arguments->arguments), node_flags); break; } @@ -14018,7 +14025,7 @@ parse_parameters( uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0; if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true); - pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_PARAMETER_NO_DEFAULT, (uint16_t) (depth + 1)); if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser); pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value); @@ -14119,7 +14126,7 @@ parse_parameters( uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0; if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true); - pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT_KW, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, binding_power, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_PARAMETER_NO_DEFAULT_KW, (uint16_t) (depth + 1)); if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser); if (parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) { @@ -14399,7 +14406,7 @@ parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_ parser_lex(parser); pm_rescue_node_operator_set(parser, rescue, &parser->previous); - pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); + pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); reference = parse_target(parser, reference, false, false); pm_rescue_node_reference_set(rescue, reference); @@ -14429,7 +14436,7 @@ parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_ if (accept1(parser, PM_TOKEN_EQUAL_GREATER)) { pm_rescue_node_operator_set(parser, rescue, &parser->previous); - pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); + pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1)); reference = parse_target(parser, reference, false, false); pm_rescue_node_reference_set(rescue, reference); @@ -14832,34 +14839,13 @@ parse_block(pm_parser_t *parser, uint16_t depth) { return pm_block_node_create(parser, &locals, &opening, parameters, statements, &parser->previous); } -/** - * Attach a do-block (PM_TOKEN_KEYWORD_DO_BLOCK) to a command-style call node. - * The current token must be PM_TOKEN_KEYWORD_DO_BLOCK when this is called. - */ -static void -parse_command_do_block(pm_parser_t *parser, pm_call_node_t *call, uint16_t depth) { - parser_lex(parser); - pm_block_node_t *block = parse_block(parser, (uint16_t) (depth + 1)); - - if (call->block != NULL) { - pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_BLOCK_MULTI); - if (call->arguments == NULL) { - call->arguments = pm_arguments_node_create(parser); - } - pm_arguments_node_arguments_append(parser->arena, call->arguments, call->block); - } - - call->block = UP(block); - PM_NODE_LENGTH_SET_NODE(call, block); -} - /** * Parse a list of arguments and their surrounding parentheses if they are * present. It returns true if it found any pieces of arguments (parentheses, * arguments, or blocks). */ static bool -parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call, uint16_t depth) { +parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, uint8_t flags, uint16_t depth) { bool found = false; bool parsed_command_args = false; @@ -14871,7 +14857,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept arguments->closing_loc = TOK2LOC(parser, &parser->previous); } else { pm_accepts_block_stack_push(parser, true); - parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT, (uint16_t) (depth + 1)); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT, (uint8_t) (flags & ~PM_PARSE_ACCEPTS_DO_BLOCK), (uint16_t) (depth + 1)); if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_ARGUMENT_TERM_PAREN, pm_token_type_human(parser->current.type)); @@ -14882,7 +14868,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept pm_accepts_block_stack_pop(parser); arguments->closing_loc = TOK2LOC(parser, &parser->previous); } - } else if (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND)) && !match1(parser, PM_TOKEN_BRACE_LEFT)) { + } else if ((flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND)) && !match1(parser, PM_TOKEN_BRACE_LEFT)) { found |= true; parsed_command_args = true; pm_accepts_block_stack_push(parser, false); @@ -14890,7 +14876,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept // If we get here, then the subsequent token cannot be used as an infix // operator. In this case we assume the subsequent token is part of an // argument to this method call. - parse_arguments(parser, arguments, accepts_block, PM_TOKEN_EOF, (uint16_t) (depth + 1)); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_EOF, flags, (uint16_t) (depth + 1)); // If we have done with the arguments and still not consumed the comma, // then we have a trailing comma where we need to check whether it is @@ -14915,7 +14901,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept } else if (pm_accepts_block_stack_p(parser) && accept1(parser, PM_TOKEN_KEYWORD_DO)) { found |= true; block = parse_block(parser, (uint16_t) (depth + 1)); - } else if (parsed_command_args && pm_accepts_block_stack_p(parser) && !parser->in_endless_def_body && accept1(parser, PM_TOKEN_KEYWORD_DO_BLOCK)) { + } else if (parsed_command_args && pm_accepts_block_stack_p(parser) && (flags & PM_PARSE_ACCEPTS_DO_BLOCK) && accept1(parser, PM_TOKEN_KEYWORD_DO_BLOCK)) { found |= true; block = parse_block(parser, (uint16_t) (depth + 1)); } @@ -15179,7 +15165,7 @@ static inline pm_node_t * parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword, uint16_t depth) { context_push(parser, PM_CONTEXT_PREDICATE); pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE; - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, error_id, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, error_id, (uint16_t) (depth + 1)); // Predicates are closed by a term, a "then", or a term and then a "then". bool predicate_closed = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); @@ -16709,7 +16695,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm first_node = parse_pattern_keyword_rest(parser, captures); break; case PM_TOKEN_STRING_BEGIN: - first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, true, PM_ERR_PATTERN_HASH_KEY_LABEL, (uint16_t) (depth + 1)); + first_node = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_LABEL, PM_ERR_PATTERN_HASH_KEY_LABEL, (uint16_t) (depth + 1)); break; default: { PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_PATTERN_HASH_KEY, pm_token_type_human(parser->current.type)); @@ -16745,7 +16731,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm // expression as the right side of the range. switch (parser->current.type) { case PM_CASE_PRIMITIVE: { - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); return UP(pm_range_node_create(parser, NULL, &operator, right)); } default: { @@ -16756,7 +16742,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm } } case PM_CASE_PRIMITIVE: { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, false, true, diag_id, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_LABEL | PM_PARSE_ACCEPTS_DO_BLOCK, diag_id, (uint16_t) (depth + 1)); // If we found a label, we need to immediately return to the caller. if (pm_symbol_node_label_p(parser, node)) return node; @@ -16779,7 +16765,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm // node. Otherwise, we'll create an endless range. switch (parser->current.type) { case PM_CASE_PRIMITIVE: { - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1)); return UP(pm_range_node_create(parser, node, &operator, right)); } default: @@ -16844,7 +16830,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm pm_token_t lparen = parser->current; parser_lex(parser); - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; accept1(parser, PM_TOKEN_NEWLINE); @@ -17454,11 +17440,104 @@ parse_regular_expression_errors(pm_parser_t *parser, pm_regular_expression_node_ pm_regexp_parse(parser, pm_string_source(unescaped), pm_string_length(unescaped), PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED), NULL, NULL, parse_regular_expression_error, &error_data); } +/** + * Determine if a given call node looks like a "command", which means it has + * arguments but does not have parentheses. + */ +static inline bool +pm_call_node_command_p(const pm_call_node_t *node) { + return ( + (node->opening_loc.length == 0) && + (node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE)) && + (node->arguments != NULL || node->block != NULL) + ); +} + +/** + * Returns true if the given node is a command-style call (a method call without + * parentheses that has arguments), excluding operator calls (e.g., a + b) which + * satisfy the same structural criteria but are not commands. + */ +static bool +pm_command_call_value_p(const pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_CALL_NODE: { + const pm_call_node_t *call = (const pm_call_node_t *) node; + + // Command-style calls (e.g., foo bar, obj.foo bar). + // Attribute writes (e.g., a.b = 1) are not commands. + if (pm_call_node_command_p(call) && !PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) && (call->receiver == NULL || call->call_operator_loc.length > 0)) { + return true; + } + + // A `!` or `not` prefix wrapping a command call (e.g., + // `!foo bar`, `not foo bar`) is also a command-call value. + if (call->receiver != NULL && call->arguments == NULL && call->opening_loc.length == 0 && call->call_operator_loc.length == 0) { + return pm_command_call_value_p(call->receiver); + } + + return false; + } + case PM_SUPER_NODE: { + const pm_super_node_t *cast = (const pm_super_node_t *) node; + return cast->lparen_loc.length == 0 && (cast->arguments != NULL || cast->block != NULL); + } + case PM_YIELD_NODE: { + const pm_yield_node_t *cast = (const pm_yield_node_t *) node; + return cast->lparen_loc.length == 0 && cast->arguments != NULL; + } + case PM_RESCUE_MODIFIER_NODE: + return pm_command_call_value_p(((const pm_rescue_modifier_node_t *) node)->expression); + case PM_DEF_NODE: { + const pm_def_node_t *cast = (const pm_def_node_t *) node; + if (cast->equal_loc.length > 0 && cast->body != NULL) { + const pm_node_t *body = cast->body; + if (PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE)) { + body = ((const pm_statements_node_t *) body)->body.nodes[((const pm_statements_node_t *) body)->body.size - 1]; + } + return pm_command_call_value_p(body); + } + return false; + } + default: + return false; + } +} + +/** + * Returns true if the given node is a block call: a command + * with a do-block, or any call chained (via `.`, `::`, `&.`) from such a node. + * Block calls can only be followed by call chaining, composition (and/or), and + * modifier operators. + */ +static bool +pm_block_call_p(const pm_node_t *node) { + while (PM_NODE_TYPE_P(node, PM_CALL_NODE)) { + const pm_call_node_t *call = (const pm_call_node_t *) node; + if (call->opening_loc.length > 0) return false; + + // Root: command with do-block (e.g., `foo bar do end`). + if (call->arguments != NULL && call->block != NULL && PM_NODE_TYPE_P(call->block, PM_BLOCK_NODE)) { + return true; + } + + // Walk up the receiver chain (e.g., `foo bar do end.baz`). + if (call->call_operator_loc.length > 0 && call->receiver != NULL) { + node = call->receiver; + continue; + } + + return false; + } + + return false; +} + /** * Parse an expression that begins with the previous node that we just lexed. */ static inline pm_node_t * -parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { +parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { switch (parser->current.type) { case PM_TOKEN_BRACKET_LEFT_ARRAY: { parser_lex(parser); @@ -17507,7 +17586,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match3(parser, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_EOF)) { pm_parser_scope_forwarding_positionals_check(parser, &operator); } else { - expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } element = UP(pm_splat_node_create(parser, &operator, expression)); @@ -17526,7 +17605,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_static_literals_free(&hash_keys); parsed_bare_hash = true; } else { - element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, true, PM_ERR_ARRAY_EXPRESSION, (uint16_t) (depth + 1)); + element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_LABEL, PM_ERR_ARRAY_EXPRESSION, (uint16_t) (depth + 1)); if (pm_symbol_node_label_p(parser, element) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) { if (parsed_bare_hash) { @@ -17542,7 +17621,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b operator = parser->previous; } - pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); + pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1)); pm_node_t *assoc = UP(pm_assoc_node_create(parser, element, NTOK2PTR(operator), value)); pm_keyword_hash_node_elements_append(parser->arena, hash, assoc); @@ -17576,7 +17655,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b case PM_TOKEN_PARENTHESIS_LEFT: case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: { pm_token_t opening = parser->current; - pm_node_flags_t flags = 0; + pm_node_flags_t paren_flags = 0; pm_node_list_t current_block_exits = { 0 }; pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); @@ -17584,7 +17663,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); while (true) { if (accept1(parser, PM_TOKEN_SEMICOLON)) { - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; } else if (!accept1(parser, PM_TOKEN_NEWLINE)) { break; } @@ -17595,14 +17674,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match2(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_EOF)) { expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN); pop_block_exits(parser, previous_block_exits); - return UP(pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, flags)); + return UP(pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, paren_flags)); } // Otherwise, we're going to parse the first statement in the list // of statements within the parentheses. pm_accepts_block_stack_push(parser, true); context_push(parser, PM_CONTEXT_PARENS); - pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); context_pop(parser); // Determine if this statement is followed by a terminator. In the @@ -17612,7 +17691,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_SEMICOLON)) { terminator_found = true; - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; } else if (accept1(parser, PM_TOKEN_NEWLINE)) { terminator_found = true; } @@ -17620,7 +17699,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (terminator_found) { while (true) { if (accept1(parser, PM_TOKEN_SEMICOLON)) { - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; } else if (!accept1(parser, PM_TOKEN_NEWLINE)) { break; } @@ -17691,14 +17770,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); - return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags)); + return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, paren_flags)); } // If we have more than one statement in the set of parentheses, // then we are going to parse all of them as a list of statements. // We'll do that here. context_push(parser, PM_CONTEXT_PARENS); - flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; + paren_flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS; pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, statement, true); @@ -17711,7 +17790,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // Parse each statement within the parentheses. while (true) { - pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1)); pm_statements_node_body_append(parser, statements, node, true); // If we're recovering from a syntax error, then we need to stop @@ -17774,7 +17853,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pop_block_exits(parser, previous_block_exits); pm_void_statements_check(parser, statements, true); - return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags)); + return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, paren_flags)); } case PM_TOKEN_BRACE_LEFT: { // If we were passed a current_hash_keys via the parser, then that @@ -17859,12 +17938,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // fact a method call, not a constant read. if ( match1(parser, PM_TOKEN_PARENTHESIS_LEFT) || - (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || + ((flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); return UP(pm_call_node_fcall_create(parser, &constant, &arguments)); } @@ -17896,7 +17975,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t operator = parser->current; parser_lex(parser); - pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); // Unary .. and ... are special because these are non-associative // operators that can also be unary operators. In this case we need @@ -17964,7 +18043,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_call_node_t *call = (pm_call_node_t *) node; pm_arguments_t arguments = { 0 }; - if (parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1))) { + if (parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1))) { // Since we found arguments, we need to turn off the // variable call bit in the flags. pm_node_flag_unset(UP(call), PM_CALL_NODE_FLAGS_VARIABLE_CALL); @@ -17986,12 +18065,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // can still be a method call if it is followed by arguments or // a block, so we need to check for that here. if ( - (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || + ((flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); pm_call_node_t *fcall = pm_call_node_fcall_create(parser, &identifier, &arguments); if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) { @@ -18230,7 +18309,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } else if (!token_begins_expression_p(parser->current.type)) { predicate = NULL; } else { - predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CASE_EXPRESSION_AFTER_CASE, (uint16_t) (depth + 1)); + predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CASE_EXPRESSION_AFTER_CASE, (uint16_t) (depth + 1)); while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)); } @@ -18263,14 +18342,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b do { if (accept1(parser, PM_TOKEN_USTAR)) { pm_token_t operator = parser->previous; - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); pm_splat_node_t *splat_node = pm_splat_node_create(parser, &operator, expression); pm_when_node_conditions_append(parser->arena, when_node, UP(splat_node)); if (PM_NODE_TYPE_P(expression, PM_MISSING_NODE)) break; } else { - pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN, (uint16_t) (depth + 1)); + pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_CASE_EXPRESSION_AFTER_WHEN, (uint16_t) (depth + 1)); pm_when_node_conditions_append(parser->arena, when_node, condition); // If we found a missing node, then this is a syntax @@ -18350,11 +18429,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // `unless` statements. if (accept1(parser, PM_TOKEN_KEYWORD_IF_MODIFIER)) { pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); pattern = UP(pm_if_node_modifier_create(parser, pattern, &keyword, predicate)); } else if (accept1(parser, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) { pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); pattern = UP(pm_unless_node_modifier_create(parser, pattern, &keyword, predicate)); } @@ -18492,10 +18571,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (binding_power == PM_BINDING_POWER_UNSET || binding_power >= PM_BINDING_POWER_RANGE) { pm_token_t next = parser->current; - parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, (uint16_t) (depth + 1)); + parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, flags, (uint16_t) (depth + 1)); // Reject `foo && return bar`. - if (!accepts_command_call && arguments.arguments != NULL) { + if (!(flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && arguments.arguments != NULL) { PM_PARSER_ERR_TOKEN_FORMAT(parser, &next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(next.type)); } } @@ -18527,7 +18606,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t keyword = parser->previous; pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); if ( arguments.opening_loc.length == 0 && @@ -18544,7 +18623,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t keyword = parser->previous; pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, false, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, false, flags, (uint16_t) (depth + 1)); // It's possible that we've parsed a block argument through our // call to parse_arguments_list. If we found one, we should mark it @@ -18573,7 +18652,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (accept1(parser, PM_TOKEN_LESS_LESS)) { pm_token_t operator = parser->previous; - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS, (uint16_t) (depth + 1)); pm_parser_scope_push(parser, true); if (!match2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { @@ -18606,7 +18685,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b return UP(pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous)); } - pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_CLASS_NAME, (uint16_t) (depth + 1)); + pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_CLASS_NAME, (uint16_t) (depth + 1)); pm_token_t name = parser->previous; if (name.type != PM_TOKEN_CONSTANT) { pm_parser_err_token(parser, &name, PM_ERR_CLASS_NAME); @@ -18622,7 +18701,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser->command_start = true; parser_lex(parser); - superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CLASS_SUPERCLASS, (uint16_t) (depth + 1)); + superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CLASS_SUPERCLASS, (uint16_t) (depth + 1)); } else { superclass = NULL; } @@ -18798,7 +18877,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t lparen = parser->previous; - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEF_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_DEF_RECEIVER, (uint16_t) (depth + 1)); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN); @@ -18920,12 +18999,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_do_loop_stack_push(parser, false); statements = UP(pm_statements_node_create(parser)); - bool allow_command_call; + uint8_t allow_flags; if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) { - allow_command_call = accepts_command_call; + allow_flags = flags & PM_PARSE_ACCEPTS_COMMAND_CALL; } else { // Allow `def foo = puts "Hello"` but not `private def foo = puts "Hello"` - allow_command_call = binding_power == PM_BINDING_POWER_ASSIGNMENT || binding_power < PM_BINDING_POWER_COMPOSITION; + allow_flags = (binding_power == PM_BINDING_POWER_ASSIGNMENT || binding_power < PM_BINDING_POWER_COMPOSITION) ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0; } // Inside a def body, we push true onto the @@ -18937,10 +19016,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // is not consumed inside the endless def body and instead // left for the outer context. pm_accepts_block_stack_push(parser, true); - bool previous_in_endless_def_body = parser->in_endless_def_body; - parser->in_endless_def_body = true; - pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_command_call, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); - parser->in_endless_def_body = previous_in_endless_def_body; + pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_flags | PM_PARSE_IN_ENDLESS_DEF, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); // If an unconsumed PM_TOKEN_KEYWORD_DO follows the body, @@ -18958,12 +19034,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b context_push(parser, PM_CONTEXT_RESCUE_MODIFIER); pm_token_t rescue_keyword = parser->previous; - pm_node_t *value = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + + // In the Ruby grammar, the rescue value of an endless + // method command excludes and/or and in/=>. + pm_node_t *value = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); statement = UP(pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value)); } + // A nested endless def whose body is a command call (e.g., + // `def f = def g = foo bar`) is a command assignment and + // cannot appear as a def body. + if (PM_NODE_TYPE_P(statement, PM_DEF_NODE) && pm_command_call_value_p(statement)) { + PM_PARSER_ERR_NODE_FORMAT(parser, statement, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + } + pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement, false); pm_do_loop_stack_pop(parser); context_pop(parser); @@ -19046,7 +19132,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b expression = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0)); lparen = (pm_token_t) { 0 }; } else { - expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); + expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); if (!parser->recovering) { accept1(parser, PM_TOKEN_NEWLINE); @@ -19055,7 +19141,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } } else { - expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); + expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1)); } context_pop(parser); @@ -19104,12 +19190,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *name = NULL; if (token_begins_expression_p(parser->current.type)) { - name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + name = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } index = UP(pm_splat_node_create(parser, &star_operator, name)); } else if (token_begins_expression_p(parser->current.type)) { - index = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); + index = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1)); } else { pm_parser_err_token(parser, &for_keyword, PM_ERR_FOR_INDEX); index = UP(pm_missing_node_create(parser, PM_TOKEN_START(parser, &for_keyword), PM_TOKEN_LENGTH(&for_keyword))); @@ -19128,7 +19214,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b expect1(parser, PM_TOKEN_KEYWORD_IN, PM_ERR_FOR_IN); pm_token_t in_keyword = parser->previous; - pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_FOR_COLLECTION, (uint16_t) (depth + 1)); + pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_FOR_COLLECTION, (uint16_t) (depth + 1)); pm_do_loop_stack_pop(parser); pm_token_t do_keyword = { 0 }; @@ -19199,8 +19285,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // where it would be parsed as an expression (i.e., at or below // the `not` binding power level). In other contexts (e.g., method // arguments, array elements, assignment right-hand sides), - // parentheses are required: `not(x)`. - if (binding_power > PM_BINDING_POWER_NOT && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { + // parentheses are required: `not(x)`. An exception is made for + // endless def bodies, where `not` is valid as both `arg` and + // `command` (e.g., `def f = not 1`, `def f = not foo bar`). + if (binding_power > PM_BINDING_POWER_NOT && !(flags & PM_PARSE_IN_ENDLESS_DEF) && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) { if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES)) { pm_parser_err(parser, PM_TOKEN_END(parser, &parser->previous), 1, PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN); } else { @@ -19220,7 +19308,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b receiver = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0)); } else { arguments.opening_loc = TOK2LOC(parser, &lparen); - receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); + receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_PARSE_ACCEPTS_COMMAND_CALL | PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); if (!parser->recovering) { accept1(parser, PM_TOKEN_NEWLINE); @@ -19229,7 +19317,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } } } else { - receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); + receiver = parse_expression(parser, PM_BINDING_POWER_NOT, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); } return UP(pm_call_node_not_create(parser, receiver, &message, &arguments)); @@ -19248,7 +19336,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t module_keyword = parser->previous; - pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_MODULE_NAME, (uint16_t) (depth + 1)); + pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_MODULE_NAME, (uint16_t) (depth + 1)); pm_token_t name; // If we can recover from a syntax error that occurred while parsing @@ -19339,7 +19427,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); pm_do_loop_stack_pop(parser); context_pop(parser); @@ -19372,7 +19460,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); pm_do_loop_stack_pop(parser); context_pop(parser); @@ -19975,7 +20063,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *name = NULL; if (token_begins_expression_p(parser->current.type)) { - name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); + name = parse_expression(parser, PM_BINDING_POWER_INDEX, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1)); } pm_node_t *splat = UP(pm_splat_node_create(parser, &operator, name)); @@ -19994,7 +20082,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (binding_power < PM_BINDING_POWER_MATCH ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!"); pm_conditional_predicate(parser, receiver, PM_CONDITIONAL_PREDICATE_TYPE_NOT); @@ -20007,7 +20095,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~"); return UP(node); @@ -20019,7 +20107,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@"); return UP(node); @@ -20028,11 +20116,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); if (accept1(parser, PM_TOKEN_STAR_STAR)) { pm_token_t exponent_operator = parser->previous; - pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, false, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); + pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1)); node = UP(pm_call_node_binary_create(parser, node, &exponent_operator, exponent, 0)); node = UP(pm_call_node_unary_create(parser, &operator, node, "-@")); } else { @@ -20140,13 +20228,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; - pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); + pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1)); pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@"); return UP(node); } case PM_TOKEN_STRING_BEGIN: - return parse_strings(parser, NULL, accepts_label, (uint16_t) (depth + 1)); + return parse_strings(parser, NULL, flags & PM_PARSE_ACCEPTS_LABEL, (uint16_t) (depth + 1)); case PM_TOKEN_SYMBOL_BEGIN: { pm_lex_mode_t lex_mode = *parser->lex_modes.current; parser_lex(parser); @@ -20194,8 +20282,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b * or any of the binary operators that can be written to a variable. */ static pm_node_t * -parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) { - pm_node_t *value = parse_value_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, false, diag_id, (uint16_t) (depth + 1)); +parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { + pm_node_t *value = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? (flags & PM_PARSE_ACCEPTS_COMMAND_CALL) : (previous_binding_power < PM_BINDING_POWER_MATCH ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0)), diag_id, (uint16_t) (depth + 1)); + + // Assignments whose value is a command call (e.g., a = b c) can only + // be followed by modifiers (if/unless/while/until/rescue) and not by + // operators with higher binding power. If we find one, emit an error + // and skip the operator and its right-hand side. + if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER && (pm_command_call_value_p(value) || pm_block_call_p(value))) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + parser_lex(parser); + parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + } // Contradicting binding powers, the right-hand-side value of the assignment // allows the `rescue` modifier. @@ -20205,7 +20303,7 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ pm_token_t rescue = parser->current; parser_lex(parser); - pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); @@ -20263,17 +20361,20 @@ parse_assignment_value_local(pm_parser_t *parser, const pm_node_t *node) { * operator that allows multiple values after it. */ static pm_node_t * -parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) { +parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { bool permitted = true; if (previous_binding_power != PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_USTAR)) permitted = false; - pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MODIFIER, diag_id, (uint16_t) (depth + 1)); + pm_node_t *value = parse_starred_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? (flags & PM_PARSE_ACCEPTS_COMMAND_CALL) : (previous_binding_power < PM_BINDING_POWER_MODIFIER ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0)), diag_id, (uint16_t) (depth + 1)); if (!permitted) pm_parser_err_node(parser, value, PM_ERR_UNEXPECTED_MULTI_WRITE); parse_assignment_value_local(parser, value); bool single_value = true; - if (previous_binding_power == PM_BINDING_POWER_STATEMENT && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) { + // Block calls (command call + do block, e.g., `foo bar do end`) cannot + // be followed by a comma to form a multi-value RHS because each element + // of a multi-value assignment must be an `arg`, not a `block_call`. + if (previous_binding_power == PM_BINDING_POWER_STATEMENT && !pm_block_call_p(value) && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) { single_value = false; pm_array_node_t *array = pm_array_node_create(parser, NULL); @@ -20290,6 +20391,16 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } + // Assignments whose value is a command call (e.g., a = b c) can only + // be followed by modifiers (if/unless/while/until/rescue) and not by + // operators with higher binding power. If we find one, emit an error + // and skip the operator and its right-hand side. + if (single_value && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER && (pm_command_call_value_p(value) || pm_block_call_p(value))) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + parser_lex(parser); + parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + } + // Contradicting binding powers, the right-hand-side value of the assignment // allows the `rescue` modifier. if ((single_value || (binding_power == (PM_BINDING_POWER_MULTI_ASSIGNMENT + 1))) && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { @@ -20309,7 +20420,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } - pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, accepts_command_call_inner, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (accepts_command_call_inner ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); @@ -20610,7 +20721,7 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t * } static inline pm_node_t * -parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, uint16_t depth) { +parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, uint8_t flags, uint16_t depth) { pm_token_t token = parser->current; switch (token.type) { @@ -20636,7 +20747,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parser_lex(parser); - pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); if (PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) && previous_binding_power != PM_BINDING_POWER_STATEMENT) { pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_MULTI_WRITE); @@ -20649,7 +20760,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_multi_target_node_targets_append(parser, multi_target, node); parser_lex(parser); - pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); return parse_write(parser, UP(multi_target), &token, value); } case PM_SOURCE_ENCODING_NODE: @@ -20662,7 +20773,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // In these special cases, we have specific error messages // and we will replace them with local variable writes. parser_lex(parser); - pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1)); return parse_unwriteable_write(parser, node, &token, value); } default: @@ -20683,7 +20794,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_GLOBAL_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_and_write_node_create(parser, node, &token, value)); return result; @@ -20691,7 +20802,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); return result; @@ -20699,7 +20810,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_PATH_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20707,7 +20818,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20715,7 +20826,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_INSTANCE_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); return result; @@ -20724,7 +20835,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); @@ -20739,7 +20850,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth)); return result; @@ -20755,7 +20866,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_constant_id_t constant_id = pm_parser_local_add_location(parser, &cast->message_loc, 1); parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); return result; @@ -20769,7 +20880,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // this is an aref expression, and we can transform it into // an aset expression. if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) { - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); return UP(pm_index_and_write_node_create(parser, cast, &token, value)); } @@ -20781,7 +20892,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parse_call_operator_write(parser, cast, &token); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1)); return UP(pm_call_and_write_node_create(parser, cast, &token, value)); } case PM_MULTI_WRITE_NODE: { @@ -20808,7 +20919,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_GLOBAL_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_or_write_node_create(parser, node, &token, value)); return result; @@ -20816,7 +20927,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); return result; @@ -20824,7 +20935,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_PATH_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20832,7 +20943,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20840,7 +20951,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_INSTANCE_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); return result; @@ -20849,7 +20960,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); @@ -20864,7 +20975,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth)); return result; @@ -20880,7 +20991,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_constant_id_t constant_id = pm_parser_local_add_location(parser, &cast->message_loc, 1); parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); return result; @@ -20894,7 +21005,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // this is an aref expression, and we can transform it into // an aset expression. if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) { - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); return UP(pm_index_or_write_node_create(parser, cast, &token, value)); } @@ -20906,7 +21017,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parse_call_operator_write(parser, cast, &token); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1)); return UP(pm_call_or_write_node_create(parser, cast, &token, value)); } case PM_MULTI_WRITE_NODE: { @@ -20943,7 +21054,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_GLOBAL_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_global_variable_operator_write_node_create(parser, node, &token, value)); return result; @@ -20951,7 +21062,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value)); return result; @@ -20959,7 +21070,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_PATH_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20967,7 +21078,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_CONSTANT_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *write = UP(pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value)); return parse_shareable_constant_write(parser, write); @@ -20975,7 +21086,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_INSTANCE_VARIABLE_READ_NODE: { parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value)); return result; @@ -20984,7 +21095,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2); parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, name, 0)); pm_node_unreference(parser, node); @@ -20999,7 +21110,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node; parser_lex(parser); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth)); return result; @@ -21014,7 +21125,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { pm_refute_numbered_parameter(parser, cast->message_loc.start, cast->message_loc.length); pm_constant_id_t constant_id = pm_parser_local_add_location(parser, &cast->message_loc, 1); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, UP(cast), &token, value, constant_id, 0)); return result; @@ -21024,7 +21135,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // this is an aref expression, and we can transform it into // an aset expression. if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) { - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_index_operator_write_node_create(parser, cast, &token, value)); } @@ -21036,7 +21147,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parse_call_operator_write(parser, cast, &token); - pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, flags, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_call_operator_write_node_create(parser, cast, &token, value)); } case PM_MULTI_WRITE_NODE: { @@ -21058,14 +21169,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_TOKEN_KEYWORD_AND: { parser_lex(parser); - pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_AND, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (parser->previous.type == PM_TOKEN_KEYWORD_AND ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_and_node_create(parser, node, &token, right)); } case PM_TOKEN_KEYWORD_OR: case PM_TOKEN_PIPE_PIPE: { parser_lex(parser); - pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_OR, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (parser->previous.type == PM_TOKEN_KEYWORD_OR ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_or_node_create(parser, node, &token, right)); } case PM_TOKEN_EQUAL_TILDE: { @@ -21077,7 +21188,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // // In this case, `foo` should be a method call and not a local yet. parser_lex(parser); - pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *argument = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); // By default, we're going to create a call node and then return it. pm_call_node_t *call = pm_call_node_binary_create(parser, node, &token, argument, 0); @@ -21183,7 +21294,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t break; } - pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *argument = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_call_node_binary_create(parser, node, &token, argument, 0)); } case PM_TOKEN_GREATER: @@ -21195,7 +21306,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } parser_lex(parser); - pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + pm_node_t *argument = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); return UP(pm_call_node_binary_create(parser, node, &token, argument, PM_CALL_NODE_FLAGS_COMPARISON)); } case PM_TOKEN_AMPERSAND_DOT: @@ -21254,7 +21365,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } } - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); pm_call_node_t *call = pm_call_node_call_create(parser, node, &operator, &message, &arguments); if ( @@ -21274,7 +21385,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_node_t *right = NULL; if (token_begins_expression_p(parser->current.type)) { - right = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); + right = parse_expression(parser, binding_power, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); } return UP(pm_range_node_create(parser, node, &token, right)); @@ -21283,14 +21394,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_token_t keyword = parser->current; parser_lex(parser); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1)); return UP(pm_if_node_modifier_create(parser, node, &keyword, predicate)); } case PM_TOKEN_KEYWORD_UNLESS_MODIFIER: { pm_token_t keyword = parser->current; parser_lex(parser); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1)); return UP(pm_unless_node_modifier_create(parser, node, &keyword, predicate)); } case PM_TOKEN_KEYWORD_UNTIL_MODIFIER: { @@ -21298,7 +21409,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, node, true); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1)); return UP(pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0)); } case PM_TOKEN_KEYWORD_WHILE_MODIFIER: { @@ -21306,7 +21417,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_statements_node_t *statements = pm_statements_node_create(parser); pm_statements_node_body_append(parser, statements, node, true); - pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); + pm_node_t *predicate = parse_value_expression(parser, binding_power, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1)); return UP(pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0)); } case PM_TOKEN_QUESTION_MARK: { @@ -21317,7 +21428,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_token_t qmark = parser->current; parser_lex(parser); - pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_TERNARY_EXPRESSION_TRUE, (uint16_t) (depth + 1)); + pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_TERNARY_EXPRESSION_TRUE, (uint16_t) (depth + 1)); if (parser->recovering) { // If parsing the true expression of this ternary resulted in a syntax @@ -21338,7 +21449,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t expect1(parser, PM_TOKEN_COLON, PM_ERR_TERNARY_COLON); pm_token_t colon = parser->previous; - pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_TERNARY_EXPRESSION_FALSE, (uint16_t) (depth + 1)); + pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_TERNARY_EXPRESSION_FALSE, (uint16_t) (depth + 1)); context_pop(parser); pop_block_exits(parser, previous_block_exits); @@ -21355,7 +21466,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if ( (parser->current.type == PM_TOKEN_PARENTHESIS_LEFT) || - (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) + ((flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) ) { // If we have a constant immediately following a '::' operator, then // this can either be a constant path or a method call, depending on @@ -21366,7 +21477,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_token_t message = parser->previous; pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); path = UP(pm_call_node_call_create(parser, node, &delimiter, &message, &arguments)); } else { // Otherwise, this is a constant path. That would look like Foo::Bar. @@ -21390,7 +21501,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // If we have an identifier following a '::' operator, then it is for // sure a method call. pm_arguments_t arguments = { 0 }; - parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1)); + parse_arguments_list(parser, &arguments, true, flags, (uint16_t) (depth + 1)); pm_call_node_t *call = pm_call_node_call_create(parser, node, &delimiter, &message, &arguments); // If this is followed by a comma then it is a multiple assignment. @@ -21419,7 +21530,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t parser_lex(parser); accept1(parser, PM_TOKEN_NEWLINE); - pm_node_t *value = parse_expression(parser, binding_power, true, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *value = parse_expression(parser, binding_power, (uint8_t) ((flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, node, &token, value)); @@ -21432,7 +21543,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) { pm_accepts_block_stack_push(parser, true); - parse_arguments(parser, &arguments, false, PM_TOKEN_BRACKET_RIGHT, (uint16_t) (depth + 1)); + parse_arguments(parser, &arguments, false, PM_TOKEN_BRACKET_RIGHT, (uint8_t) (flags & ~PM_PARSE_ACCEPTS_DO_BLOCK), (uint16_t) (depth + 1)); pm_accepts_block_stack_pop(parser); expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_EXPECT_RBRACKET); } @@ -21514,16 +21625,83 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t #undef PM_PARSE_PATTERN_MULTI /** - * Determine if a given call node looks like a "command", which means it has - * arguments but does not have parentheses. + * Some nodes act as statements and limit which operators can follow. This + * function inspects the node and the upcoming token to determine whether the + * expression loop should stop. It is called both after prefix parsing and after + * each infix operator. + * + * As a side effect, this function also attaches do-blocks to command-style call + * nodes when appropriate. + * + * Returns true if the expression loop should stop (i.e., the next operator + * should not be consumed). */ -static inline bool -pm_call_node_command_p(const pm_call_node_t *node) { - return ( - (node->opening_loc.length == 0) && - (node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE)) && - (node->arguments != NULL || node->block != NULL) - ); +static bool +parse_expression_terminator(pm_parser_t *parser, pm_node_t *node) { + pm_binding_power_t left = pm_binding_powers[parser->current.type].left; + + switch (PM_NODE_TYPE(node)) { + case PM_MULTI_WRITE_NODE: + case PM_RETURN_NODE: + case PM_BREAK_NODE: + case PM_NEXT_NODE: + return left > PM_BINDING_POWER_MODIFIER; + case PM_CLASS_VARIABLE_WRITE_NODE: + case PM_CONSTANT_PATH_WRITE_NODE: + case PM_CONSTANT_WRITE_NODE: + case PM_GLOBAL_VARIABLE_WRITE_NODE: + case PM_INSTANCE_VARIABLE_WRITE_NODE: + case PM_LOCAL_VARIABLE_WRITE_NODE: + return PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && left > PM_BINDING_POWER_MODIFIER; + case PM_CALL_NODE: { + // Calls with an implicit array on the right-hand side are + // statements and can only be followed by modifiers. + if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY)) { + return left > PM_BINDING_POWER_MODIFIER; + } + + // Command-style calls (including block commands like + // `foo bar do end`) can only be followed by composition + // (and/or) and modifier (if/unless/etc.) operators. + if (pm_command_call_value_p(node)) { + return left > PM_BINDING_POWER_COMPOSITION; + } + + // A block call (command with do-block, or any call chained + // from one) can only be followed by call chaining (., ::, + // &.), composition (and/or), and modifier operators. + if (pm_block_call_p(node)) { + return left > PM_BINDING_POWER_COMPOSITION && left < PM_BINDING_POWER_CALL; + } + + return false; + } + case PM_SUPER_NODE: + case PM_YIELD_NODE: + // Command-style super/yield (without parens) can only be followed + // by composition and modifier operators. + if (pm_command_call_value_p(node)) { + return left > PM_BINDING_POWER_COMPOSITION; + } + return false; + case PM_DEF_NODE: + // An endless method whose body is a command-style call (e.g., + // `def f = foo bar`) is a command assignment and can only be + // followed by modifiers. + return left > PM_BINDING_POWER_MODIFIER && pm_command_call_value_p(node); + case PM_RESCUE_MODIFIER_NODE: + // A rescue modifier whose handler is a pattern match (=> or in) + // produces a statement and cannot be followed by operators above + // the modifier level. + if (left > PM_BINDING_POWER_MODIFIER) { + pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; + pm_node_t *rescue_expression = cast->rescue_expression; + return PM_NODE_TYPE_P(rescue_expression, PM_MATCH_REQUIRED_NODE) || PM_NODE_TYPE_P(rescue_expression, PM_MATCH_PREDICATE_NODE); + } + return false; + default: + return false; + } } /** @@ -21535,53 +21713,39 @@ pm_call_node_command_p(const pm_call_node_t *node) { * determine if they need to perform additional cleanup. */ static pm_node_t * -parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) { +parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { if (PRISM_UNLIKELY(depth >= PRISM_DEPTH_MAXIMUM)) { pm_parser_err_current(parser, PM_ERR_NESTING_TOO_DEEP); return UP(pm_missing_node_create(parser, PM_TOKEN_START(parser, &parser->current), PM_TOKEN_LENGTH(&parser->current))); } - pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth); + pm_node_t *node = parse_expression_prefix(parser, binding_power, flags, diag_id, depth); + // Some prefix nodes are statements and can only be followed by modifiers + // (if/unless/while/until/rescue) or nothing at all. We check these cheaply + // here before entering the infix loop. switch (PM_NODE_TYPE(node)) { case PM_MISSING_NODE: - // If we found a syntax error, then the type of node returned by - // parse_expression_prefix is going to be a missing node. return node; case PM_PRE_EXECUTION_NODE: + return node; case PM_POST_EXECUTION_NODE: case PM_ALIAS_GLOBAL_VARIABLE_NODE: case PM_ALIAS_METHOD_NODE: - case PM_MULTI_WRITE_NODE: case PM_UNDEF_NODE: - // These expressions are statements, and cannot be followed by - // operators (except modifiers). if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { return node; } break; case PM_CALL_NODE: - // A do-block can attach to a command-style call at the - // primary level. Inside an endless def body, DO_BLOCK must - // not be consumed so it can bubble up to the outer context - // (e.g., `private` in `private def f = bar baz do end`). - if (match1(parser, PM_TOKEN_KEYWORD_DO_BLOCK) && !parser->in_endless_def_body && pm_accepts_block_stack_p(parser) && pm_call_node_command_p((pm_call_node_t *) node)) { - parse_command_do_block(parser, (pm_call_node_t *) node, depth); - } - - // If we have a call node, then we need to check if it looks like a - // method call without parentheses that contains arguments. If it - // does, then it has different rules for parsing infix operators, - // namely that it only accepts composition (and/or) and modifiers - // (if/unless/etc.). - if ((pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_COMPOSITION) && pm_call_node_command_p((pm_call_node_t *) node)) { + case PM_SUPER_NODE: + case PM_YIELD_NODE: + case PM_DEF_NODE: + if (parse_expression_terminator(parser, node)) { return node; } break; case PM_SYMBOL_NODE: - // If we have a symbol node that is being parsed as a label, then we - // need to immediately return, because there should never be an - // infix operator following this node. if (pm_symbol_node_label_p(parser, node)) { return node; } @@ -21590,8 +21754,8 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc break; } - // Otherwise we'll look and see if the next token can be parsed as an infix - // operator. If it can, then we'll parse it using parse_expression_infix. + // Look and see if the next token can be parsed as an infix operator. If it + // can, then we'll parse it using parse_expression_infix. pm_binding_powers_t current_binding_powers; pm_token_type_t current_token_type; @@ -21601,74 +21765,8 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc binding_power <= current_binding_powers.left && current_binding_powers.binary ) { - node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1)); - - switch (PM_NODE_TYPE(node)) { - case PM_MULTI_WRITE_NODE: - // Multi-write nodes are statements, and cannot be followed by - // operators except modifiers. - if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { - return node; - } - break; - case PM_CLASS_VARIABLE_WRITE_NODE: - case PM_CONSTANT_PATH_WRITE_NODE: - case PM_CONSTANT_WRITE_NODE: - case PM_GLOBAL_VARIABLE_WRITE_NODE: - case PM_INSTANCE_VARIABLE_WRITE_NODE: - case PM_LOCAL_VARIABLE_WRITE_NODE: - // These expressions are statements, by virtue of the right-hand - // side of their write being an implicit array. - if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { - return node; - } - break; - case PM_CALL_NODE: { - // A do-block can attach to a command-style call - // produced by infix operators (e.g., dot-calls like - // `obj.method args do end`). - if (match1(parser, PM_TOKEN_KEYWORD_DO_BLOCK) && !parser->in_endless_def_body && pm_accepts_block_stack_p(parser) && pm_call_node_command_p((pm_call_node_t *) node)) { - parse_command_do_block(parser, (pm_call_node_t *) node, depth); - } - - // These expressions are also statements, by virtue of the - // right-hand side of the expression (i.e., the last argument to - // the call node) being an implicit array. - if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { - return node; - } - - // Command-style calls (calls with arguments but without - // parentheses) only accept composition (and/or) and modifier - // (if/unless/etc.) operators. We need to exclude operator calls - // (e.g., a + b) which also satisfy pm_call_node_command_p but - // are not commands. - const pm_call_node_t *cast = (const pm_call_node_t *) node; - if ( - (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_COMPOSITION) && - (cast->receiver == NULL || cast->call_operator_loc.length > 0) && - pm_call_node_command_p(cast) - ) { - return node; - } - break; - } - case PM_RESCUE_MODIFIER_NODE: - // A rescue modifier whose handler is a one-liner pattern match - // (=> or in) produces a statement. That means it cannot be - // extended by operators above the modifier level. - if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { - pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; - pm_node_t *rescue_expression = cast->rescue_expression; - - if (PM_NODE_TYPE_P(rescue_expression, PM_MATCH_REQUIRED_NODE) || PM_NODE_TYPE_P(rescue_expression, PM_MATCH_PREDICATE_NODE)) { - return node; - } - } - break; - default: - break; - } + node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, flags, (uint16_t) (depth + 1)); + if (parse_expression_terminator(parser, node)) return node; // If the operator is nonassoc and we should not be able to parse the // upcoming infix operator, break. @@ -21701,7 +21799,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc } } - if (accepts_command_call) { + if (flags & PM_PARSE_ACCEPTS_COMMAND_CALL) { // A command-style method call is only accepted on method chains. // Thus, we check whether the parsed node can continue method chains. // The method chain can continue if the parsed node is one of the following five kinds: @@ -21738,7 +21836,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc cast->block != NULL && PM_NODE_TYPE_P(cast->block, PM_BLOCK_NODE) ) ) { - accepts_command_call = false; + flags &= (uint8_t) ~PM_PARSE_ACCEPTS_COMMAND_CALL; } break; } @@ -21746,7 +21844,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc case PM_CONSTANT_PATH_NODE: break; default: - accepts_command_call = false; + flags &= (uint8_t) ~PM_PARSE_ACCEPTS_COMMAND_CALL; break; } } diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt index 2fdcf09738..2b7286abc3 100644 --- a/test/prism/errors/command_call_in.txt +++ b/test/prism/errors/command_call_in.txt @@ -2,4 +2,5 @@ foo 1 in a ^~ unexpected 'in', expecting end-of-input ^~ unexpected 'in', ignoring it a = foo 2 in b + ^~ unexpected 'in', expecting end-of-input diff --git a/test/prism/errors/command_call_value_and.txt b/test/prism/errors/command_call_value_and.txt new file mode 100644 index 0000000000..a131aa5530 --- /dev/null +++ b/test/prism/errors/command_call_value_and.txt @@ -0,0 +1,3 @@ +a = b c and 1 + ^~~ unexpected 'and', expecting end-of-input + diff --git a/test/prism/errors/command_call_value_or.txt b/test/prism/errors/command_call_value_or.txt new file mode 100644 index 0000000000..cc75714166 --- /dev/null +++ b/test/prism/errors/command_call_value_or.txt @@ -0,0 +1,3 @@ +a = b c or 1 + ^~ unexpected 'or', expecting end-of-input + diff --git a/test/prism/errors/command_calls_34.txt b/test/prism/errors/command_calls_34.txt index ce62bc1492..bc0ea5e81c 100644 --- a/test/prism/errors/command_calls_34.txt +++ b/test/prism/errors/command_calls_34.txt @@ -1,12 +1,19 @@ foo(bar 1 do end, 2) - ^ invalid comma - ^ unexpected integer; expected a `)` to close the arguments - ^ unexpected integer, expecting end-of-input + ^~ unexpected 'do'; expected a `)` to close the arguments + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', ignoring it + ^ unexpected ',', ignoring it ^ unexpected ')', expecting end-of-input ^ unexpected ')', ignoring it foo(bar 1 do end,) - ^ invalid comma + ^~ unexpected 'do'; expected a `)` to close the arguments + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', ignoring it + ^ unexpected ',', ignoring it + ^ unexpected ')', ignoring it foo(1, bar 2 do end) ^ unexpected integer; expected a `)` to close the arguments diff --git a/test/prism/errors/command_calls_35.txt b/test/prism/errors/command_calls_35.txt index 45f569b117..bd72d1be56 100644 --- a/test/prism/errors/command_calls_35.txt +++ b/test/prism/errors/command_calls_35.txt @@ -14,7 +14,11 @@ p(p a, &block => value) ^ unexpected ')', ignoring it p(p a do end => value) - ^~ unexpected '=>'; expected a `)` to close the arguments + ^~ unexpected 'do'; expected a `)` to close the arguments + ^~ unexpected 'do', expecting end-of-input + ^~ unexpected 'do', ignoring it + ^~~ unexpected 'end', ignoring it + ^~ unexpected '=>', ignoring it ^ unexpected ')', expecting end-of-input ^ unexpected ')', ignoring it diff --git a/test/prism/errors/destroy_call_operator_write_arguments.txt b/test/prism/errors/destroy_call_operator_write_arguments.txt index c3c72f9226..b6933d61d1 100644 --- a/test/prism/errors/destroy_call_operator_write_arguments.txt +++ b/test/prism/errors/destroy_call_operator_write_arguments.txt @@ -2,9 +2,9 @@ t next&&do end&= ^~ unexpected 'do'; expected an expression after the operator ^~~~ unexpected void value expression ^~~~ unexpected void value expression -^~~~~~~~~~~~~~ unexpected write target - ^~ unexpected operator after a call with arguments - ^~ unexpected operator after a call with a block + ^~ unexpected '&=', expecting end-of-input + ^~ unexpected '&=', ignoring it + ^~~~ Invalid next ''while= ^~~~~ expected a predicate expression for the `while` statement ^ unexpected '='; target cannot be written diff --git a/test/prism/fixtures/command_method_call_2.txt b/test/prism/fixtures/command_method_call_2.txt index 165c45987a..8bd40cff9e 100644 --- a/test/prism/fixtures/command_method_call_2.txt +++ b/test/prism/fixtures/command_method_call_2.txt @@ -1,3 +1 @@ -foo(bar baz do end) - foo(bar baz, bat) From 979251ef064409586de96506d905f4af3f3b56e8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 09:15:48 -0400 Subject: [PATCH 101/289] Fix pinned expression binding power --- src/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prism.c b/src/prism.c index 3b2b03cdd5..0cf1bf771d 100644 --- a/src/prism.c +++ b/src/prism.c @@ -16830,7 +16830,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm pm_token_t lparen = parser->current; parser_lex(parser); - pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1)); + pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1)); parser->pattern_matching_newlines = previous_pattern_matching_newlines; accept1(parser, PM_TOKEN_NEWLINE); From 7e797f59ae083e34d3e08e7e89dbc5422defd5e2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 09:28:53 -0400 Subject: [PATCH 102/289] Fix not binding power in endless methods [Bug #21097] Also, parse: ``` x = a rescue b in c ``` as: ``` (x = (a rescue b)) in c ``` and: ``` def f = a rescue b in c ``` as: ``` (def f = (a rescue b)) in c ``` --- src/prism.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/prism.c b/src/prism.c index 3b2b03cdd5..42d311f751 100644 --- a/src/prism.c +++ b/src/prism.c @@ -19317,7 +19317,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u } } } else { - receiver = parse_expression(parser, PM_BINDING_POWER_NOT, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); + /* `not` in a single line method is allowed to be followed by + * an expression without pattern matching, that optionally is + * followed by a `rescue` modifier. */ + if (flags & PM_PARSE_IN_ENDLESS_DEF) { + receiver = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); + + if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { + context_push(parser, PM_CONTEXT_RESCUE_MODIFIER); + pm_token_t rescue_keyword = parser->previous; + pm_node_t *value = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + context_pop(parser); + receiver = UP(pm_rescue_modifier_node_create(parser, receiver, &rescue_keyword, value)); + } + } else { + receiver = parse_expression(parser, PM_BINDING_POWER_NOT, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); + } } return UP(pm_call_node_not_create(parser, receiver, &message, &arguments)); @@ -20303,7 +20318,7 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ pm_token_t rescue = parser->current; parser_lex(parser); - pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); @@ -20420,7 +20435,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } - pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (accepts_command_call_inner ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (accepts_command_call_inner ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); From e08b47e26ce65d6a12bc9d64f53585acf6a01cec Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 10 Mar 2026 15:21:14 +0100 Subject: [PATCH 103/289] Make it possible to lazily deserialize DefNode in Loader.java * TRUFFLERUBY_METRICS_REPS=5 jt metrics time --experimental-options -e0 For parsing-core: before: 0.097 0.099 0.092 0.096 after: 0.061 0.063 0.066 0.059 * Remove extra trailing spaces by using `<%-#`. --- .../java/org/ruby_lang/prism/Loader.java.erb | 49 ++++++++++++++++--- .../java/org/ruby_lang/prism/Nodes.java.erb | 30 ++++++++++-- templates/src/serialize.c.erb | 4 +- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 3c2a0cfd09..91ec49b70c 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -16,7 +16,7 @@ import java.util.Locale; public class Loader { public static ParseResult load(byte[] serialized, byte[] sourceBytes) { - return new Loader(serialized, sourceBytes).load(); + return new Loader(serialized).load(sourceBytes); } // Overridable methods @@ -71,19 +71,21 @@ public class Loader { } private final ByteBuffer buffer; - private final Nodes.Source source; protected String encodingName; <%- if string_type == "String" -%> private Charset encodingCharset; <%- end -%> private ConstantPool constantPool; - protected Loader(byte[] serialized, byte[] sourceBytes) { + protected Loader(byte[] serialized) { this.buffer = ByteBuffer.wrap(serialized).order(ByteOrder.nativeOrder()); - this.source = new Nodes.Source(sourceBytes); } - protected ParseResult load() { + // We pass sourceBytes here and not in the constructor to avoid keeping + // the sourceBytes in memory unnecessarily with lazy DefNode's which hold on the Loader. + protected ParseResult load(byte[] sourceBytes) { + Nodes.Source source = new Nodes.Source(sourceBytes); + expect((byte) 'P', "incorrect prism header"); expect((byte) 'R', "incorrect prism header"); expect((byte) 'I', "incorrect prism header"); @@ -331,6 +333,10 @@ public class Loader { return negative ? result.negate() : result; } + <%- + base_params = [*("nodeId" if Prism::Template::INCLUDE_NODE_ID), "startOffset", "length"] + base_params_sig = base_params.map { "int #{_1}" }.join(", ") + -%> private Nodes.Node loadNode() { int type = buffer.get() & 0xFF; <%- if Prism::Template::INCLUDE_NODE_ID -%> @@ -347,7 +353,7 @@ public class Loader { params = [] params << "nodeId" if Prism::Template::INCLUDE_NODE_ID params << "startOffset" << "length" - params << "buffer.getInt()" if node.needs_serialized_length? + params << "buffer.getInt()" << "null" if node.needs_serialized_length? params << "loadFlags()" if node.flags params.concat node.semantic_fields.map { |field| case field @@ -370,13 +376,44 @@ public class Loader { else raise end } + $DefNode_params = params if node.name == "DefNode" -%> + <%- if node.name == "DefNode" -%> + return loadDefNode(<%= base_params.join(", ") -%>); + <%- else -%> return new Nodes.<%= node.name %>(<%= params.join(", ") -%>); + <%- end -%> <%- end -%> default: throw new Error("Unknown node type: " + type); } } + + // Can be overridden to use createLazyDefNode instead + protected Nodes.DefNode loadDefNode(<%= base_params_sig -%>) { + return createDefNode(<%= base_params.join(", ") -%>); + } + + protected Nodes.DefNode createLazyDefNode(<%= base_params_sig -%>) { + int bufferPosition = buffer.position(); + int serializedLength = buffer.getInt(); + // Load everything except the body and locals, because the name, receiver, parameters are still needed for lazily defining the method + Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_STRING_ARRAY); + buffer.position(bufferPosition + serializedLength); // skip past the serialized DefNode + return lazyDefNode; + } + + protected Nodes.DefNode createDefNode(<%= base_params_sig -%>) { + return new Nodes.DefNode(<%= $DefNode_params.join(", ") -%>); + } + + Nodes.DefNode createDefNodeFromSavedPosition(<%= base_params_sig -%>, int bufferPosition) { + // This method mutates the buffer position and may be called from different threads so we must synchronize + synchronized (this) { + buffer.position(bufferPosition); + return createDefNode(<%= base_params.join(", ") -%>); + } + } <%- array_types.uniq.each do |type| -%> private static final Nodes.<%= type %>[] EMPTY_<%= type %>_ARRAY = {}; diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index 47b2ea0a7e..e234faa6f5 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -142,7 +142,7 @@ public abstract class Nodes { protected abstract String toString(String indent); } -<%# FLAGS -%> +<%-# FLAGS -%> <%- flags.each do |flag| -%> /** @@ -194,7 +194,7 @@ public abstract class Nodes { <%- end -%> } <%- end -%> -<%# NODES -%> +<%-# NODES -%> <%- nodes.each do |node| -%> /** @@ -207,6 +207,7 @@ public abstract class Nodes { public static final class <%= node.name -%> extends Node { <%- if node.needs_serialized_length? -%> public final int serializedLength; + public final Loader loader; <%- end -%> <%- if node.flags -%> public final short flags; @@ -234,7 +235,10 @@ public abstract class Nodes { params = [] params << "int nodeId" if Prism::Template::INCLUDE_NODE_ID params << "int startOffset" << "int length" - params << "int serializedLength" if node.needs_serialized_length? + if node.needs_serialized_length? + params << "int serializedLength" + params << "Loader loader" + end params << "short flags" if node.flags params.concat(node.semantic_fields.map { |field| "#{field.java_type} #{field.name}" }) -%> @@ -246,6 +250,7 @@ public abstract class Nodes { <%- end -%> <%- if node.needs_serialized_length? -%> this.serializedLength = serializedLength; + this.loader = loader; <%- end -%> <%- if node.flags -%> this.flags = flags; @@ -254,7 +259,22 @@ public abstract class Nodes { this.<%= field.name %> = <%= field.name %>; <%- end -%> } - <%# methods for flags -%> + <%-# extra methods for DefNode -%> + <%- if node.needs_serialized_length? -%> + + public boolean isLazy() { + return serializedLength < 0; + } + + public <%= node.name -%> getNonLazy() { + if (isLazy()) { + return loader.createDefNodeFromSavedPosition(<%= "nodeId, " if Prism::Template::INCLUDE_NODE_ID %>startOffset, length, -serializedLength); + } else { + return this; + } + } + <%- end -%> + <%-# methods for flags -%> <%- if (node_flags = node.flags) -%> <%- node_flags.values.each do |value| -%> @@ -263,7 +283,7 @@ public abstract class Nodes { } <%- end -%> <%- end -%> - <%# potential override of setNewLineFlag() -%> + <%-# potential override of setNewLineFlag() -%> <%- if node.newline == false -%> @Override diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 4fe0cb88c1..75b613439c 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -50,8 +50,6 @@ static void pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_buffer_append_byte(buffer, (uint8_t) PM_NODE_TYPE(node)); - size_t offset = buffer->length; - <%- if Prism::Template::INCLUDE_NODE_ID -%> pm_buffer_append_varuint(buffer, node->node_id); <%- end -%> @@ -126,7 +124,7 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { <%- end -%> <%- if node.needs_serialized_length? -%> // serialize length - uint32_t length = pm_sizet_to_u32(buffer->length - offset - sizeof(uint32_t)); + uint32_t length = pm_sizet_to_u32(buffer->length - length_offset); memcpy(buffer->value + length_offset, &length, sizeof(uint32_t)); <%- end -%> break; From 0944c7fba294aea09b9448f84b0eca4ab74695c4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 22:32:43 -0400 Subject: [PATCH 104/289] Restructure regexp encoding validation Move all the logic from prism.c into regexp.c. Now regexp.c does two passes. The first pass scans the raw source to track escape types, non-ASCII literals, and multibyte validity for encoding validation. The second pass scans the unescaped content for named capture extraction (needed because escape sequences like line continuations alter group names). Fixed a couple of things along the way. ascii_only was previously computed from unescaped content, but we can do that as we go to avoid scanning again. Unicode properties also now properly error for regexp with modifiers. --- config.yml | 2 + include/prism/parser.h | 6 - include/prism/regexp.h | 53 +- .../seattlerb/regexp_escape_extended.txt | 2 +- src/prism.c | 370 ++----- src/regexp.c | 965 +++++++++++++++++- templates/src/diagnostic.c.erb | 6 +- .../regular_expression_encoding_test.rb | 34 +- 8 files changed, 1065 insertions(+), 373 deletions(-) diff --git a/config.yml b/config.yml index c82c239de6..1ea1bcf7f1 100644 --- a/config.yml +++ b/config.yml @@ -248,7 +248,9 @@ errors: - PATTERN_TERM_PAREN - PIPEPIPEEQ_MULTI_ASSIGN - REGEXP_ENCODING_OPTION_MISMATCH + - REGEXP_ESCAPED_NON_ASCII_IN_UTF8 - REGEXP_INCOMPAT_CHAR_ENCODING + - REGEXP_INVALID_CHAR_PROPERTY - REGEXP_INVALID_UNICODE_RANGE - REGEXP_NON_ESCAPED_MBC - REGEXP_PARSE_ERROR diff --git a/include/prism/parser.h b/include/prism/parser.h index 5ebace10c6..d8e7a550e7 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -933,12 +933,6 @@ struct pm_parser { */ bool semantic_token_seen; - /** - * True if the current regular expression being lexed contains only ASCII - * characters. - */ - bool current_regular_expression_ascii_only; - /** * By default, Ruby always warns about mismatched indentation. This can be * toggled with a magic comment. diff --git a/include/prism/regexp.h b/include/prism/regexp.h index 5366b5a5a0..b3e739b457 100644 --- a/include/prism/regexp.h +++ b/include/prism/regexp.h @@ -17,27 +17,56 @@ #include /** - * This callback is called by pm_regexp_parse() when a named capture group is found. + * Accumulation state for named capture groups found during regexp parsing. + * The caller initializes this with the call node and passes it to + * pm_regexp_parse. The regexp parser populates match and names as groups + * are found. */ -typedef void (*pm_regexp_name_callback_t)(const pm_string_t *name, void *data); +typedef struct { + /** The call node wrapping the regular expression node (for =~). */ + pm_call_node_t *call; + + /** The match write node being built, or NULL if no captures found yet. */ + pm_match_write_node_t *match; + + /** The list of capture names found so far (for deduplication). */ + pm_constant_id_list_t names; +} pm_regexp_name_data_t; /** - * This callback is called by pm_regexp_parse() when a parse error is found. + * Callback invoked by pm_regexp_parse() for each named capture group found. + * + * @param parser The main parser. + * @param name The name of the capture group. + * @param shared Whether the source content is shared (impacts constant storage). + * @param data The accumulation state for named captures. */ -typedef void (*pm_regexp_error_callback_t)(const uint8_t *start, const uint8_t *end, const char *message, void *data); +typedef void (*pm_regexp_name_callback_t)(pm_parser_t *parser, const pm_string_t *name, bool shared, pm_regexp_name_data_t *data); /** - * Parse a regular expression. + * Parse a regular expression, validate its encoding, and optionally extract + * named capture groups. Returns the encoding flags to set on the node. * * @param parser The parser that is currently being used. - * @param source The source code to parse. - * @param size The size of the source code. - * @param extended_mode Whether to parse the regular expression in extended mode. + * @param node The regular expression node to parse and validate. * @param name_callback The optional callback to call when a named capture group is found. - * @param name_data The optional data to pass to the name callback. - * @param error_callback The callback to call when a parse error is found. - * @param error_data The data to pass to the error callback. + * @param name_data The optional accumulation state for named captures. + * @return The encoding flags to set on the node (e.g., FORCED_UTF8_ENCODING). + */ +PRISM_EXPORTED_FUNCTION pm_node_flags_t pm_regexp_parse(pm_parser_t *parser, pm_regular_expression_node_t *node, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data); + +/** + * Parse an interpolated regular expression for named capture groups only. + * No encoding validation is performed. + * + * @param parser The parser that is currently being used. + * @param source The source content to parse. + * @param size The length of the source content. + * @param shared Whether the source points into the parser's source buffer. + * @param extended_mode Whether or not the regular expression is in extended mode. + * @param name_callback The callback to call when a named capture group is found. + * @param name_data The accumulation state for named captures. */ -PRISM_EXPORTED_FUNCTION void pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool extended_mode, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data); +void pm_regexp_parse_named_captures(pm_parser_t *parser, const uint8_t *source, size_t size, bool shared, bool extended_mode, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data); #endif diff --git a/snapshots/seattlerb/regexp_escape_extended.txt b/snapshots/seattlerb/regexp_escape_extended.txt index 732899a20d..a2e4d5eb96 100644 --- a/snapshots/seattlerb/regexp_escape_extended.txt +++ b/snapshots/seattlerb/regexp_escape_extended.txt @@ -6,7 +6,7 @@ ├── flags: ∅ └── body: (length: 1) └── @ RegularExpressionNode (location: (1,0)-(1,6)) - ├── flags: newline, static_literal + ├── flags: newline, static_literal, forced_us_ascii_encoding ├── opening_loc: (1,0)-(1,1) = "/" ├── content_loc: (1,1)-(1,5) = "\\“" ├── closing_loc: (1,5)-(1,6) = "/" diff --git a/src/prism.c b/src/prism.c index fcc7be8a1a..d196c5d7c4 100644 --- a/src/prism.c +++ b/src/prism.c @@ -6423,129 +6423,6 @@ parse_symbol_encoding(pm_parser_t *parser, const pm_token_t *location, const pm_ return 0; } -static pm_node_flags_t -parse_and_validate_regular_expression_encoding_modifier(pm_parser_t *parser, const pm_string_t *source, bool ascii_only, pm_node_flags_t flags, char modifier, const pm_encoding_t *modifier_encoding) { - assert ((modifier == 'n' && modifier_encoding == PM_ENCODING_ASCII_8BIT_ENTRY) || - (modifier == 'u' && modifier_encoding == PM_ENCODING_UTF_8_ENTRY) || - (modifier == 'e' && modifier_encoding == PM_ENCODING_EUC_JP_ENTRY) || - (modifier == 's' && modifier_encoding == PM_ENCODING_WINDOWS_31J_ENTRY)); - - // There's special validation logic used if a string does not contain any character escape sequences. - if (parser->explicit_encoding == NULL) { - // If an ASCII-only string without character escapes is used with an encoding modifier, then resulting Regexp - // has the modifier encoding, unless the ASCII-8BIT modifier is used, in which case the Regexp "downgrades" to - // the US-ASCII encoding. - if (ascii_only) { - return modifier == 'n' ? PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING : flags; - } - - if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { - if (!ascii_only) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); - } - } else if (parser->encoding != modifier_encoding) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_ENCODING_OPTION_MISMATCH, modifier, parser->encoding->name); - - if (modifier == 'n' && !ascii_only) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_NON_ESCAPED_MBC, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } - } - - return flags; - } - - // TODO (nirvdrum 21-Feb-2024): To validate regexp sources with character escape sequences we need to know whether hex or Unicode escape sequences were used and Prism doesn't currently provide that data. We handle a subset of unambiguous cases in the meanwhile. - bool mixed_encoding = false; - - if (mixed_encoding) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_ESCAPE, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } else if (modifier != 'n' && parser->explicit_encoding == PM_ENCODING_ASCII_8BIT_ENTRY) { - // TODO (nirvdrum 21-Feb-2024): Validate the content is valid in the modifier encoding. Do this on-demand so we don't pay the cost of computation unnecessarily. - bool valid_string_in_modifier_encoding = true; - - if (!valid_string_in_modifier_encoding) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_ESCAPE, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } - } else if (modifier != 'u' && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { - // TODO (nirvdrum 21-Feb-2024): There's currently no way to tell if the source used hex or Unicode character escapes from `explicit_encoding` alone. If the source encoding was already UTF-8, both character escape types would set `explicit_encoding` to UTF-8, but need to be processed differently. Skip for now. - if (parser->encoding != PM_ENCODING_UTF_8_ENTRY) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING, (int) pm_string_length(source), (const char *) pm_string_source(source)); - } - } - - // We've determined the encoding would naturally be EUC-JP and there is no need to force the encoding to anything else. - return flags; -} - -/** - * Ruby "downgrades" the encoding of Regexps to US-ASCII if the associated encoding is ASCII-compatible and - * the unescaped representation of a Regexp source consists only of US-ASCII code points. This is true even - * when the Regexp is explicitly given an ASCII-8BIT encoding via the (/n) modifier. Otherwise, the encoding - * may be explicitly set with an escape sequence. - */ -static pm_node_flags_t -parse_and_validate_regular_expression_encoding(pm_parser_t *parser, const pm_string_t *source, bool ascii_only, pm_node_flags_t flags) { - // TODO (nirvdrum 22-Feb-2024): CRuby reports a special Regexp-specific error for invalid Unicode ranges. We either need to scan again or modify the "invalid Unicode escape sequence" message we already report. - bool valid_unicode_range = true; - if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY && !valid_unicode_range) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_REGEXP_INVALID_UNICODE_RANGE, (int) pm_string_length(source), (const char *) pm_string_source(source)); - return flags; - } - - // US-ASCII strings do not admit multi-byte character literals. However, character escape sequences corresponding - // to multi-byte characters are allowed. - if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY && parser->explicit_encoding == NULL && !ascii_only) { - // CRuby will continue processing even though a SyntaxError has already been detected. It may result in the - // following error message appearing twice. We do the same for compatibility. - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); - } - - /** - * Start checking modifier flags. We need to process these before considering any explicit encodings that may have - * been set by character literals. The order in which the encoding modifiers is checked does not matter. In the - * event that both an encoding modifier and an explicit encoding would result in the same encoding we do not set - * the corresponding "forced_" flag. Instead, the caller should check the encoding modifier flag and - * determine the encoding that way. - */ - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 'n', PM_ENCODING_ASCII_8BIT_ENTRY); - } - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 'u', PM_ENCODING_UTF_8_ENTRY); - } - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 'e', PM_ENCODING_EUC_JP_ENTRY); - } - - if (flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { - return parse_and_validate_regular_expression_encoding_modifier(parser, source, ascii_only, flags, 's', PM_ENCODING_WINDOWS_31J_ENTRY); - } - - // At this point no encoding modifiers will be present on the regular expression as they would have already - // been processed. Ruby stipulates that all source files must use an ASCII-compatible encoding. Thus, all - // regular expressions without an encoding modifier appearing in source are eligible for "downgrading" to US-ASCII. - if (ascii_only) { - return PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING; - } - - // A Regexp may optionally have its encoding explicitly set via a character escape sequence in the source string - // or by specifying a modifier. - // - // NB: an explicitly set encoding is ignored by Ruby if the Regexp consists of only US ASCII code points. - if (parser->explicit_encoding != NULL) { - if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { - return PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING; - } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { - return PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING; - } - } - - return 0; -} - /** * Allocate and initialize a new SymbolNode node with the given unescaped * string. @@ -8589,7 +8466,7 @@ escape_hexadecimal_digit(const uint8_t value) { * validated. */ static inline uint32_t -escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const pm_location_t *error_location) { +escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const pm_location_t *error_location, const uint8_t flags) { uint32_t value = 0; for (size_t index = 0; index < length; index++) { if (index != 0) value <<= 4; @@ -8599,7 +8476,10 @@ escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const // Here we're going to verify that the value is actually a valid Unicode // codepoint and not a surrogate pair. if (value >= 0xD800 && value <= 0xDFFF) { - if (error_location != NULL) { + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, defer the error to regexp encoding + // validation where we can produce a regexp-specific message. + } else if (error_location != NULL) { pm_parser_err(parser, error_location->start, error_location->length, PM_ERR_ESCAPE_INVALID_UNICODE); } else { pm_parser_err(parser, U32(string - parser->start), U32(length), PM_ERR_ESCAPE_INVALID_UNICODE); @@ -8630,14 +8510,25 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t fla // literal. if (value >= 0x80 || flags & PM_ESCAPE_FLAG_SINGLE) { if (parser->explicit_encoding != NULL && parser->explicit_encoding != PM_ENCODING_UTF_8_ENTRY) { - PM_PARSER_ERR_FORMAT(parser, U32(start - parser->start), U32(end - start), PM_ERR_MIXED_ENCODING, parser->explicit_encoding->name); + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, suppress this error — the regexp encoding + // validation will produce a more specific error message. + } else { + PM_PARSER_ERR_FORMAT(parser, U32(start - parser->start), U32(end - start), PM_ERR_MIXED_ENCODING, parser->explicit_encoding->name); + } } parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY; } if (!pm_buffer_append_unicode_codepoint(buffer, value)) { - pm_parser_err(parser, U32(start - parser->start), U32(end - start), PM_ERR_ESCAPE_INVALID_UNICODE); + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, defer the error to the regexp encoding + // validation which produces a regexp-specific message. + } else { + pm_parser_err(parser, U32(start - parser->start), U32(end - start), PM_ERR_ESCAPE_INVALID_UNICODE); + } + pm_buffer_append_byte(buffer, 0xEF); pm_buffer_append_byte(buffer, 0xBF); pm_buffer_append_byte(buffer, 0xBD); @@ -8649,10 +8540,15 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t fla * (i.e., the top bit is set) then it locks in the encoding. */ static inline void -escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t byte) { +escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t flags, uint8_t byte) { if (byte >= 0x80) { if (parser->explicit_encoding != NULL && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY && parser->encoding != PM_ENCODING_UTF_8_ENTRY) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_MIXED_ENCODING, parser->encoding->name); + if (flags & PM_ESCAPE_FLAG_REGEXP) { + // In regexp context, suppress this error — the regexp encoding + // validation will produce a more specific error message. + } else { + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_MIXED_ENCODING, parser->encoding->name); + } } parser->explicit_encoding = parser->encoding; @@ -8682,7 +8578,7 @@ escape_write_byte(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular pm_buffer_append_format(regular_expression_buffer, "\\x%02X", byte); } - escape_write_byte_encoded(parser, buffer, byte); + escape_write_byte_encoded(parser, buffer, flags, byte); } /** @@ -8838,7 +8734,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } } - escape_write_byte_encoded(parser, buffer, value); + escape_write_byte_encoded(parser, buffer, flags, value); } else { pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_HEXADECIMAL); } @@ -8887,7 +8783,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre if (flags & PM_ESCAPE_FLAG_REGEXP) { // If this is a regular expression, we are going to // let the regular expression engine handle this - // error instead of us. + // error instead of us because we don't know at this + // point if we're inside a comment in /x mode. pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); } else { pm_parser_err(parser, PM_TOKEN_END(parser, &parser->current), 0, PM_ERR_ESCAPE_INVALID_UNICODE); @@ -8903,7 +8800,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre extra_codepoints_start = unicode_start; } - uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length, NULL); + uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length, NULL, flags); escape_write_unicode(parser, buffer, flags, unicode_start, parser->current.end, value); parser->current.end += pm_strspn_inline_whitespace(parser->current.end, parser->end - parser->current.end); @@ -8923,7 +8820,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre if (flags & PM_ESCAPE_FLAG_REGEXP) { // If this is a regular expression, we are going to let // the regular expression engine handle this error - // instead of us. + // instead of us because we don't know at this point if + // we're inside a comment in /x mode. pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); } else { pm_parser_err(parser, U32(unicode_codepoints_start - parser->start), U32(parser->current.end - unicode_codepoints_start), PM_ERR_ESCAPE_INVALID_UNICODE_TERM); @@ -8944,7 +8842,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre PM_PARSER_ERR_FORMAT(parser, U32(start - parser->start), U32(parser->current.end - start), PM_ERR_ESCAPE_INVALID_UNICODE_SHORT, 2, start); } } else if (length == 4) { - uint32_t value = escape_unicode(parser, parser->current.end, 4, NULL); + uint32_t value = escape_unicode(parser, parser->current.end, 4, NULL, flags); if (flags & PM_ESCAPE_FLAG_REGEXP) { pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end + 4 - start)); @@ -9131,7 +9029,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre case '\r': { if (peek_offset(parser, 1) == '\n') { parser->current.end += 2; - escape_write_byte_encoded(parser, buffer, escape_byte('\n', flags)); + escape_write_byte_encoded(parser, buffer, flags, escape_byte('\n', flags)); return; } PRISM_FALLTHROUGH @@ -9516,20 +9414,12 @@ pm_token_buffer_push_escaped(pm_token_buffer_t *token_buffer, pm_parser_t *parse static void pm_regexp_token_buffer_push_escaped(pm_regexp_token_buffer_t *token_buffer, pm_parser_t *parser) { size_t width = parser_char_width(parser); - pm_buffer_append_bytes(&token_buffer->base.buffer, parser->current.end, width); - pm_buffer_append_bytes(&token_buffer->regexp_buffer, parser->current.end, width); + const uint8_t *start = parser->current.end; + pm_buffer_append_bytes(&token_buffer->base.buffer, start, width); + pm_buffer_append_bytes(&token_buffer->regexp_buffer, start, width); parser->current.end += width; } -static bool -pm_slice_ascii_only_p(const uint8_t *value, size_t length) { - for (size_t index = 0; index < length; index++) { - if (value[index] & 0x80) return false; - } - - return true; -} - /** * When we're about to return from lexing the current token and we know for sure * that we have found an escape sequence, this function is called to copy the @@ -9548,7 +9438,6 @@ pm_token_buffer_copy(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { static inline void pm_regexp_token_buffer_copy(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { pm_token_buffer_copy(parser, &token_buffer->base); - parser->current_regular_expression_ascii_only = pm_slice_ascii_only_p((const uint8_t *) pm_buffer_value(&token_buffer->regexp_buffer), pm_buffer_length(&token_buffer->regexp_buffer)); pm_buffer_free(&token_buffer->regexp_buffer); } @@ -9575,10 +9464,11 @@ static void pm_regexp_token_buffer_flush(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { if (token_buffer->base.cursor == NULL) { pm_string_shared_init(&parser->current_string, parser->current.start, parser->current.end); - parser->current_regular_expression_ascii_only = pm_slice_ascii_only_p(parser->current.start, (size_t) (parser->current.end - parser->current.start)); } else { - pm_buffer_append_bytes(&token_buffer->base.buffer, token_buffer->base.cursor, (size_t) (parser->current.end - token_buffer->base.cursor)); - pm_buffer_append_bytes(&token_buffer->regexp_buffer, token_buffer->base.cursor, (size_t) (parser->current.end - token_buffer->base.cursor)); + const uint8_t *cursor = token_buffer->base.cursor; + size_t length = (size_t) (parser->current.end - cursor); + pm_buffer_append_bytes(&token_buffer->base.buffer, cursor, length); + pm_buffer_append_bytes(&token_buffer->regexp_buffer, cursor, length); pm_regexp_token_buffer_copy(parser, token_buffer); } } @@ -17383,63 +17273,6 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) { } } -/** - * This struct is used to pass information between the regular expression parser - * and the error callback. - */ -typedef struct { - /** The parser that we are parsing the regular expression for. */ - pm_parser_t *parser; - - /** The start of the regular expression. */ - const uint8_t *start; - - /** The end of the regular expression. */ - const uint8_t *end; - - /** - * Whether or not the source of the regular expression is shared. This - * impacts the location of error messages, because if it is shared then we - * can use the location directly and if it is not, then we use the bounds of - * the regular expression itself. - */ - bool shared; -} parse_regular_expression_error_data_t; - -/** - * This callback is called when the regular expression parser encounters a - * syntax error. - */ -static void -parse_regular_expression_error(const uint8_t *start, const uint8_t *end, const char *message, void *data) { - parse_regular_expression_error_data_t *callback_data = (parse_regular_expression_error_data_t *) data; - pm_token_t location; - - if (callback_data->shared) { - location = (pm_token_t) { .type = 0, .start = start, .end = end }; - } else { - location = (pm_token_t) { .type = 0, .start = callback_data->start, .end = callback_data->end }; - } - - PM_PARSER_ERR_FORMAT(callback_data->parser, PM_TOKEN_START(callback_data->parser, &location), PM_TOKEN_LENGTH(&location), PM_ERR_REGEXP_PARSE_ERROR, message); -} - -/** - * Parse the errors for the regular expression and add them to the parser. - */ -static void -parse_regular_expression_errors(pm_parser_t *parser, pm_regular_expression_node_t *node) { - const pm_string_t *unescaped = &node->unescaped; - parse_regular_expression_error_data_t error_data = { - .parser = parser, - .start = parser->start + PM_NODE_START(node), - .end = parser->start + PM_NODE_END(node), - .shared = unescaped->type == PM_STRING_SHARED - }; - - pm_regexp_parse(parser, pm_string_source(unescaped), pm_string_length(unescaped), PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED), NULL, NULL, parse_regular_expression_error, &error_data); -} - /** * Determine if a given call node looks like a "command", which means it has * arguments but does not have parentheses. @@ -19317,22 +19150,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u } } } else { - /* `not` in a single line method is allowed to be followed by - * an expression without pattern matching, that optionally is - * followed by a `rescue` modifier. */ - if (flags & PM_PARSE_IN_ENDLESS_DEF) { - receiver = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); - - if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { - context_push(parser, PM_CONTEXT_RESCUE_MODIFIER); - pm_token_t rescue_keyword = parser->previous; - pm_node_t *value = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); - context_pop(parser); - receiver = UP(pm_rescue_modifier_node_create(parser, receiver, &rescue_keyword, value)); - } - } else { - receiver = parse_expression(parser, PM_BINDING_POWER_NOT, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); - } + receiver = parse_expression(parser, PM_BINDING_POWER_NOT, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | PM_PARSE_ACCEPTS_COMMAND_CALL, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1)); } return UP(pm_call_node_not_create(parser, receiver, &message, &arguments)); @@ -19913,10 +19731,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u parser_lex(parser); - pm_node_t *node = UP(pm_regular_expression_node_create(parser, &opening, &content, &parser->previous)); - pm_node_flag_set(node, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING); - - return node; + pm_regular_expression_node_t *node = pm_regular_expression_node_create(parser, &opening, &content, &parser->previous); + pm_node_flag_set(UP(node), pm_regexp_parse(parser, node, NULL, NULL)); + return UP(node); } pm_interpolated_regular_expression_node_t *interpolated; @@ -19928,7 +19745,6 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u // regular expression) or if it's not then it has interpolation. pm_string_t unescaped = parser->current_string; pm_token_t content = parser->current; - bool ascii_only = parser->current_regular_expression_ascii_only; parser_lex(parser); // If we hit an end, then we can create a regular expression @@ -19937,15 +19753,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u if (accept1(parser, PM_TOKEN_REGEXP_END)) { pm_regular_expression_node_t *node = (pm_regular_expression_node_t *) pm_regular_expression_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); - // If we're not immediately followed by a =~, then we want - // to parse all of the errors at this point. If it is - // followed by a =~, then it will get parsed higher up while - // parsing the named captures as well. + // If we're not immediately followed by a =~, then we + // parse and validate now. If it is followed by a =~, + // then it will get parsed in the =~ handler where + // named captures can also be extracted. if (!match1(parser, PM_TOKEN_EQUAL_TILDE)) { - parse_regular_expression_errors(parser, node); + pm_node_flag_set(UP(node), pm_regexp_parse(parser, node, NULL, NULL)); } - pm_node_flag_set(UP(node), parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, FL(node))); return UP(node); } @@ -20318,7 +20133,7 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ pm_token_t rescue = parser->current; parser_lex(parser); - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); @@ -20435,7 +20250,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } - pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (accepts_command_call_inner ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); + pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, (flags & PM_PARSE_ACCEPTS_DO_BLOCK) | (accepts_command_call_inner ? PM_PARSE_ACCEPTS_COMMAND_CALL : 0), PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1)); context_pop(parser); return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right)); @@ -20466,31 +20281,6 @@ parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const } } -/** - * This struct is used to pass information between the regular expression parser - * and the named capture callback. - */ -typedef struct { - /** The parser that is parsing the regular expression. */ - pm_parser_t *parser; - - /** The call node wrapping the regular expression node. */ - pm_call_node_t *call; - - /** The match write node that is being created. */ - pm_match_write_node_t *match; - - /** The list of names that have been parsed. */ - pm_constant_id_list_t names; - - /** - * Whether the content of the regular expression is shared. This impacts - * whether or not we used owned constants or shared constants in the - * constant pool for the names of the captures. - */ - bool shared; -} parse_regular_expression_named_capture_data_t; - static inline const uint8_t * pm_named_capture_escape_hex(pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end) { cursor++; @@ -20543,7 +20333,7 @@ pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, con if (*cursor != '{') { size_t length = pm_strspn_hexadecimal_digit(cursor, MIN(end - cursor, 4)); - uint32_t value = escape_unicode(parser, cursor, length, error_location); + uint32_t value = escape_unicode(parser, cursor, length, error_location, 0); if (!pm_buffer_append_unicode_codepoint(unescaped, value)) { pm_buffer_append_string(unescaped, (const char *) start, (size_t) ((cursor + length) - start)); @@ -20566,7 +20356,7 @@ pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, con if (length == 0) { break; } - uint32_t value = escape_unicode(parser, cursor, length, error_location); + uint32_t value = escape_unicode(parser, cursor, length, error_location, 0); (void) pm_buffer_append_unicode_codepoint(unescaped, value); cursor += length; @@ -20616,10 +20406,7 @@ pm_named_capture_escape(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8 * capture group. */ static void -parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { - parse_regular_expression_named_capture_data_t *callback_data = (parse_regular_expression_named_capture_data_t *) data; - - pm_parser_t *parser = callback_data->parser; +parse_regular_expression_named_capture(pm_parser_t *parser, const pm_string_t *capture, bool shared, pm_regexp_name_data_t *callback_data) { pm_call_node_t *call = callback_data->call; pm_constant_id_list_t *names = &callback_data->names; @@ -20637,7 +20424,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { // unescaped, which is what we need. const uint8_t *cursor = pm_memchr(source, '\\', length, parser->encoding_changed, parser->encoding); if (PRISM_UNLIKELY(cursor != NULL)) { - pm_named_capture_escape(parser, &unescaped, source, length, cursor, callback_data->shared ? NULL : &call->receiver->location); + pm_named_capture_escape(parser, &unescaped, source, length, cursor, shared ? NULL : &call->receiver->location); source = (const uint8_t *) pm_buffer_value(&unescaped); length = pm_buffer_length(&unescaped); } @@ -20653,7 +20440,7 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { return; } - if (callback_data->shared) { + if (shared) { // If the unescaped string is a slice of the source, then we can // copy the names directly. The pointers will line up. start = source; @@ -20707,26 +20494,19 @@ parse_regular_expression_named_capture(const pm_string_t *capture, void *data) { } /** - * Potentially change a =~ with a regular expression with named captures into a - * match write node. + * Potentially change a =~ with an interpolated regular expression with named + * captures into a match write node. This is for the interpolated case where + * we have concatenated content rather than a regular expression node. */ static pm_node_t * -parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *content, pm_call_node_t *call, bool extended_mode) { - parse_regular_expression_named_capture_data_t callback_data = { - .parser = parser, +parse_interpolated_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *content, pm_call_node_t *call, bool extended_mode) { + pm_regexp_name_data_t callback_data = { .call = call, + .match = NULL, .names = { 0 }, - .shared = content->type == PM_STRING_SHARED - }; - - parse_regular_expression_error_data_t error_data = { - .parser = parser, - .start = parser->start + PM_NODE_START(call->receiver), - .end = parser->start + PM_NODE_END(call->receiver), - .shared = content->type == PM_STRING_SHARED }; - pm_regexp_parse(parser, pm_string_source(content), pm_string_length(content), extended_mode, parse_regular_expression_named_capture, &callback_data, parse_regular_expression_error, &error_data); + pm_regexp_parse_named_captures(parser, pm_string_source(content), pm_string_length(content), false, extended_mode, parse_regular_expression_named_capture, &callback_data); if (callback_data.match != NULL) { return UP(callback_data.match); @@ -21248,14 +21028,25 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_string_t owned; pm_string_owned_init(&owned, (uint8_t *) memory, total_length); - result = parse_regular_expression_named_captures(parser, &owned, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); + result = parse_interpolated_regular_expression_named_captures(parser, &owned, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); pm_string_free(&owned); } } else if (PM_NODE_TYPE_P(node, PM_REGULAR_EXPRESSION_NODE)) { - // If we have a regular expression node, then we can just parse - // the named captures directly off the unescaped string. - const pm_string_t *content = &((pm_regular_expression_node_t *) node)->unescaped; - result = parse_regular_expression_named_captures(parser, content, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); + // If we have a regular expression node, then we can parse + // the named captures and validate encoding in one pass. + pm_regular_expression_node_t *regexp = (pm_regular_expression_node_t *) node; + + pm_regexp_name_data_t name_data = { + .call = call, + .match = NULL, + .names = { 0 }, + }; + + pm_node_flag_set(UP(regexp), pm_regexp_parse(parser, regexp, parse_regular_expression_named_capture, &name_data)); + + if (name_data.match != NULL) { + result = UP(name_data.match); + } } return result; @@ -22137,7 +21928,6 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si .current_block_exits = NULL, .semantic_token_seen = false, .frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET, - .current_regular_expression_ascii_only = false, .warn_mismatched_indentation = true }; diff --git a/src/regexp.c b/src/regexp.c index dcc7476244..23495a35e7 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,5 +1,9 @@ #include "prism/regexp.h" +#include "prism/diagnostic.h" +#include "prism/util/pm_buffer.h" +#include "prism/util/pm_strncasecmp.h" +/** The maximum depth of nested groups allowed in a regular expression. */ #define PM_REGEXP_PARSE_DEPTH_MAX 4096 /** @@ -18,6 +22,54 @@ typedef struct { /** A pointer to the end of the source that we are parsing. */ const uint8_t *end; + /** The encoding of the source. */ + const pm_encoding_t *encoding; + + /** The callback to call when a named capture group is found. */ + pm_regexp_name_callback_t name_callback; + + /** The data to pass to the name callback. */ + pm_regexp_name_data_t *name_data; + + /** The start of the regexp node (for error locations). */ + const uint8_t *node_start; + + /** The end of the regexp node (for error locations). */ + const uint8_t *node_end; + + /** + * The explicit encoding determined by escape sequences. NULL if no + * encoding-setting escape has been seen, UTF-8 for `\u` escapes, or the + * source encoding for `\x` escapes. + */ + const pm_encoding_t *explicit_encoding; + + /** + * Pointer to the first non-POSIX property name (for /n error messages). + * POSIX properties (Alnum, Alpha, etc.) work in all encodings. + * Script properties (Hiragana, Katakana, etc.) work in /e, /s, /u. + * Unicode-only properties (L, Ll, etc.) work only in /u. + */ + const uint8_t *property_name; + + /** Length of the first non-POSIX property name found. */ + size_t property_name_length; + + /** + * Pointer to the first Unicode-only property name (for /e, /s error + * messages). NULL if only POSIX or script properties have been seen. + */ + const uint8_t *unicode_property_name; + + /** Length of the first Unicode-only property name found. */ + size_t unicode_property_name_length; + + /** Buffer of hex escape byte values >= 0x80, separated by 0x00 sentinels. */ + pm_buffer_t hex_escape_buffer; + + /** Count of non-ASCII literal bytes (not from escapes). */ + uint32_t non_ascii_literal_count; + /** * Whether or not the regular expression currently being parsed is in * extended mode, wherein whitespace is ignored and comments are allowed. @@ -27,30 +79,76 @@ typedef struct { /** Whether the encoding has changed from the default. */ bool encoding_changed; - /** The encoding of the source. */ - const pm_encoding_t *encoding; + /** Whether the source content is shared (for named capture callback). */ + bool shared; - /** The callback to call when a named capture group is found. */ - pm_regexp_name_callback_t name_callback; + /** Whether a `\u{...}` escape with value >= 0x80 was seen. */ + bool has_unicode_escape; - /** The data to pass to the name callback. */ - void *name_data; + /** Whether a `\xNN` escape (or `\M-x`, etc.) with value >= 0x80 was seen. */ + bool has_hex_escape; + + /** + * Tracks whether the last encoding-setting escape was `\u` (true) or `\x` + * (false). This matters for error messages when both types are mixed. + */ + bool last_escape_was_unicode; + + /** Whether any `\p{...}` or `\P{...}` property escape was found. */ + bool has_property_escape; - /** The callback to call when a parse error is found. */ - pm_regexp_error_callback_t error_callback; + /** Whether a Unicode-only property escape was found (not POSIX or script). */ + bool has_unicode_property_escape; - /** The data to pass to the error callback. */ - void *error_data; + /** Whether a `\u` escape with invalid range (surrogate or > 0x10FFFF) was seen. */ + bool invalid_unicode_range; + + /** Whether we are accumulating consecutive hex escape bytes. */ + bool hex_group_active; + + /** Whether an invalid multibyte character was found during parsing. */ + bool has_invalid_multibyte; } pm_regexp_parser_t; /** - * Append an error to the parser. + * Append a syntax error to the parser's error list. If the source is shared + * (points into the original source), we can point to the exact error location. + * Otherwise, we point to the whole regexp node. */ static inline void pm_regexp_parse_error(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end, const char *message) { - parser->error_callback(start, end, message, parser->error_data); + pm_parser_t *pm = parser->parser; + uint32_t loc_start, loc_length; + + if (parser->shared) { + loc_start = (uint32_t) (start - pm->start); + loc_length = (uint32_t) (end - start); + } else { + loc_start = (uint32_t) (parser->node_start - pm->start); + loc_length = (uint32_t) (parser->node_end - parser->node_start); + } + + pm_diagnostic_list_append_format(&pm->error_list, loc_start, loc_length, PM_ERR_REGEXP_PARSE_ERROR, message); } +/** + * Append a formatted diagnostic error with proper shared/non-shared location + * handling. This is a macro because we need variadic args for the format string. + */ +#define pm_regexp_parse_error_format(parser_, err_start_, err_end_, diag_id, ...) \ + do { \ + pm_parser_t *pm__ = (parser_)->parser; \ + uint32_t loc_start__, loc_length__; \ + if ((parser_)->shared) { \ + loc_start__ = (uint32_t) ((err_start_) - pm__->start); \ + loc_length__ = (uint32_t) ((err_end_) - (err_start_)); \ + } else { \ + loc_start__ = (uint32_t) ((parser_)->node_start - pm__->start); \ + loc_length__ = (uint32_t) ((parser_)->node_end - (parser_)->node_start); \ + } \ + pm_diagnostic_list_append_format(&pm__->error_list, loc_start__, loc_length__, diag_id, __VA_ARGS__); \ + } while (0) + /** * This appends a new string to the list of named captures. This function * assumes the caller has already checked the validity of the name callback. @@ -59,7 +157,7 @@ static void pm_regexp_parser_named_capture(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end) { pm_string_t string; pm_string_shared_init(&string, start, end); - parser->name_callback(&string, parser->name_data); + parser->name_callback(parser->parser, &string, parser->shared, parser->name_data); pm_string_free(&string); } @@ -113,6 +211,47 @@ pm_regexp_char_find(pm_regexp_parser_t *parser, uint8_t value) { return true; } +/** + * Mark a group boundary in the hex escape byte buffer. When consecutive hex + * escape bytes >= 0x80 are followed by a non-hex-escape, this appends a 0x00 + * sentinel to separate the groups for later multibyte validation. + */ +static inline void +pm_regexp_hex_group_boundary(pm_regexp_parser_t *parser) { + if (parser->hex_group_active) { + pm_buffer_append_byte(&parser->hex_escape_buffer, 0x00); + parser->hex_group_active = false; + } +} + +/** + * Track a hex escape byte value >= 0x80 for multibyte validation. + */ +static inline void +pm_regexp_track_hex_escape(pm_regexp_parser_t *parser, uint8_t byte) { + if (byte >= 0x80) { + pm_buffer_append_byte(&parser->hex_escape_buffer, byte); + parser->hex_group_active = true; + parser->has_hex_escape = true; + + parser->explicit_encoding = parser->encoding; + parser->last_escape_was_unicode = false; + } else { + pm_regexp_hex_group_boundary(parser); + } +} + +/** + * Parse a hex digit character and return its value, or -1 if not a hex digit. + */ +static inline int +pm_regexp_hex_digit_value(uint8_t byte) { + if (byte >= '0' && byte <= '9') return byte - '0'; + if (byte >= 'a' && byte <= 'f') return byte - 'a' + 10; + if (byte >= 'A' && byte <= 'F') return byte - 'A' + 10; + return -1; +} + /** * Range quantifiers are a special class of quantifiers that look like * @@ -121,13 +260,12 @@ pm_regexp_char_find(pm_regexp_parser_t *parser, uint8_t value) { * * {digit,digit} * * {,digit} * - * Unfortunately, if there are any spaces in between, then this just becomes a - * regular character match expression and we have to backtrack. So when this - * function first starts running, we'll create a "save" point and then attempt - * to parse the quantifier. If it fails, we'll restore the save point and - * return. + * If there are any spaces in between, then this just becomes a regular + * character match expression and we have to backtrack. So when this function + * first starts running, we'll create a "save" point and then attempt to parse + * the quantifier. If it fails, we'll restore the save point and return. * - * The properly track everything, we're going to build a little state machine. + * To properly track everything, we're going to build a little state machine. * It looks something like the following: * * +-------+ +---------+ ------------+ @@ -275,10 +413,368 @@ pm_regexp_parse_posix_class(pm_regexp_parser_t *parser) { ); } +/** + * Property escape classification. Onigmo supports three tiers of property + * names depending on the encoding: + * + * - POSIX properties (Alnum, Alpha, ASCII, Blank, Cntrl, Digit, Graph, Lower, + * Print, Punct, Space, Upper, XDigit, Word): valid in all encodings. + * - Script properties (Hiragana, Katakana, Han, Latin, Greek, Cyrillic): valid + * in EUC-JP (/e), Windows-31J (/s), and UTF-8 (/u), but not ASCII-8BIT (/n). + * - Unicode-only properties (general categories like L, Ll, Lu, etc., plus + * Any, Assigned): valid only in UTF-8 (/u). + */ +typedef enum { + PM_REGEXP_PROPERTY_POSIX, + PM_REGEXP_PROPERTY_SCRIPT, + PM_REGEXP_PROPERTY_UNICODE +} pm_regexp_property_type_t; + +/** + * Check if a property name matches a NUL-terminated target string + * (case-insensitive, exact length match). + */ +static inline bool +pm_regexp_property_name_matches(const uint8_t *name, size_t length, const char *target) { + return target[length] == '\0' && pm_strncasecmp(name, (const uint8_t *) target, length) == 0; +} + +/** + * Classify a property name. The name may start with '^' for negation, which + * is skipped before matching. + */ +static pm_regexp_property_type_t +pm_regexp_classify_property(const uint8_t *name, size_t length) { + // Skip leading '^' for negated properties like \p{^Hiragana}. + if (length > 0 && name[0] == '^') { + name++; + length--; + } + + // POSIX properties — valid in all encodings. + static const char *const posix_properties[] = { + "Alnum", "Alpha", "ASCII", "Blank", "Cntrl", "Digit", "Graph", + "Lower", "Print", "Punct", "Space", "Upper", "XDigit", "Word", + NULL + }; + + for (const char *const *property = posix_properties; *property != NULL; property++) { + if (pm_regexp_property_name_matches(name, length, *property)) { + return PM_REGEXP_PROPERTY_POSIX; + } + } + + // Script properties — valid in /e, /s, /u but not /n. + static const char *const script_properties[] = { + "Hiragana", "Katakana", "Han", "Latin", "Greek", "Cyrillic", + NULL + }; + + for (const char *const *property = script_properties; *property != NULL; property++) { + if (pm_regexp_property_name_matches(name, length, *property)) { + return PM_REGEXP_PROPERTY_SCRIPT; + } + } + + // Everything else is Unicode-only (general categories, other scripts, etc.). + return PM_REGEXP_PROPERTY_UNICODE; +} + +/** + * Check for and skip a `\p{...}` or `\P{...}` Unicode property escape. The + * cursor should be pointing at 'p' or 'P' when this is called. If a property + * escape is found, record it on the regexp parser and advance past the closing + * '}'. + * + * Properties are classified into three tiers (POSIX, script, Unicode-only) to + * determine which encoding modifiers they are valid with. + */ +static bool +pm_regexp_parse_property_escape(pm_regexp_parser_t *parser) { + assert(*parser->cursor == 'p' || *parser->cursor == 'P'); + + if (parser->cursor + 1 < parser->end && parser->cursor[1] == '{') { + const uint8_t *name_start = parser->cursor + 2; + const uint8_t *search = name_start; + + while (search < parser->end && *search != '}') search++; + + if (search < parser->end) { + size_t name_length = (size_t) (search - name_start); + parser->has_property_escape = true; + + pm_regexp_property_type_t type = pm_regexp_classify_property(name_start, name_length); + + // Track the first non-POSIX property name (for /n error messages). + if (type >= PM_REGEXP_PROPERTY_SCRIPT && parser->property_name == NULL) { + parser->property_name = name_start; + parser->property_name_length = name_length; + } + + // Track the first Unicode-only property name (for /e, /s error messages). + if (type == PM_REGEXP_PROPERTY_UNICODE) { + parser->has_unicode_property_escape = true; + if (parser->unicode_property_name == NULL) { + parser->unicode_property_name = name_start; + parser->unicode_property_name_length = name_length; + } + } + + parser->cursor = search + 1; // skip past '}' + return true; + } + } + + // Not a property escape, just skip the single character after '\'. + parser->cursor++; + return false; +} + +/** + * Validate and skip a \u escape sequence in a regular expression. The cursor + * should be pointing at the character after 'u' when this is called. This + * handles both the \u{NNNN MMMM} and \uNNNN forms. Also tracks encoding + * state for validation. + */ +static void +pm_regexp_parse_unicode_escape(pm_regexp_parser_t *parser) { + const uint8_t *escape_start = parser->cursor - 2; // points to '\' + + if (pm_regexp_char_is_eof(parser)) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "invalid Unicode escape"); + return; + } + + if (*parser->cursor == '{') { + parser->cursor++; // skip '{' + + // Skip leading whitespace. + while (!pm_regexp_char_is_eof(parser) && pm_char_is_whitespace(*parser->cursor)) { + parser->cursor++; + } + + bool has_codepoint = false; + + while (!pm_regexp_char_is_eof(parser) && *parser->cursor != '}') { + // Parse the hex digits to compute the codepoint value. + uint32_t value = 0; + size_t hex_count = 0; + + int digit; + while (!pm_regexp_char_is_eof(parser) && (digit = pm_regexp_hex_digit_value(*parser->cursor)) >= 0) { + value = (value << 4) | (uint32_t) digit; + hex_count++; + parser->cursor++; + } + + if (hex_count == 0) { + // Skip to '}' or end of regexp to find the full extent. + while (!pm_regexp_char_is_eof(parser) && *parser->cursor != '}') { + parser->cursor++; + } + + const uint8_t *escape_end = parser->cursor; + if (!pm_regexp_char_is_eof(parser)) { + escape_end++; + parser->cursor++; // skip '}' + } + + pm_regexp_parse_error_format(parser, escape_start, escape_end, PM_ERR_ESCAPE_INVALID_UNICODE_LIST, (int) (escape_end - escape_start), (const char *) escape_start); + return; + } + + if (hex_count > 6) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "invalid Unicode range"); + } + + // Track encoding state for this codepoint. + if (value >= 0x80) { + parser->has_unicode_escape = true; + parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY; + parser->last_escape_was_unicode = true; + pm_regexp_hex_group_boundary(parser); + } + + // Check for invalid Unicode range (surrogates or > 0x10FFFF). + if (value > 0x10FFFF || (value >= 0xD800 && value <= 0xDFFF)) { + parser->invalid_unicode_range = true; + } + + has_codepoint = true; + + // Skip whitespace between codepoints. + while (!pm_regexp_char_is_eof(parser) && pm_char_is_whitespace(*parser->cursor)) { + parser->cursor++; + } + } + + if (pm_regexp_char_is_eof(parser)) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "unterminated Unicode escape"); + } else { + if (!has_codepoint) { + pm_regexp_parse_error_format(parser, escape_start, parser->cursor + 1, PM_ERR_ESCAPE_INVALID_UNICODE_LIST, (int) (parser->cursor + 1 - escape_start), (const char *) escape_start); + } + parser->cursor++; // skip '}' + } + } else { + // \uNNNN form — need exactly 4 hex digits. + uint32_t value = 0; + size_t hex_count = 0; + + int digit; + while (hex_count < 4 && !pm_regexp_char_is_eof(parser) && (digit = pm_regexp_hex_digit_value(*parser->cursor)) >= 0) { + value = (value << 4) | (uint32_t) digit; + hex_count++; + parser->cursor++; + } + + if (hex_count < 4) { + pm_regexp_parse_error(parser, escape_start, parser->cursor, "invalid Unicode escape"); + } else if (value >= 0x80) { + parser->has_unicode_escape = true; + parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY; + parser->last_escape_was_unicode = true; + pm_regexp_hex_group_boundary(parser); + } + + // Check for invalid Unicode range. + if (hex_count == 4 && (value > 0x10FFFF || (value >= 0xD800 && value <= 0xDFFF))) { + parser->invalid_unicode_range = true; + } + } +} + // Forward declaration because character sets can be nested. static bool pm_regexp_parse_lbracket(pm_regexp_parser_t *parser, uint16_t depth); +/** + * Parse a \x escape and return the byte value. The cursor should be pointing + * at the character after 'x'. Returns -1 if no hex digits follow. + */ +static int +pm_regexp_parse_hex_escape(pm_regexp_parser_t *parser) { + int value = -1; + + if (!pm_regexp_char_is_eof(parser)) { + int digit = pm_regexp_hex_digit_value(*parser->cursor); + if (digit >= 0) { + value = digit; + parser->cursor++; + + if (!pm_regexp_char_is_eof(parser)) { + digit = pm_regexp_hex_digit_value(*parser->cursor); + if (digit >= 0) { + value = (value << 4) | digit; + parser->cursor++; + } + } + } + } + + if (value >= 0) { + pm_regexp_track_hex_escape(parser, (uint8_t) value); + } + + return value; +} + +/** + * Parse a backslash escape sequence in a regexp, handling \u (unicode), + * \p/\P (property), \x (hex), and other single-character escapes. Also + * tracks encoding state for \M-x and \C-\M-x escapes. + */ +static void +pm_regexp_parse_backslash_escape(pm_regexp_parser_t *parser) { + if (pm_regexp_char_is_eof(parser)) return; + + switch (*parser->cursor) { + case 'u': + parser->cursor++; // skip 'u' + pm_regexp_parse_unicode_escape(parser); + break; + case 'p': + case 'P': + pm_regexp_parse_property_escape(parser); + break; + case 'x': + parser->cursor++; // skip 'x' + pm_regexp_parse_hex_escape(parser); + break; + case 'M': + // \M-x produces (x | 0x80), always >= 0x80 + if (parser->cursor + 2 < parser->end && parser->cursor[1] == '-') { + parser->cursor += 2; // skip 'M-' + if (!pm_regexp_char_is_eof(parser)) { + if (*parser->cursor == '\\') { + parser->cursor++; + // \M-\C-x or \M-\cx — the resulting byte is always >= 0x80 + // We just need to track it as a hex escape >= 0x80. + pm_regexp_parse_backslash_escape(parser); + } else { + parser->cursor++; + } + // \M-x always produces a byte >= 0x80 + pm_regexp_track_hex_escape(parser, 0x80); + } + } else { + parser->cursor++; + } + break; + case 'C': + // \C-x produces (x & 0x1F) + if (parser->cursor + 2 < parser->end && parser->cursor[1] == '-') { + parser->cursor += 2; // skip 'C-' + if (!pm_regexp_char_is_eof(parser)) { + if (*parser->cursor == '\\') { + parser->cursor++; + pm_regexp_parse_backslash_escape(parser); + } else { + parser->cursor++; + } + } + } else { + parser->cursor++; + } + break; + case 'c': + // \cx produces (x & 0x1F) + parser->cursor++; // skip 'c' + if (!pm_regexp_char_is_eof(parser)) { + if (*parser->cursor == '\\') { + parser->cursor++; + pm_regexp_parse_backslash_escape(parser); + } else { + parser->cursor++; + } + } + break; + default: + pm_regexp_hex_group_boundary(parser); + parser->cursor++; + break; + } +} + +/** + * Check if a byte at the current position is a non-ASCII byte in a multibyte + * encoding that produces an invalid character. If so, emit an error at the + * byte location immediately. + */ +static void +pm_regexp_parse_invalid_multibyte(pm_regexp_parser_t *parser, const uint8_t *cursor) { + uint8_t byte = *cursor; + if (byte >= 0x80 && parser->encoding_changed && parser->encoding->multibyte) { + size_t width = parser->encoding->char_width(cursor, (ptrdiff_t) (parser->end - cursor)); + if (width > 1) { + parser->cursor += width - 1; + } else if (width == 0) { + parser->has_invalid_multibyte = true; + pm_regexp_parse_error_format(parser, cursor, cursor + 1, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } + } +} + /** * match-char-set : '[' '^'? (match-range | match-char)* ']' * ; @@ -293,12 +789,16 @@ pm_regexp_parse_character_set(pm_regexp_parser_t *parser, uint16_t depth) { pm_regexp_parse_lbracket(parser, (uint16_t) (depth + 1)); break; case '\\': - if (!pm_regexp_char_is_eof(parser)) { - parser->cursor++; - } + pm_regexp_parse_backslash_escape(parser); break; default: - // do nothing, we've already advanced the cursor + // We've already advanced the cursor by one byte. If the byte + // was >= 0x80 in a multibyte encoding, we may need to consume + // additional continuation bytes and validate the character. + if (*(parser->cursor - 1) >= 0x80) { + parser->non_ascii_literal_count++; + } + pm_regexp_parse_invalid_multibyte(parser, parser->cursor - 1); break; } } @@ -354,8 +854,13 @@ typedef enum { // These are the options that are configurable on the regular expression (or // from within a group). +/** The minimum character value for a regexp option slot. */ #define PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM 'a' + +/** The maximum character value for a regexp option slot. */ #define PRISM_REGEXP_OPTION_STATE_SLOT_MAXIMUM 'x' + +/** The number of regexp option slots. */ #define PRISM_REGEXP_OPTION_STATE_SLOTS (PRISM_REGEXP_OPTION_STATE_SLOT_MAXIMUM - PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM + 1) /** @@ -498,7 +1003,15 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser, uint16_t depth) { } size_t width = parser->encoding->char_width(parser->cursor, (ptrdiff_t) (parser->end - parser->cursor)); - if (width == 0) return false; + if (width == 0) { + if (*parser->cursor >= 0x80) { + parser->has_invalid_multibyte = true; + pm_regexp_parse_error_format(parser, parser->cursor, parser->cursor + 1, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + parser->cursor++; + continue; + } + return false; + } escaped = (width == 1) && (*parser->cursor == '\\'); parser->cursor += width; @@ -686,9 +1199,7 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser, uint16_t depth) { return pm_regexp_parse_quantifier(parser); case '\\': parser->cursor++; - if (!pm_regexp_char_is_eof(parser)) { - parser->cursor++; - } + pm_regexp_parse_backslash_escape(parser); return pm_regexp_parse_quantifier(parser); case '(': parser->cursor++; @@ -720,9 +1231,30 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser, uint16_t depth) { width = parser->encoding->char_width(parser->cursor, (ptrdiff_t) (parser->end - parser->cursor)); } - if (width == 0) return false; // TODO: add appropriate error - parser->cursor += width; + if (width == 0) { + if (*parser->cursor >= 0x80 && parser->encoding_changed) { + if (parser->encoding->multibyte) { + // Invalid multibyte character in a multibyte encoding. + // Emit the error at the byte location immediately. + parser->has_invalid_multibyte = true; + pm_regexp_parse_error_format(parser, parser->cursor, parser->cursor + 1, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } else { + // Non-ASCII byte in a single-byte encoding (e.g., + // US-ASCII). Count it for later error reporting. + parser->non_ascii_literal_count++; + } + parser->cursor++; + return pm_regexp_parse_quantifier(parser); + } + return false; + } + // Count non-ASCII literal bytes. + for (size_t i = 0; i < width; i++) { + if (parser->cursor[i] >= 0x80) parser->non_ascii_literal_count++; + } + + parser->cursor += width; return pm_regexp_parse_quantifier(parser); } } @@ -768,13 +1300,353 @@ pm_regexp_parse_pattern(pm_regexp_parser_t *parser) { return pm_regexp_char_is_eof(parser); } +// --------------------------------------------------------------------------- +// Encoding validation +// --------------------------------------------------------------------------- + /** - * Parse a regular expression and extract the names of all of the named capture - * groups. + * Validate that groups of hex escape bytes in the buffer form valid multibyte + * characters in the given encoding. Groups are separated by 0x00 sentinels. + */ +static bool +pm_regexp_validate_hex_escapes(const pm_encoding_t *encoding, const pm_buffer_t *buffer) { + const uint8_t *data = (const uint8_t *) pm_buffer_value(buffer); + size_t len = pm_buffer_length(buffer); + size_t i = 0; + + while (i < len) { + size_t group_start = i; + while (i < len && data[i] != 0x00) i++; + + for (size_t j = group_start; j < i; ) { + size_t width = encoding->char_width(data + j, (ptrdiff_t) (i - j)); + if (width == 0) return false; + j += width; + } + + if (i < len) i++; // skip sentinel + } + + return true; +} + +/** + * Format regexp source content for use in error messages, hex-escaping + * non-ASCII bytes. + */ +static void +pm_regexp_format_for_error(pm_buffer_t *buffer, const pm_encoding_t *encoding, const uint8_t *source, size_t length) { + size_t index = 0; + + if (encoding == PM_ENCODING_UTF_8_ENTRY) { + pm_buffer_append_string(buffer, (const char *) source, length); + return; + } + + while (index < length) { + if (source[index] < 0x80) { + pm_buffer_append_byte(buffer, source[index]); + index++; + } else if (encoding->multibyte) { + size_t width = encoding->char_width(source + index, (ptrdiff_t) (length - index)); + + if (width > 1) { + pm_buffer_append_string(buffer, "\\x{", 3); + for (size_t i = 0; i < width; i++) { + pm_buffer_append_format(buffer, "%02X", source[index + i]); + } + pm_buffer_append_byte(buffer, '}'); + index += width; + } else { + pm_buffer_append_format(buffer, "\\x%02X", source[index]); + index++; + } + } else { + pm_buffer_append_format(buffer, "\\x%02X", source[index]); + index++; + } + } +} + +/** + * Emit an encoding validation error on the regexp node. + */ +#define PM_REGEXP_ENCODING_ERROR(parser, diag_id, ...) \ + pm_diagnostic_list_append_format( \ + &(parser)->parser->error_list, \ + (uint32_t) ((parser)->node_start - (parser)->parser->start), \ + (uint32_t) ((parser)->node_end - (parser)->node_start), \ + diag_id, __VA_ARGS__) + +/** + * Validate encoding for a regexp with an encoding modifier (/e, /s, /u, /n). + * + * The decision tree is: + * + * 1. No escape-set encoding (explicit_encoding == NULL): + * a. ASCII-only content: validate property escapes, return forced US-ASCII + * for /n or the modifier flags for others. + * b. US-ASCII source with non-ASCII literals: emit per-byte errors. + * c. Source encoding differs from modifier encoding: emit mismatch error. + * + * 2. Mixed \u and \x escapes: emit the appropriate conflict error depending + * on the modifier and which escape type was last. + * + * 3. \u escape with non-/u modifier: incompatible encoding error. + * + * 4. Validate that hex escape byte sequences form valid multibyte characters + * in the modifier's encoding. + */ +static pm_node_flags_t +pm_regexp_validate_encoding_modifier(pm_regexp_parser_t *parser, bool ascii_only, pm_node_flags_t flags, char modifier, const pm_encoding_t *modifier_encoding, const char *source_start, int source_length) { + + if (parser->explicit_encoding == NULL) { + if (ascii_only) { + // Check property escapes against the modifier's encoding tier. + // /n (ASCII-8BIT): only POSIX properties are valid. + // /e, /s: POSIX and script properties are valid. + // /u: all properties are valid. + if (modifier == 'n' && parser->property_name != NULL) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INVALID_CHAR_PROPERTY, + (int) parser->property_name_length, (const char *) parser->property_name, + source_length, source_start); + } else if (modifier != 'u' && parser->has_unicode_property_escape) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INVALID_CHAR_PROPERTY, + (int) parser->unicode_property_name_length, (const char *) parser->unicode_property_name, + source_length, source_start); + } + return modifier == 'n' ? PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING : flags; + } + + if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + for (uint32_t i = 0; i < parser->non_ascii_literal_count; i++) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } + } else if (parser->encoding != modifier_encoding) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_ENCODING_OPTION_MISMATCH, modifier, parser->encoding->name); + + if (modifier == 'n' && !ascii_only) { + pm_buffer_t formatted = { 0 }; + pm_regexp_format_for_error(&formatted, parser->encoding, (const uint8_t *) source_start, (size_t) source_length); + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_NON_ESCAPED_MBC, (int) formatted.length, (const char *) formatted.value); + pm_buffer_free(&formatted); + } + } + + return flags; + } + + // Mixed unicode + hex escapes. + if (parser->has_unicode_escape && parser->has_hex_escape) { + if (modifier == 'n') { + if (parser->last_escape_was_unicode) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP, source_length, source_start); + } else { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_ESCAPED_NON_ASCII_IN_UTF8, source_length, source_start); + } + } else { + if (!pm_regexp_validate_hex_escapes(modifier_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + } + + return flags; + } + + if (modifier != 'u' && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + if (parser->last_escape_was_unicode) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING, source_length, source_start); + } else if (parser->encoding != PM_ENCODING_UTF_8_ENTRY) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING, source_length, source_start); + } + } + + if (modifier != 'n' && !pm_regexp_validate_hex_escapes(modifier_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + + return flags; +} + +/** + * Validate encoding for a regexp without a modifier and compute the encoding + * flags to set on the node. + * + * The decision tree is: + * + * 1. If a modifier (/n, /u, /e, /s) is present, delegate to + * pm_regexp_validate_encoding_modifier. + * 2. Invalid multibyte chars or unicode ranges: suppress further checks (errors + * were already emitted during parsing). + * 3. US-ASCII source with non-ASCII literals: emit per-byte errors. + * 4. ASCII-only content: return forced US-ASCII (or forced UTF-8 if \p{...}). + * 5. Escape-set encoding present: validate hex escapes against the target + * encoding, handle mixed \u + \x conflicts, and return the appropriate + * forced encoding flag. + */ +static pm_node_flags_t +pm_regexp_validate_encoding(pm_regexp_parser_t *parser, bool ascii_only, pm_node_flags_t flags, const char *source_start, int source_length) { + + // Invalid multibyte characters suppress further validation. + // Errors were already emitted at the byte locations during parsing. + if (parser->has_invalid_multibyte) { + return flags; + } + + if (parser->invalid_unicode_range) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_INVALID_UNICODE_RANGE, source_length, source_start); + return flags; + } + + // Check modifier flags first. + if (flags & PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 'n', PM_ENCODING_ASCII_8BIT_ENTRY, source_start, source_length); + } + if (flags & PM_REGULAR_EXPRESSION_FLAGS_UTF_8) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 'u', PM_ENCODING_UTF_8_ENTRY, source_start, source_length); + } + if (flags & PM_REGULAR_EXPRESSION_FLAGS_EUC_JP) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 'e', PM_ENCODING_EUC_JP_ENTRY, source_start, source_length); + } + if (flags & PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J) { + return pm_regexp_validate_encoding_modifier(parser, ascii_only, flags, 's', PM_ENCODING_WINDOWS_31J_ENTRY, source_start, source_length); + } + + // No modifier — check for non-ASCII literals in US-ASCII encoding. + if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY && parser->explicit_encoding == NULL && !ascii_only) { + for (uint32_t i = 0; i < parser->non_ascii_literal_count; i++) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_CHAR, parser->encoding->name); + } + } + + // ASCII-only regexps get downgraded to US-ASCII, unless property escapes + // force UTF-8. + if (ascii_only) { + if (parser->has_property_escape) { + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING; + } + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING; + } + + // Check explicit encoding from escape sequences. + if (parser->explicit_encoding != NULL) { + // Mixed unicode + hex escapes without modifier. + if (parser->has_unicode_escape && parser->has_hex_escape && parser->encoding != PM_ENCODING_UTF_8_ENTRY) { + if (parser->encoding != PM_ENCODING_US_ASCII_ENTRY && + parser->encoding != PM_ENCODING_ASCII_8BIT_ENTRY && + !pm_regexp_validate_hex_escapes(parser->encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } else if (parser->last_escape_was_unicode) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP, source_length, source_start); + } else { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_ESCAPED_NON_ASCII_IN_UTF8, source_length, source_start); + } + + return 0; + } + + if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + if (!pm_regexp_validate_hex_escapes(parser->explicit_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING; + } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + return PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING; + } else { + if (!pm_regexp_validate_hex_escapes(parser->explicit_encoding, &parser->hex_escape_buffer)) { + PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_INVALID_MULTIBYTE_ESCAPE, source_length, source_start); + } + } + } + + return 0; +} + +/** + * Parse a regular expression, validate its encoding, and optionally extract + * named capture groups. Encoding validation walks the raw source (content_loc) + * to distinguish escape-produced bytes from literal bytes. Named capture + * extraction walks the unescaped content since escape sequences in group names + * (e.g., line continuations) have already been processed by the lexer. + */ +PRISM_EXPORTED_FUNCTION pm_node_flags_t +pm_regexp_parse(pm_parser_t *parser, pm_regular_expression_node_t *node, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data) { + const uint8_t *source = parser->start + node->content_loc.start; + size_t size = node->content_loc.length; + bool extended_mode = PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED); + pm_node_flags_t flags = PM_NODE_FLAGS(node); + + const uint8_t *node_start = parser->start + node->base.location.start; + const uint8_t *node_end = parser->start + node->base.location.start + node->base.location.length; + + // First pass: walk raw source for encoding validation (no name extraction). + pm_regexp_parser_t regexp_parser = { + .parser = parser, + .start = source, + .cursor = source, + .end = source + size, + .extended_mode = extended_mode, + .encoding_changed = parser->encoding_changed, + .encoding = parser->encoding, + .name_callback = NULL, + .name_data = NULL, + .shared = true, + .node_start = node_start, + .node_end = node_end, + .has_unicode_escape = false, + .has_hex_escape = false, + .last_escape_was_unicode = false, + .explicit_encoding = NULL, + .has_property_escape = false, + .has_unicode_property_escape = false, + .property_name = NULL, + .property_name_length = 0, + .unicode_property_name = NULL, + .unicode_property_name_length = 0, + .non_ascii_literal_count = 0, + .invalid_unicode_range = false, + .hex_escape_buffer = { 0 }, + .hex_group_active = false, + .has_invalid_multibyte = false, + }; + + pm_regexp_parse_pattern(®exp_parser); + + // Compute ascii_only from the regexp parser's tracked state. We cannot + // use node->unescaped for this because regexp unescaped content preserves + // escape text (e.g., \x80 is 4 ASCII chars), not the binary values. + bool ascii_only = !regexp_parser.has_hex_escape && !regexp_parser.has_unicode_escape && regexp_parser.non_ascii_literal_count == 0; + // Use the unescaped content for error messages to match CRuby's format, + // where Ruby escapes like \M-\C-? are resolved to bytes but regexp escapes + // like \u{80} are preserved as text. + const char *error_source = (const char *) pm_string_source(&node->unescaped); + int error_source_length = (int) pm_string_length(&node->unescaped); + pm_node_flags_t encoding_flags = pm_regexp_validate_encoding(®exp_parser, ascii_only, flags, error_source, error_source_length); + pm_buffer_free(®exp_parser.hex_escape_buffer); + + // Second pass: walk unescaped content for named capture extraction. + if (name_callback != NULL) { + bool shared = node->unescaped.type == PM_STRING_SHARED; + pm_regexp_parse_named_captures(parser, pm_string_source(&node->unescaped), pm_string_length(&node->unescaped), shared, extended_mode, name_callback, name_data); + } + + return encoding_flags; +} + +/** + * Parse an interpolated regular expression for named capture groups only. + * This is used for the =~ operator with interpolated regexps where we don't + * have a pm_regular_expression_node_t. No encoding validation is performed. + * + * Note: The encoding-tracking fields (has_unicode_escape, has_hex_escape, etc.) + * are initialized but not used for the result. They exist because the parsing + * functions (pm_regexp_parse_backslash_escape, etc.) unconditionally update + * them as they walk through the content. */ -PRISM_EXPORTED_FUNCTION void -pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool extended_mode, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data) { - pm_regexp_parse_pattern(&(pm_regexp_parser_t) { +void +pm_regexp_parse_named_captures(pm_parser_t *parser, const uint8_t *source, size_t size, bool shared, bool extended_mode, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data) { + pm_regexp_parser_t regexp_parser = { .parser = parser, .start = source, .cursor = source, @@ -784,7 +1656,26 @@ pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool ex .encoding = parser->encoding, .name_callback = name_callback, .name_data = name_data, - .error_callback = error_callback, - .error_data = error_data - }); + .shared = shared, + .node_start = source, + .node_end = source + size, + .has_unicode_escape = false, + .has_hex_escape = false, + .last_escape_was_unicode = false, + .explicit_encoding = NULL, + .has_property_escape = false, + .has_unicode_property_escape = false, + .property_name = NULL, + .property_name_length = 0, + .unicode_property_name = NULL, + .unicode_property_name_length = 0, + .non_ascii_literal_count = 0, + .invalid_unicode_range = false, + .hex_escape_buffer = { 0 }, + .hex_group_active = false, + .has_invalid_multibyte = false, + }; + + pm_regexp_parse_pattern(®exp_parser); + pm_buffer_free(®exp_parser.hex_escape_buffer); } diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index d717dc1e16..8fa47590c0 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -330,13 +330,15 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PATTERN_TERM_PAREN] = { "expected a `)` to close the pattern expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = { "unexpected `||=` in a multiple assignment", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_ENCODING_OPTION_MISMATCH] = { "regexp encoding option '%c' differs from source encoding '%s'", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_REGEXP_ESCAPED_NON_ASCII_IN_UTF8] = { "escaped non ASCII character in UTF-8 regexp: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING] = { "incompatible character encoding: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_REGEXP_NON_ESCAPED_MBC] = { "/.../n has a non escaped non ASCII character in non ASCII-8BIT script: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_REGEXP_INVALID_CHAR_PROPERTY] = { "invalid character property name {%.*s}: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_INVALID_UNICODE_RANGE] = { "invalid Unicode range: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_REGEXP_NON_ESCAPED_MBC] = { "/.../n has a non escaped non ASCII character in non ASCII-8BIT script: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_PARSE_ERROR] = { "%s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_UNKNOWN_OPTIONS] = { "unknown regexp %s - %.*s", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_REGEXP_TERM] = { "unterminated regexp meets end of file; expected a closing delimiter", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP] = { "UTF-8 character in non UTF-8 regexp: /%s/", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP] = { "UTF-8 character in non UTF-8 regexp: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_RESCUE_EXPRESSION] = { "expected a rescued expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_RESCUE_MODIFIER_VALUE] = { "expected a value after the `rescue` modifier", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/encoding/regular_expression_encoding_test.rb b/test/prism/encoding/regular_expression_encoding_test.rb index e2daae1d7f..fdff1e3281 100644 --- a/test/prism/encoding/regular_expression_encoding_test.rb +++ b/test/prism/encoding/regular_expression_encoding_test.rb @@ -2,6 +2,7 @@ return unless defined?(RubyVM::InstructionSequence) return if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism +return if RUBY_VERSION < "3.2" require_relative "../test_helper" @@ -21,7 +22,7 @@ class RegularExpressionEncodingTest < TestCase ["n", "u", "e", "s"].each do |modifier| define_method(:"test_regular_expression_encoding_modifiers_/#{modifier}_#{encoding.name}") do - regexp_sources = ["abc", "garçon", "\\x80", "gar\\xC3\\xA7on", "gar\\u{E7}on", "abc\\u{FFFFFF}", "\\x80\\u{80}" ] + regexp_sources = ["abc", "garçon", "\\x80", "gar\\xC3\\xA7on", "gar\\u{E7}on", "abc\\u{FFFFFF}", "\\x80\\u{80}", "\\p{L}" ] assert_regular_expression_encoding_flags( encoding, @@ -35,17 +36,15 @@ class RegularExpressionEncodingTest < TestCase def assert_regular_expression_encoding_flags(encoding, regexps) regexps.each do |regexp| - regexp_modifier_used = regexp.end_with?("/u") || regexp.end_with?("/e") || regexp.end_with?("/s") || regexp.end_with?("/n") source = "# encoding: #{encoding.name}\n#{regexp}" - encoding_errors = ["invalid multibyte char", "escaped non ASCII character in UTF-8 regexp", "differs from source encoding"] - skipped_errors = ["invalid multibyte escape", "incompatible character encoding", "UTF-8 character in non UTF-8 regexp", "invalid Unicode range", "invalid Unicode list"] - - # TODO (nirvdrum 21-Feb-2024): Prism currently does not handle Regexp validation unless modifiers are used. So, skip processing those errors for now: https://github.com/ruby/prism/issues/2104 - unless regexp_modifier_used - skipped_errors += encoding_errors - encoding_errors.clear - end + encoding_errors = [ + "invalid multibyte char", "escaped non ASCII character in UTF-8 regexp", + "differs from source encoding", "incompatible character encoding", + "invalid multibyte escape", "UTF-8 character in non UTF-8 regexp", + "invalid Unicode range", "non escaped non ASCII character", + "invalid character property name", "invalid Unicode list", + ] expected = begin @@ -53,8 +52,6 @@ def assert_regular_expression_encoding_flags(encoding, regexps) rescue SyntaxError => error if encoding_errors.find { |e| error.message.include?(e) } error.message.split("\n").map { |m| m[/: (.+?)$/, 1] } - elsif skipped_errors.find { |e| error.message.include?(e) } - next else raise end @@ -111,19 +108,6 @@ def assert_regular_expression_encoding_flags(encoding, regexps) end end - # TODO (nirvdrum 22-Feb-2024): Remove this workaround once Prism better maps CRuby's error messages. - # This class of error message is tricky. The part not being compared is a representation of the regexp. - # Depending on the source encoding and any encoding modifiers being used, CRuby alters how the regexp is represented. - # Sometimes it's an MBC string. Other times it uses hexadecimal character escapes. And in other cases it uses - # the long-form Unicode escape sequences. This short-circuit checks that the error message is mostly correct. - if expected.is_a?(Array) && actual.is_a?(Array) - if expected.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") && - actual.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") - expected.pop - actual.pop - end - end - assert_equal expected, actual end end From 1d6a9669dcae8d7a227146d0ad9e4f49f0ff0499 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 11 Mar 2026 00:36:52 -0400 Subject: [PATCH 105/289] Fix reading past end of target names --- src/regexp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/regexp.c b/src/regexp.c index 23495a35e7..93711d6b94 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -436,7 +436,7 @@ typedef enum { */ static inline bool pm_regexp_property_name_matches(const uint8_t *name, size_t length, const char *target) { - return target[length] == '\0' && pm_strncasecmp(name, (const uint8_t *) target, length) == 0; + return strlen(target) == length && pm_strncasecmp(name, (const uint8_t *) target, length) == 0; } /** From 2e58c5219664f89e72b5834ca716fb0daaf08b87 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 11 Mar 2026 12:40:21 -0400 Subject: [PATCH 106/289] Track newlines in character escape sequences --- src/prism.c | 5 +++++ test/prism/newline_offsets_test.rb | 27 +++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/prism.c b/src/prism.c index d196c5d7c4..9d58bdb43d 100644 --- a/src/prism.c +++ b/src/prism.c @@ -8594,6 +8594,7 @@ escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_ } if (width == 1) { + if (*parser->current.end == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(*parser->current.end++, flags)); } else if (width > 1) { // Valid multibyte character. Just ignore escape. @@ -8910,6 +8911,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } + if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL)); return; @@ -8968,6 +8970,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } + if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL)); return; @@ -9021,6 +9024,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } + if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META)); return; @@ -9028,6 +9032,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } case '\r': { if (peek_offset(parser, 1) == '\n') { + pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 2); parser->current.end += 2; escape_write_byte_encoded(parser, buffer, flags, escape_byte('\n', flags)); return; diff --git a/test/prism/newline_offsets_test.rb b/test/prism/newline_offsets_test.rb index 99b808b1df..bb06876a96 100644 --- a/test/prism/newline_offsets_test.rb +++ b/test/prism/newline_offsets_test.rb @@ -8,15 +8,38 @@ class NewlineOffsetsTest < TestCase define_method(fixture.test_name) { assert_newline_offsets(fixture) } end + def test_escape_control_newline + # Newlines consumed inside escape sequences like \C-, \c, and \M- + # must be tracked in line offsets across all literal types. + %w[\\C- \\c \\M-].each do |escape| + assert_newline_offsets_for("\"#{escape}\n\"", "#{escape} in string") + assert_newline_offsets_for("`#{escape}\n`", "#{escape} in xstring") + assert_newline_offsets_for("/#{escape}\n/", "#{escape} in regexp") + assert_newline_offsets_for("%Q{#{escape}\n}", "#{escape} in %Q") + assert_newline_offsets_for("%W[#{escape}\n]", "#{escape} in %W") + assert_newline_offsets_for("<<~H\n#{escape}\n\nH\n", "#{escape} in heredoc") + assert_newline_offsets_for("?#{escape}\n", "#{escape} in char literal") + end + + # Combined meta + control escapes + assert_newline_offsets_for("\"\\M-\\C-\n\"", "\\M-\\C- in string") + assert_newline_offsets_for("\"\\M-\\c\n\"", "\\M-\\c in string") + + # \r\n consumed inside escape context + assert_newline_offsets_for("\"\\C-\r\n\"", "\\C- with \\r\\n") + end + private def assert_newline_offsets(fixture) - source = fixture.read + assert_newline_offsets_for(fixture.read) + end + def assert_newline_offsets_for(source, message = nil) expected = [0] source.b.scan("\n") { expected << $~.offset(0)[0] + 1 } - assert_equal expected, Prism.parse(source).source.offsets + assert_equal expected, Prism.parse(source).source.offsets, message end end end From 3bdd79257b2524a5f51a582aaf552890c5fbb548 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 11 Mar 2026 13:47:11 -0400 Subject: [PATCH 107/289] Improve pm_regexp_classify_property perf --- src/regexp.c | 84 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/src/regexp.c b/src/regexp.c index 93711d6b94..f864e187c9 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -430,15 +430,6 @@ typedef enum { PM_REGEXP_PROPERTY_UNICODE } pm_regexp_property_type_t; -/** - * Check if a property name matches a NUL-terminated target string - * (case-insensitive, exact length match). - */ -static inline bool -pm_regexp_property_name_matches(const uint8_t *name, size_t length, const char *target) { - return strlen(target) == length && pm_strncasecmp(name, (const uint8_t *) target, length) == 0; -} - /** * Classify a property name. The name may start with '^' for negation, which * is skipped before matching. @@ -451,30 +442,63 @@ pm_regexp_classify_property(const uint8_t *name, size_t length) { length--; } - // POSIX properties — valid in all encodings. - static const char *const posix_properties[] = { - "Alnum", "Alpha", "ASCII", "Blank", "Cntrl", "Digit", "Graph", - "Lower", "Print", "Punct", "Space", "Upper", "XDigit", "Word", - NULL - }; +#define PM_REGEXP_CASECMP(str_) (pm_strncasecmp(name, (const uint8_t *) (str_), length) == 0) - for (const char *const *property = posix_properties; *property != NULL; property++) { - if (pm_regexp_property_name_matches(name, length, *property)) { - return PM_REGEXP_PROPERTY_POSIX; - } + switch (length) { + case 3: + if (PM_REGEXP_CASECMP("Han")) return PM_REGEXP_PROPERTY_SCRIPT; + break; + case 4: + if (PM_REGEXP_CASECMP("Word")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 5: + /* Most properties are length 5, so dispatch on first character. */ + switch (name[0] | 0x20) { + case 'a': + if (PM_REGEXP_CASECMP("Alnum")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Alpha")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("ASCII")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'b': + if (PM_REGEXP_CASECMP("Blank")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'c': + if (PM_REGEXP_CASECMP("Cntrl")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'd': + if (PM_REGEXP_CASECMP("Digit")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'g': + if (PM_REGEXP_CASECMP("Graph")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Greek")) return PM_REGEXP_PROPERTY_SCRIPT; + break; + case 'l': + if (PM_REGEXP_CASECMP("Lower")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Latin")) return PM_REGEXP_PROPERTY_SCRIPT; + break; + case 'p': + if (PM_REGEXP_CASECMP("Print")) return PM_REGEXP_PROPERTY_POSIX; + if (PM_REGEXP_CASECMP("Punct")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 's': + if (PM_REGEXP_CASECMP("Space")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 'u': + if (PM_REGEXP_CASECMP("Upper")) return PM_REGEXP_PROPERTY_POSIX; + break; + } + break; + case 6: + if (PM_REGEXP_CASECMP("XDigit")) return PM_REGEXP_PROPERTY_POSIX; + break; + case 8: + if (PM_REGEXP_CASECMP("Hiragana")) return PM_REGEXP_PROPERTY_SCRIPT; + if (PM_REGEXP_CASECMP("Katakana")) return PM_REGEXP_PROPERTY_SCRIPT; + if (PM_REGEXP_CASECMP("Cyrillic")) return PM_REGEXP_PROPERTY_SCRIPT; + break; } - // Script properties — valid in /e, /s, /u but not /n. - static const char *const script_properties[] = { - "Hiragana", "Katakana", "Han", "Latin", "Greek", "Cyrillic", - NULL - }; - - for (const char *const *property = script_properties; *property != NULL; property++) { - if (pm_regexp_property_name_matches(name, length, *property)) { - return PM_REGEXP_PROPERTY_SCRIPT; - } - } +#undef PM_REGEXP_CASECMP // Everything else is Unicode-only (general categories, other scripts, etc.). return PM_REGEXP_PROPERTY_UNICODE; From 82cb026a68a00f9d351ea03ae2c212ed71f0566f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 13 Mar 2026 11:32:17 -0400 Subject: [PATCH 108/289] Use the flags name for flags fields in JSON --- templates/src/node.c.erb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 5806742612..df59545129 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -173,7 +173,11 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no // Dump the <%= field.name %> field pm_buffer_append_byte(buffer, ','); + <%- if field.is_a?(Prism::Template::Flags) -%> + pm_buffer_append_string(buffer, "\"flags\":", 8); + <%- else -%> pm_buffer_append_string(buffer, "\"<%= field.name %>\":", <%= field.name.bytesize + 3 %>); + <%- end -%> <%- case field -%> <%- when Prism::Template::NodeField -%> pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>); From 0f1500ce92deccfa914c1048cda9aa64c7910e90 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 13 Mar 2026 11:29:29 -0400 Subject: [PATCH 109/289] Expose parse options to Rust --- include/prism/util/pm_string.h | 2 +- rust/ruby-prism-sys/build/main.rs | 21 ++ rust/ruby-prism/src/lib.rs | 399 ++++++++++++++++++++++++++++-- 3 files changed, 406 insertions(+), 16 deletions(-) diff --git a/include/prism/util/pm_string.h b/include/prism/util/pm_string.h index d8456ff294..76942180b6 100644 --- a/include/prism/util/pm_string.h +++ b/include/prism/util/pm_string.h @@ -94,7 +94,7 @@ void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length); * @param source The source of the string. * @param length The length of the string. */ -void pm_string_constant_init(pm_string_t *string, const char *source, size_t length); +PRISM_EXPORTED_FUNCTION void pm_string_constant_init(pm_string_t *string, const char *source, size_t length); /** * Represents the result of calling pm_string_mapped_init or diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 30da93ae6c..04109ac6e9 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -120,6 +120,9 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_type("pm_magic_comment_t") .allowlist_type("pm_node_t") .allowlist_type("pm_node_type") + .allowlist_type("pm_options_t") + .allowlist_type("pm_options_scope_t") + .allowlist_type("pm_options_version_t") .allowlist_type("pm_parser_t") .allowlist_type("pm_string_t") .allowlist_type(r"^pm_\w+_node_t") @@ -128,20 +131,38 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .rustified_non_exhaustive_enum("pm_comment_type_t") .rustified_non_exhaustive_enum(r"pm_\w+_flags") .rustified_non_exhaustive_enum("pm_node_type") + .rustified_non_exhaustive_enum("pm_options_version_t") // Functions .allowlist_function("pm_arena_free") .allowlist_function("pm_list_empty_p") .allowlist_function("pm_list_free") + .allowlist_function("pm_options_command_line_set") + .allowlist_function("pm_options_encoding_locked_set") + .allowlist_function("pm_options_encoding_set") + .allowlist_function("pm_options_filepath_set") + .allowlist_function("pm_options_free") + .allowlist_function("pm_options_frozen_string_literal_set") + .allowlist_function("pm_options_line_set") + .allowlist_function("pm_options_main_script_set") + .allowlist_function("pm_options_partial_script_set") + .allowlist_function("pm_options_scope_forwarding_set") + .allowlist_function("pm_options_scope_get") + .allowlist_function("pm_options_scope_init") + .allowlist_function("pm_options_scope_local_get") + .allowlist_function("pm_options_scopes_init") .allowlist_function("pm_parse") .allowlist_function("pm_parser_free") .allowlist_function("pm_parser_init") .allowlist_function("pm_size_to_native") + .allowlist_function("pm_string_constant_init") .allowlist_function("pm_string_free") .allowlist_function("pm_string_length") .allowlist_function("pm_string_source") .allowlist_function("pm_version") // Vars .allowlist_var(r"^pm_encoding\S+") + .allowlist_var(r"^PM_OPTIONS_COMMAND_LINE_\w+") + .allowlist_var(r"^PM_OPTIONS_SCOPE_FORWARDING_\w+") .generate() .expect("Unable to generate prism bindings") } diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 37a14c80ec..a11ca9fbee 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -16,6 +16,7 @@ mod bindings { mod node; mod parse_result; +use std::ffi::CString; use std::mem::MaybeUninit; use std::ptr::NonNull; @@ -23,7 +24,328 @@ pub use self::bindings::*; pub use self::node::{ConstantId, ConstantList, ConstantListIter, Integer, NodeList, NodeListIter}; pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnostics, Location, MagicComment, MagicComments, ParseResult}; -use ruby_prism_sys::{pm_arena_t, pm_parse, pm_parser_init, pm_parser_t}; +use ruby_prism_sys::{ + pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_free, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_partial_script_set, pm_options_scope_forwarding_set, + pm_options_scope_get, pm_options_scope_init, pm_options_scope_local_get, pm_options_scopes_init, pm_options_t, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, +}; + +/// The version of Ruby syntax to parse with. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Version { + /// Use the latest version of prism. + Latest, + /// The vendored version of prism in `CRuby` 3.3.x. + CRuby3_3, + /// The vendored version of prism in `CRuby` 3.4.x. + CRuby3_4, + /// The vendored version of prism in `CRuby` 3.5.x / 4.0.x. + CRuby3_5, + /// The vendored version of prism in `CRuby` 4.1.x. + CRuby4_1, +} + +impl From for ruby_prism_sys::pm_options_version_t { + fn from(version: Version) -> Self { + match version { + Version::Latest => Self::PM_OPTIONS_VERSION_LATEST, + Version::CRuby3_3 => Self::PM_OPTIONS_VERSION_CRUBY_3_3, + Version::CRuby3_4 => Self::PM_OPTIONS_VERSION_CRUBY_3_4, + Version::CRuby3_5 => Self::PM_OPTIONS_VERSION_CRUBY_3_5, + Version::CRuby4_1 => Self::PM_OPTIONS_VERSION_CRUBY_4_1, + } + } +} + +/// A command line option that affects parsing behavior. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum CommandLineFlag { + /// `-a`: splits the input line `$_` into `$F`. + A, + /// `-e`: specifies a script to be executed. + E, + /// `-l`: chomps the input line by default. + L, + /// `-n`: wraps the script in a `while gets` loop. + N, + /// `-p`: prints the value of `$_` at the end of each loop. + P, + /// `-x`: searches the input file for a shebang. + X, +} + +impl From for u8 { + fn from(flag: CommandLineFlag) -> Self { + match flag { + CommandLineFlag::A => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_A, + CommandLineFlag::E => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_E, + CommandLineFlag::L => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_L, + CommandLineFlag::N => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_N, + CommandLineFlag::P => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_P, + CommandLineFlag::X => ruby_prism_sys::PM_OPTIONS_COMMAND_LINE_X, + } + } +} + +/// A forwarding parameter for a scope. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ScopeForwardingFlag { + /// Forwarding with the `*` parameter. + Positionals, + /// Forwarding with the `**` parameter. + Keywords, + /// Forwarding with the `&` parameter. + Block, + /// Forwarding with the `...` parameter. + All, +} + +impl From for u8 { + fn from(flag: ScopeForwardingFlag) -> Self { + match flag { + ScopeForwardingFlag::Positionals => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS, + ScopeForwardingFlag::Keywords => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS, + ScopeForwardingFlag::Block => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_BLOCK, + ScopeForwardingFlag::All => ruby_prism_sys::PM_OPTIONS_SCOPE_FORWARDING_ALL, + } + } +} + +/// A scope of locals surrounding the code that is being parsed. +#[derive(Debug, Clone, Default)] +pub struct Scope { + locals: Vec>, + forwarding: Vec, +} + +impl Scope { + /// Sets the local variable names in this scope. + #[must_use] + pub fn locals(mut self, locals: Vec>) -> Self { + self.locals = locals; + self + } + + /// Sets the forwarding parameters in this scope. + #[must_use] + pub fn forwarding(mut self, forwarding: Vec) -> Self { + self.forwarding = forwarding; + self + } +} + +/// Options that can be passed to the parser. +#[derive(Debug, Clone, Default)] +pub struct Options { + filepath: Option, + line: Option, + encoding: Option, + encoding_locked: bool, + frozen_string_literal: Option, + command_line: Vec, + version: Option, + main_script: bool, + partial_script: bool, + scopes: Vec, +} + +impl Options { + /// Sets the filepath option. + #[must_use] + pub fn filepath(mut self, filepath: &str) -> Self { + self.filepath = Some(filepath.to_string()); + self + } + + /// Sets the line option. + #[must_use] + pub const fn line(mut self, line: i32) -> Self { + self.line = Some(line); + self + } + + /// Sets the encoding option. + #[must_use] + pub fn encoding(mut self, encoding: &str) -> Self { + self.encoding = Some(encoding.to_string()); + self + } + + /// Sets the encoding locked option. + #[must_use] + pub const fn encoding_locked(mut self, locked: bool) -> Self { + self.encoding_locked = locked; + self + } + + /// Sets the frozen string literal option. `Some(true)` freezes string + /// literals, `Some(false)` keeps them mutable, and `None` leaves the + /// option unset. + #[must_use] + pub const fn frozen_string_literal(mut self, frozen: Option) -> Self { + self.frozen_string_literal = frozen; + self + } + + /// Sets the command line flags. + #[must_use] + pub fn command_line(mut self, command_line: Vec) -> Self { + self.command_line = command_line; + self + } + + /// Sets the version option. + #[must_use] + pub const fn version(mut self, version: Version) -> Self { + self.version = Some(version); + self + } + + /// Sets the main script option. + #[must_use] + pub const fn main_script(mut self, main_script: bool) -> Self { + self.main_script = main_script; + self + } + + /// Sets the partial script option. + #[must_use] + pub const fn partial_script(mut self, partial_script: bool) -> Self { + self.partial_script = partial_script; + self + } + + /// Adds a scope to the options. + #[must_use] + pub fn scope(mut self, scope: Scope) -> Self { + self.scopes.push(scope); + self + } + + /// Sets the scopes, replacing any previously added scopes. + #[must_use] + pub fn scopes(mut self, scopes: Vec) -> Self { + self.scopes = scopes; + self + } + + /// Builds the C-level parse options from these options. The returned + /// `ParseOptions` must outlive any `ParseResult` created from it. + /// + /// # Panics + /// + /// Panics if `filepath` or `encoding` contain interior null bytes. + #[must_use] + pub fn build(self) -> ParseOptions { + let mut opts = pm_options_t::default(); + + let c_filepath = self.filepath.map(|filepath| { + let cstring = CString::new(filepath).unwrap(); + unsafe { pm_options_filepath_set(&raw mut opts, cstring.as_ptr()) }; + cstring + }); + + if let Some(line) = self.line { + unsafe { pm_options_line_set(&raw mut opts, line) }; + } + + let c_encoding = self.encoding.map(|encoding| { + let cstring = CString::new(encoding).unwrap(); + unsafe { pm_options_encoding_set(&raw mut opts, cstring.as_ptr()) }; + cstring + }); + + if self.encoding_locked { + unsafe { pm_options_encoding_locked_set(&raw mut opts, true) }; + } + + if let Some(frozen) = self.frozen_string_literal { + unsafe { pm_options_frozen_string_literal_set(&raw mut opts, frozen) }; + } + + let command_line = self.command_line.iter().fold(0u8, |acc, &flag| acc | u8::from(flag)); + if command_line != 0 { + unsafe { pm_options_command_line_set(&raw mut opts, command_line) }; + } + + if let Some(version) = self.version { + opts.version = version.into(); + } + + if self.main_script { + unsafe { pm_options_main_script_set(&raw mut opts, true) }; + } + + if self.partial_script { + unsafe { pm_options_partial_script_set(&raw mut opts, true) }; + } + + if !self.scopes.is_empty() { + unsafe { pm_options_scopes_init(&raw mut opts, self.scopes.len()) }; + + for (scope_index, scope) in self.scopes.iter().enumerate() { + let pm_scope = unsafe { pm_options_scope_get(&raw const opts, scope_index).cast_mut() }; + unsafe { pm_options_scope_init(pm_scope, scope.locals.len()) }; + + for (local_index, local) in scope.locals.iter().enumerate() { + let pm_local = unsafe { pm_options_scope_local_get(pm_scope, local_index).cast_mut() }; + unsafe { pm_string_constant_init(pm_local, local.as_ptr().cast::(), local.len()) }; + } + + let forwarding = scope.forwarding.iter().fold(0u8, |acc, &flag| acc | u8::from(flag)); + if forwarding != 0 { + unsafe { pm_options_scope_forwarding_set(pm_scope, forwarding) }; + } + } + } + + ParseOptions { + options: opts, + _filepath: c_filepath, + _encoding: c_encoding, + _scopes: self.scopes, + } + } +} + +/// The C-level parse options. Created from [`Options::build`]. Must outlive +/// any [`ParseResult`] created with [`parse_with_options`]. +#[derive(Debug)] +pub struct ParseOptions { + options: pm_options_t, + // These CStrings back the constant pm_string_t values inside `options`. + // They must not be dropped before `options` is freed. + _filepath: Option, + _encoding: Option, + // The scopes data that pm_string_t values point into. + _scopes: Vec, +} + +impl Drop for ParseOptions { + fn drop(&mut self) { + unsafe { pm_options_free(&raw mut self.options) }; + } +} + +/// Initializes a parser, parses the source, and returns the result. +/// +/// # Safety +/// +/// `options` must be a valid pointer to a `pm_options_t` or null. +unsafe fn parse_impl(source: &[u8], options: *const pm_options_t) -> ParseResult<'_> { + let mut arena = Box::new(MaybeUninit::::zeroed().assume_init()); + let uninit = Box::new(MaybeUninit::::uninit()); + let uninit = Box::into_raw(uninit); + + pm_parser_init(arena.as_mut(), (*uninit).as_mut_ptr(), source.as_ptr(), source.len(), options); + + let parser = (*uninit).assume_init_mut(); + let parser = NonNull::new_unchecked(parser); + + let node = pm_parse(parser.as_ptr()); + let node = NonNull::new_unchecked(node); + + ParseResult::new(source, arena, parser, node) +} /// Parses the given source string and returns a parse result. /// @@ -33,21 +355,19 @@ use ruby_prism_sys::{pm_arena_t, pm_parse, pm_parser_init, pm_parser_t}; /// #[must_use] pub fn parse(source: &[u8]) -> ParseResult<'_> { - unsafe { - let mut arena = Box::new(MaybeUninit::::zeroed().assume_init()); - let uninit = Box::new(MaybeUninit::::uninit()); - let uninit = Box::into_raw(uninit); - - pm_parser_init(arena.as_mut(), (*uninit).as_mut_ptr(), source.as_ptr(), source.len(), std::ptr::null()); - - let parser = (*uninit).assume_init_mut(); - let parser = NonNull::new_unchecked(parser); - - let node = pm_parse(parser.as_ptr()); - let node = NonNull::new_unchecked(node); + unsafe { parse_impl(source, std::ptr::null()) } +} - ParseResult::new(source, arena, parser, node) - } +/// Parses the given source string with the given options and returns a parse +/// result. The `options` must outlive the returned `ParseResult`. +/// +/// # Panics +/// +/// Panics if the parser fails to initialize. +/// +#[must_use] +pub fn parse_with_options<'a>(source: &'a [u8], options: &'a ParseOptions) -> ParseResult<'a> { + unsafe { parse_impl(source, &raw const options.options) } } #[cfg(test)] @@ -743,6 +1063,55 @@ end assert_eq!(3, extractor.scopes.len()); } + #[test] + fn parse_with_options_frozen_string_literal_test() { + use super::{parse_with_options, Options}; + + let source = b"\"foo\""; + let options = Options::default().frozen_string_literal(Some(true)).build(); + let result = parse_with_options(source, &options); + + let node = result.node(); + let string = node.as_program_node().unwrap().statements().body().iter().next().unwrap(); + let string = string.as_string_node().unwrap(); + assert!(string.is_frozen()); + } + + #[test] + fn parse_with_options_filepath_test() { + use super::{parse_with_options, Options}; + + let source = b"__FILE__"; + let options = Options::default().filepath("test.rb").build(); + let result = parse_with_options(source, &options); + assert!(result.errors().next().is_none()); + } + + #[test] + fn parse_with_options_line_test() { + use super::{parse_with_options, Options}; + + let source = b"1 + 2"; + let options = Options::default().line(10).build(); + let result = parse_with_options(source, &options); + assert!(result.errors().next().is_none()); + } + + #[test] + fn parse_with_options_scopes_test() { + use super::{parse_with_options, Options, Scope}; + + let source = b"x"; + let scope = Scope::default().locals(vec![b"x".to_vec()]); + let options = Options::default().scope(scope).build(); + let result = parse_with_options(source, &options); + assert!(result.errors().next().is_none()); + + let node = result.node(); + let stmt = node.as_program_node().unwrap().statements().body().iter().next().unwrap(); + assert!(stmt.as_local_variable_read_node().is_some()); + } + #[test] fn malformed_shebang() { let source = "#!\x00"; From 4258b2ad7e8d9cb2df871c95bdfa74517118c4b6 Mon Sep 17 00:00:00 2001 From: Seong Yong-ju Date: Wed, 4 Mar 2026 18:13:56 +0900 Subject: [PATCH 110/289] feat: add `start_line`, `end_line`, `start_column`, `end_column`, and `chop` methods for `Location` Co-Authored-By: Kevin Newton --- include/prism/util/pm_line_offset_list.h | 2 +- rust/ruby-prism-sys/build/main.rs | 15 +++++++ rust/ruby-prism/src/lib.rs | 44 +++++++++++++++++++- rust/ruby-prism/src/parse_result/mod.rs | 52 +++++++++++++++++++++++- 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index fe16e0b034..968eeae52d 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -96,7 +96,7 @@ int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cur * @param start_line The line to start counting from. * @return The line and column of the given offset. */ -pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); +PRISM_EXPORTED_FUNCTION pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); /** * Free the internal memory allocated for the list. diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 04109ac6e9..50a8f51d6c 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -9,6 +9,7 @@ fn main() { let ruby_build_path = prism_lib_path(); let ruby_include_path = prism_include_path(); + emit_rerun_hints(&ruby_include_path); // Tell cargo/rustc that we want to link against `libprism.a`. println!("cargo:rustc-link-lib=static=prism"); @@ -23,6 +24,19 @@ fn main() { write_bindings(&bindings); } +fn emit_rerun_hints(ruby_include_path: &Path) { + println!("cargo:rerun-if-env-changed=PRISM_INCLUDE_DIR"); + println!("cargo:rerun-if-env-changed=PRISM_LIB_DIR"); + println!("cargo:rerun-if-changed={}", ruby_include_path.display()); + + if let Some(project_root) = ruby_include_path.parent() { + let src_path = project_root.join("src"); + if src_path.exists() { + println!("cargo:rerun-if-changed={}", src_path.display()); + } + } +} + /// Gets the path to project files (`libprism*`) at `[root]/build/`. /// fn prism_lib_path() -> PathBuf { @@ -134,6 +148,7 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .rustified_non_exhaustive_enum("pm_options_version_t") // Functions .allowlist_function("pm_arena_free") + .allowlist_function("pm_line_offset_list_line_column") .allowlist_function("pm_list_empty_p") .allowlist_function("pm_list_free") .allowlist_function("pm_options_command_line_set") diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index a11ca9fbee..65e7be1610 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -448,7 +448,7 @@ mod tests { } #[test] - fn location_test() { + fn location_slice_test() { let source = "111 + 222 + 333"; let result = parse(source.as_ref()); @@ -502,6 +502,48 @@ mod tests { assert_eq!(slice, "222"); } + #[test] + fn location_line_column_test() { + let source = "first\nsecond\nthird"; + let result = parse(source.as_ref()); + + let node = result.node(); + let program = node.as_program_node().unwrap(); + let statements = program.statements().body(); + let mut iter = statements.iter(); + + let _first = iter.next().unwrap(); + let second = iter.next().unwrap(); + let third = iter.next().unwrap(); + + let second_loc = second.location(); + assert_eq!(second_loc.start_line(), 2); + assert_eq!(second_loc.end_line(), 2); + assert_eq!(second_loc.start_column(), 0); + assert_eq!(second_loc.end_column(), 6); + + let third_loc = third.location(); + assert_eq!(third_loc.start_line(), 3); + assert_eq!(third_loc.end_line(), 3); + assert_eq!(third_loc.start_column(), 0); + assert_eq!(third_loc.end_column(), 5); + } + + #[test] + fn location_chop_test() { + let result = parse(b"foo"); + let mut location = result.node().as_program_node().unwrap().location(); + + assert_eq!(location.chop().as_slice(), b"fo"); + assert_eq!(location.chop().chop().chop().as_slice(), b""); + + // Check that we don't go negative. + for _ in 0..10 { + location = location.chop(); + } + assert_eq!(location.as_slice(), b""); + } + #[test] fn visitor_test() { use super::{visit_interpolated_regular_expression_node, visit_regular_expression_node, InterpolatedRegularExpressionNode, RegularExpressionNode, Visit}; diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index d186ced7ec..4576b0fe62 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -8,7 +8,7 @@ mod diagnostics; use std::ptr::NonNull; -use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_free, pm_parser_t}; +use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_free, pm_parser_t}; pub use self::comments::{Comment, CommentType, Comments, MagicComment, MagicComments}; pub use self::diagnostics::{Diagnostic, Diagnostics}; @@ -66,6 +66,56 @@ impl<'pr> Location<'pr> { }) } } + + /// Returns a new location that is the result of chopping off the last byte. + #[must_use] + pub const fn chop(&self) -> Self { + Location { + parser: self.parser, + start: self.start, + length: if self.length == 0 { 0 } else { self.length - 1 }, + marker: std::marker::PhantomData, + } + } +} + +impl Location<'_> { + /// Returns the line number where this location starts. + #[must_use] + pub fn start_line(&self) -> i32 { + self.line_column(self.start).0 + } + + /// Returns the column number in bytes where this location starts from the + /// start of the line. + #[must_use] + pub fn start_column(&self) -> u32 { + self.line_column(self.start).1 + } + + /// Returns the line number where this location ends. + #[must_use] + pub fn end_line(&self) -> i32 { + self.line_column(self.end()).0 + } + + /// Returns the column number in bytes where this location ends from the + /// start of the line. + #[must_use] + pub fn end_column(&self) -> u32 { + self.line_column(self.end()).1 + } + + /// Returns the line and column number for the given byte offset. + fn line_column(&self, cursor: u32) -> (i32, u32) { + // SAFETY: We read the line_offsets and start_line from the parser, + // which is valid for the lifetime of this Location. + unsafe { + let parser = self.parser.as_ptr(); + let result = pm_line_offset_list_line_column(&raw const (*parser).line_offsets, cursor, (*parser).start_line); + (result.line, result.column) + } + } } impl std::fmt::Debug for Location<'_> { From 04b986f1a1345d63aa2eed3b91e734ea72628ad4 Mon Sep 17 00:00:00 2001 From: Seong Yong-ju Date: Thu, 29 Jan 2026 13:22:21 +0900 Subject: [PATCH 111/289] feat: add `node_ext` module with `full_name` methods for constant nodes Port Ruby's `node_ext.rb` functionality to Rust bindings, providing `full_name` and `full_name_parts` methods for `ConstantReadNode`, `ConstantWriteNode`, `ConstantTargetNode`, `ConstantPathNode`, and `ConstantPathTargetNode`. Co-Authored-By: Kevin Newton --- rust/ruby-prism/src/lib.rs | 2 + rust/ruby-prism/src/node_ext.rs | 250 ++++++++++++++++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 rust/ruby-prism/src/node_ext.rs diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 65e7be1610..2cb8446022 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -14,6 +14,7 @@ mod bindings { } mod node; +mod node_ext; mod parse_result; use std::ffi::CString; @@ -22,6 +23,7 @@ use std::ptr::NonNull; pub use self::bindings::*; pub use self::node::{ConstantId, ConstantList, ConstantListIter, Integer, NodeList, NodeListIter}; +pub use self::node_ext::{ConstantPathError, FullName}; pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnostics, Location, MagicComment, MagicComments, ParseResult}; use ruby_prism_sys::{ diff --git a/rust/ruby-prism/src/node_ext.rs b/rust/ruby-prism/src/node_ext.rs new file mode 100644 index 0000000000..8e61532315 --- /dev/null +++ b/rust/ruby-prism/src/node_ext.rs @@ -0,0 +1,250 @@ +//! Node extension methods for the prism parser. +//! +//! This module provides convenience methods on AST nodes that aren't generated +//! from the config, mirroring Ruby's `node_ext.rb`. + +use std::fmt; + +use crate::{ConstantPathNode, ConstantPathTargetNode, ConstantReadNode, ConstantTargetNode, ConstantWriteNode, Node}; + +/// Errors for constant path name computation. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ConstantPathError { + /// The constant path contains dynamic parts (e.g., `var::Bar::Baz`). + DynamicParts, + /// The constant path contains missing nodes (e.g., `Foo::`). + MissingNodes, +} + +impl fmt::Display for ConstantPathError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::DynamicParts => { + write!(f, "Constant path contains dynamic parts. Cannot compute full name") + }, + Self::MissingNodes => { + write!(f, "Constant path contains missing nodes. Cannot compute full name") + }, + } + } +} + +impl std::error::Error for ConstantPathError {} + +/// Trait for nodes that can compute their full constant name. +/// +/// Implemented by constant-related nodes (`ConstantReadNode`, +/// `ConstantWriteNode`, `ConstantTargetNode`, `ConstantPathNode`, and +/// `ConstantPathTargetNode`). +pub trait FullName<'pr> { + /// Returns the list of parts for the full name of this constant. + /// + /// # Errors + /// + /// Returns [`ConstantPathError`] if the path contains dynamic parts or + /// missing nodes. + fn full_name_parts(&self) -> Result, ConstantPathError>; + + /// Returns the full name of this constant. + /// + /// # Errors + /// + /// Returns [`ConstantPathError`] if the path contains dynamic parts or + /// missing nodes. + fn full_name(&self) -> Result, ConstantPathError> { + let parts = self.full_name_parts()?; + let mut result = Vec::new(); + for (index, part) in parts.iter().enumerate() { + if index > 0 { + result.extend_from_slice(b"::"); + } + result.extend_from_slice(part); + } + Ok(result) + } +} + +/// Computes `full_name_parts` for a `Node` by dispatching to the appropriate +/// `FullName` implementation. +#[allow(clippy::option_if_let_else)] +fn full_name_parts_for_node<'pr>(node: &Node<'pr>) -> Result, ConstantPathError> { + if let Some(path_node) = node.as_constant_path_node() { + path_node.full_name_parts() + } else if let Some(read_node) = node.as_constant_read_node() { + read_node.full_name_parts() + } else { + Err(ConstantPathError::DynamicParts) + } +} + +/// Computes `full_name_parts` for a constant path node given its name and +/// parent. +fn constant_path_full_name_parts<'pr>(name: Option>, parent: Option>) -> Result, ConstantPathError> { + let name = name.ok_or(ConstantPathError::MissingNodes)?; + + let mut parts = match parent { + Some(parent) => full_name_parts_for_node(&parent)?, + None => vec![b"".as_slice()], + }; + + parts.push(name.as_slice()); + Ok(parts) +} + +/// Implements `FullName` for simple constant nodes that have a `name()` method +/// returning a single constant identifier. +macro_rules! impl_simple_full_name { + ($node_type:ident) => { + impl<'pr> FullName<'pr> for $node_type<'pr> { + fn full_name_parts(&self) -> Result, ConstantPathError> { + Ok(vec![self.name().as_slice()]) + } + } + }; +} + +impl_simple_full_name!(ConstantReadNode); +impl_simple_full_name!(ConstantWriteNode); +impl_simple_full_name!(ConstantTargetNode); + +impl<'pr> FullName<'pr> for ConstantPathNode<'pr> { + fn full_name_parts(&self) -> Result, ConstantPathError> { + constant_path_full_name_parts(self.name(), self.parent()) + } +} + +impl<'pr> FullName<'pr> for ConstantPathTargetNode<'pr> { + fn full_name_parts(&self) -> Result, ConstantPathError> { + constant_path_full_name_parts(self.name(), self.parent()) + } +} + +#[cfg(test)] +mod tests { + use super::{ConstantPathError, FullName}; + use crate::parse; + + #[test] + fn test_full_name_for_constant_read_node() { + let result = parse(b"Foo"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant = node.as_constant_read_node().unwrap(); + + assert_eq!(constant.full_name_parts().unwrap(), vec![b"Foo".as_slice()]); + assert_eq!(constant.full_name().unwrap(), b"Foo"); + } + + #[test] + fn test_full_name_for_constant_write_node() { + let result = parse(b"Foo = 1"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant = node.as_constant_write_node().unwrap(); + + assert_eq!(constant.full_name_parts().unwrap(), vec![b"Foo".as_slice()]); + assert_eq!(constant.full_name().unwrap(), b"Foo"); + } + + #[test] + fn test_full_name_for_constant_target_node() { + let result = parse(b"Foo, Bar = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant = target.as_constant_target_node().unwrap(); + + assert_eq!(constant.full_name_parts().unwrap(), vec![b"Foo".as_slice()]); + assert_eq!(constant.full_name().unwrap(), b"Foo"); + } + + #[test] + fn test_full_name_for_constant_path() { + let result = parse(b"Foo::Bar"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"Foo".as_slice(), b"Bar".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"Foo::Bar"); + } + + #[test] + fn test_full_name_for_constant_path_with_stovetop() { + let result = parse(b"::Foo::Bar"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"".as_slice(), b"Foo".as_slice(), b"Bar".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"::Foo::Bar"); + } + + #[test] + fn test_full_name_for_constant_path_with_self() { + let source = r" +self:: + Bar::Baz:: + Qux +"; + let result = parse(source.as_bytes()); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::DynamicParts); + } + + #[test] + fn test_full_name_for_constant_path_with_variable() { + let source = r" +foo:: + Bar::Baz:: + Qux +"; + let result = parse(source.as_bytes()); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::DynamicParts); + } + + #[test] + fn test_full_name_for_constant_path_with_missing_name() { + let result = parse(b"Foo::"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let constant_path = node.as_constant_path_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::MissingNodes); + } + + #[test] + fn test_full_name_for_constant_path_target() { + let result = parse(b"Foo::Bar, Baz = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant_path = target.as_constant_path_target_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"Foo".as_slice(), b"Bar".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"Foo::Bar"); + } + + #[test] + fn test_full_name_for_constant_path_target_with_stovetop() { + let result = parse(b"::Foo, Bar = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant_path = target.as_constant_path_target_node().unwrap(); + + assert_eq!(constant_path.full_name_parts().unwrap(), vec![b"".as_slice(), b"Foo".as_slice()]); + assert_eq!(constant_path.full_name().unwrap(), b"::Foo"); + } + + #[test] + fn test_full_name_for_constant_path_target_with_self() { + let result = parse(b"self::Foo, Bar = [1, 2]"); + let node = result.node().as_program_node().unwrap().statements().body().iter().next().unwrap(); + let multi_write = node.as_multi_write_node().unwrap(); + let target = multi_write.lefts().iter().next().unwrap(); + let constant_path = target.as_constant_path_target_node().unwrap(); + + assert_eq!(constant_path.full_name().unwrap_err(), ConstantPathError::DynamicParts); + } +} From 660b0f7c7d75315d98684b8938eb66d99b30ed03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:31:22 +0000 Subject: [PATCH 112/289] Bump actions/create-github-app-token in the action-deps group Bumps the action-deps group with 1 update: [actions/create-github-app-token](https://github.com/actions/create-github-app-token). Updates `actions/create-github-app-token` from 2 to 3 - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Commits](https://github.com/actions/create-github-app-token/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/create-github-app-token dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major dependency-group: action-deps ... Signed-off-by: dependabot[bot] --- .github/workflows/sync-ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-ruby.yml b/.github/workflows/sync-ruby.yml index 66a736ed85..72be2a09c5 100644 --- a/.github/workflows/sync-ruby.yml +++ b/.github/workflows/sync-ruby.yml @@ -12,7 +12,7 @@ jobs: - name: Create GitHub App token id: app-token - uses: actions/create-github-app-token@v2 + uses: actions/create-github-app-token@v3 with: app-id: 2060836 private-key: ${{ secrets.RUBY_SYNC_DEFAULT_GEMS_PRIVATE_KEY }} From 572f35ff01034776e8303ea45fa0966a1e59397d Mon Sep 17 00:00:00 2001 From: Reese Williams Date: Mon, 16 Mar 2026 14:18:37 -0500 Subject: [PATCH 113/289] [rust] Expose `start` offsets --- rust/ruby-prism/src/lib.rs | 1 + rust/ruby-prism/src/parse_result/mod.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 2cb8446022..3725633378 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -465,6 +465,7 @@ mod tests { assert_eq!(slice, "222"); assert_eq!(6, location.start); + assert_eq!(location.start, location.start()); assert_eq!(9, location.end()); let recv_loc = plus.receiver().unwrap().location(); diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index 4576b0fe62..b0e7197707 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -44,6 +44,12 @@ impl<'pr> Location<'pr> { } } + /// Returns the start offset from the beginning of the parsed source. + #[must_use] + pub const fn start(&self) -> u32 { + self.start + } + /// Returns the end offset from the beginning of the parsed source. #[must_use] pub const fn end(&self) -> u32 { From fb80fe219c02d13a9e3bf7b4736f5e63dc6bae94 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 16 Mar 2026 20:32:35 +0100 Subject: [PATCH 114/289] Do not pass source bytes to Loader.java at all * That way we are sure it's not retained by it. * Source#bytes seems to have no usages. * Arrays.binarySearch() works just fine if the value is > the last array element. --- .../main/java/org/jruby/parser/prism/wasm/Prism.java | 2 +- rakelib/serialization.rake | 3 +-- templates/java/org/ruby_lang/prism/Loader.java.erb | 10 ++++------ templates/java/org/ruby_lang/prism/Nodes.java.erb | 5 +---- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java index 6dd89c70cb..67a127276c 100644 --- a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java +++ b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java @@ -83,7 +83,7 @@ public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLeng public ParseResult serializeParse(byte[] packedOptions, String source) { var sourceBytes = source.getBytes(StandardCharsets.ISO_8859_1); byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length); - return Loader.load(result, sourceBytes); + return Loader.load(result); } @Override diff --git a/rakelib/serialization.rake b/rakelib/serialization.rake index 499be443ce..516e8fe5ba 100644 --- a/rakelib/serialization.rake +++ b/rakelib/serialization.rake @@ -25,8 +25,7 @@ task "test:java_loader:internal" => :compile do puts puts path serialized = Prism.dump_file(path) - source_bytes = File.binread(path).unpack('c*') - parse_result = org.ruby_lang.prism.Loader.load(serialized.unpack('c*'), source_bytes) + parse_result = org.ruby_lang.prism.Loader.load(serialized.unpack('c*')) puts parse_result.value end end diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index e2fe114ca9..4149628bf1 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -15,8 +15,8 @@ import java.util.Locale; // @formatter:off public class Loader { - public static ParseResult load(byte[] serialized, byte[] sourceBytes) { - return new Loader(serialized).load(sourceBytes); + public static ParseResult load(byte[] serialized) { + return new Loader(serialized).load(); } // Overridable methods @@ -81,10 +81,8 @@ public class Loader { this.buffer = ByteBuffer.wrap(serialized).order(ByteOrder.nativeOrder()); } - // We pass sourceBytes here and not in the constructor to avoid keeping - // the sourceBytes in memory unnecessarily with lazy DefNode's which hold on the Loader. - protected ParseResult load(byte[] sourceBytes) { - Nodes.Source source = new Nodes.Source(sourceBytes); + protected ParseResult load() { + Nodes.Source source = new Nodes.Source(); expect((byte) 'P', "incorrect prism header"); expect((byte) 'R', "incorrect prism header"); diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index e234faa6f5..de597eea67 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -47,12 +47,10 @@ public abstract class Nodes { } public static final class Source { - public final byte[] bytes; private int startLine = 1; private int[] lineOffsets = null; - Source(byte[] bytes) { - this.bytes = bytes; + Source() { } void setStartLine(int startLine) { @@ -70,7 +68,6 @@ public abstract class Nodes { // 0-based public int findLine(int byteOffset) { - if (byteOffset >= bytes.length) byteOffset = bytes.length - 1; assert byteOffset >= 0 : byteOffset; int index = Arrays.binarySearch(lineOffsets, byteOffset); int line; From 96edaf3d4093ffcf32593d55e3ce27314c41ebe5 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 16 Mar 2026 20:47:25 +0100 Subject: [PATCH 115/289] Mark newlines for lazy DefNodes * By running the MarkNewlinesVisitor on them when they are lazily loaded. * See https://github.com/ruby/prism/pull/3983. * Achieves the same nodes as with eager DefNode. --- .../org/ruby_lang/prism/MarkNewlinesVisitor.java | 4 ++-- .../java/org/ruby_lang/prism/Loader.java.erb | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/java/org/ruby_lang/prism/MarkNewlinesVisitor.java b/java/org/ruby_lang/prism/MarkNewlinesVisitor.java index 8d08424942..148b0d1a2e 100644 --- a/java/org/ruby_lang/prism/MarkNewlinesVisitor.java +++ b/java/org/ruby_lang/prism/MarkNewlinesVisitor.java @@ -6,9 +6,9 @@ final class MarkNewlinesVisitor extends AbstractNodeVisitor { private final Nodes.Source source; private boolean[] newlineMarked; - MarkNewlinesVisitor(Nodes.Source source, boolean[] newlineMarked) { + MarkNewlinesVisitor(Nodes.Source source) { this.source = source; - this.newlineMarked = newlineMarked; + this.newlineMarked = new boolean[1 + source.getLineCount()]; } @Override diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 4149628bf1..534d8401ca 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,8 +1,6 @@ <%- string_type = Prism::Template::JAVA_STRING_TYPE -%> package org.ruby_lang.prism; -import org.ruby_lang.prism.Nodes; - import java.lang.Short; import java.math.BigInteger; import java.nio.ByteBuffer; @@ -76,13 +74,14 @@ public class Loader { private Charset encodingCharset; <%- end -%> private ConstantPool constantPool; + private Nodes.Source source = null; protected Loader(byte[] serialized) { this.buffer = ByteBuffer.wrap(serialized).order(ByteOrder.nativeOrder()); } protected ParseResult load() { - Nodes.Source source = new Nodes.Source(); + this.source = new Nodes.Source(); expect((byte) 'P', "incorrect prism header"); expect((byte) 'R', "incorrect prism header"); @@ -127,8 +126,7 @@ public class Loader { throw new Error("Expected to consume all bytes while deserializing but there were " + left + " bytes left"); } - boolean[] newlineMarked = new boolean[1 + source.getLineCount()]; - MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source, newlineMarked); + MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source); node.accept(visitor); } else { node = null; @@ -407,11 +405,17 @@ public class Loader { } Nodes.DefNode createDefNodeFromSavedPosition(<%= base_params_sig -%>, int bufferPosition) { + Nodes.DefNode node; // This method mutates the buffer position and may be called from different threads so we must synchronize synchronized (this) { buffer.position(bufferPosition); - return createDefNode(<%= base_params.join(", ") -%>); + node = createDefNode(<%= base_params.join(", ") -%>); } + + MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source); + node.accept(visitor); + + return node; } <%- array_types.uniq.each do |type| -%> From bf8be9bf3a2aea25afb3bdda5b845a461f37d4e1 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 16 Mar 2026 16:06:39 -0700 Subject: [PATCH 116/289] Use explicit npm dist-tag to allow publishing older versions When publishing a backport release (e.g. 1.8.1) after a newer version (e.g. 1.9.0) already exists on npm, `npm publish` fails because it tries to move the `latest` tag to a lower version. Fix this by comparing the package version against the current `latest` on npm and using a `stable-X.Y` dist-tag for older releases. --- .github/workflows/publish-npm.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index e14746a155..5a27aecd4c 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -42,5 +42,17 @@ jobs: - name: Update npm run: npm install -g npm@latest - - run: npm publish + - name: Determine npm tag + id: npm-tag + run: | + PACKAGE_VERSION=$(node -p "require('./javascript/package.json').version") + LATEST_VERSION=$(npm view @ruby/prism version 2>/dev/null || echo "0.0.0") + if npx semver "$PACKAGE_VERSION" -r ">$LATEST_VERSION"; then + echo "tag=latest" >> "$GITHUB_OUTPUT" + else + MINOR=$(echo "$PACKAGE_VERSION" | cut -d. -f1,2) + echo "tag=stable-$MINOR" >> "$GITHUB_OUTPUT" + fi + + - run: npm publish --tag ${{ steps.npm-tag.outputs.tag }} working-directory: javascript From dadeb7e67953a356ffcad5e487aba3779908fb7a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 7 Mar 2026 11:51:57 -0500 Subject: [PATCH 117/289] Use an arena for parser metadata --- include/prism/parser.h | 3 + include/prism/util/pm_char.h | 2 +- include/prism/util/pm_line_offset_list.h | 23 ++--- src/prism.c | 105 ++++++++--------------- src/util/pm_char.c | 4 +- src/util/pm_line_offset_list.c | 42 +++------ src/util/pm_strpbrk.c | 4 +- templates/include/prism/diagnostic.h.erb | 23 ++--- templates/src/diagnostic.c.erb | 45 ++-------- 9 files changed, 77 insertions(+), 174 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index d8e7a550e7..caa08538c6 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -639,6 +639,9 @@ struct pm_parser { /** The arena used for all AST-lifetime allocations. Caller-owned. */ pm_arena_t *arena; + /** The arena used for parser metadata (comments, diagnostics, etc.). */ + pm_arena_t metadata_arena; + /** * The next node identifier that will be assigned. This is a unique * identifier used to track nodes such that the syntax tree can be dropped diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index ab1f513a66..f9a556cabe 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -36,7 +36,7 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); * @return The number of characters at the start of the string that are * whitespace. */ -size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset); +size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_arena_t *arena, pm_line_offset_list_t *line_offsets, uint32_t start_offset); /** * Returns the number of characters at the start of the string that are inline diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index 968eeae52d..2b14b060a1 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -15,6 +15,7 @@ #define PRISM_LINE_OFFSET_LIST_H #include "prism/defines.h" +#include "prism/util/pm_arena.h" #include #include @@ -48,14 +49,13 @@ typedef struct { } pm_line_column_t; /** - * Initialize a new line offset list with the given capacity. Returns true if - * the allocation of the offsets succeeds, otherwise returns false. + * Initialize a new line offset list with the given capacity. * + * @param arena The arena to allocate from. * @param list The list to initialize. * @param capacity The initial capacity of the list. - * @return True if the allocation of the offsets succeeds, otherwise false. */ -bool pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity); +void pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity); /** * Clear out the offsets that have been appended to the list. @@ -65,15 +65,13 @@ bool pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity); void pm_line_offset_list_clear(pm_line_offset_list_t *list); /** - * Append a new offset to the list. Returns true if the reallocation of the - * offsets succeeds (if one was necessary), otherwise returns false. + * Append a new offset to the list. * + * @param arena The arena to allocate from. * @param list The list to append to. * @param cursor The offset to append. - * @return True if the reallocation of the offsets succeeds (if one was - * necessary), otherwise false. */ -bool pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor); +void pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor); /** * Returns the line of the given offset. If the offset is not in the list, the @@ -98,11 +96,4 @@ int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cur */ PRISM_EXPORTED_FUNCTION pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); -/** - * Free the internal memory allocated for the list. - * - * @param list The list to free. - */ -void pm_line_offset_list_free(pm_line_offset_list_t *list); - #endif diff --git a/src/prism.c b/src/prism.c index 9d58bdb43d..f5902b6f98 100644 --- a/src/prism.c +++ b/src/prism.c @@ -451,7 +451,7 @@ debug_lex_state_set(pm_parser_t *parser, pm_lex_state_t state, char const * call */ static inline void pm_parser_err(pm_parser_t *parser, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) { - pm_diagnostic_list_append(&parser->error_list, start, length, diag_id); + pm_diagnostic_list_append(&parser->metadata_arena, &parser->error_list, start, length, diag_id); } /** @@ -494,7 +494,7 @@ pm_parser_err_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_ * Append an error to the list of errors on the parser using a format string. */ #define PM_PARSER_ERR_FORMAT(parser_, start_, length_, diag_id_, ...) \ - pm_diagnostic_list_append_format(&(parser_)->error_list, start_, length_, diag_id_, __VA_ARGS__) + pm_diagnostic_list_append_format(&(parser_)->metadata_arena, &(parser_)->error_list, start_, length_, diag_id_, __VA_ARGS__) /** * Append an error to the list of errors on the parser using the location of the @@ -529,7 +529,7 @@ pm_parser_err_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_ */ static inline void pm_parser_warn(pm_parser_t *parser, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) { - pm_diagnostic_list_append(&parser->warning_list, start, length, diag_id); + pm_diagnostic_list_append(&parser->metadata_arena, &parser->warning_list, start, length, diag_id); } /** @@ -555,7 +555,7 @@ pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id * and the given location. */ #define PM_PARSER_WARN_FORMAT(parser_, start_, length_, diag_id_, ...) \ - pm_diagnostic_list_append_format(&(parser_)->warning_list, start_, length_, diag_id_, __VA_ARGS__) + pm_diagnostic_list_append_format(&(parser_)->metadata_arena, &(parser_)->warning_list, start_, length_, diag_id_, __VA_ARGS__) /** * Append a warning to the list of warnings on the parser using the location of @@ -3897,7 +3897,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { ellipsis = ""; } - pm_diagnostic_list_append_format(&parser->warning_list, PM_TOKEN_START(parser, token), PM_TOKEN_LENGTH(token), PM_WARN_FLOAT_OUT_OF_RANGE, warn_width, (const char *) token->start, ellipsis); + pm_diagnostic_list_append_format(&parser->metadata_arena, &parser->warning_list, PM_TOKEN_START(parser, token), PM_TOKEN_LENGTH(token), PM_WARN_FLOAT_OUT_OF_RANGE, warn_width, (const char *) token->start, ellipsis); value = (value < 0.0) ? -HUGE_VAL : HUGE_VAL; } @@ -7525,12 +7525,10 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { pm_string_free(&key); // Allocate a new magic comment node to append to the parser's list. - pm_magic_comment_t *magic_comment; - if ((magic_comment = (pm_magic_comment_t *) xcalloc(1, sizeof(pm_magic_comment_t))) != NULL) { - magic_comment->key = (pm_location_t) { .start = U32(key_start - parser->start), .length = U32(key_length) }; - magic_comment->value = (pm_location_t) { .start = U32(value_start - parser->start), .length = value_length }; - pm_list_append(&parser->magic_comment_list, (pm_list_node_t *) magic_comment); - } + pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) pm_arena_zalloc(&parser->metadata_arena, sizeof(pm_magic_comment_t), PRISM_ALIGNOF(pm_magic_comment_t)); + magic_comment->key = (pm_location_t) { .start = U32(key_start - parser->start), .length = U32(key_length) }; + magic_comment->value = (pm_location_t) { .start = U32(value_start - parser->start), .length = value_length }; + pm_list_append(&parser->magic_comment_list, (pm_list_node_t *) magic_comment); } return result; @@ -9189,8 +9187,7 @@ parser_lex_callback(pm_parser_t *parser) { */ static inline pm_comment_t * parser_comment(pm_parser_t *parser, pm_comment_type_t type) { - pm_comment_t *comment = (pm_comment_t *) xcalloc(1, sizeof(pm_comment_t)); - if (comment == NULL) return NULL; + pm_comment_t *comment = (pm_comment_t *) pm_arena_zalloc(&parser->metadata_arena, sizeof(pm_comment_t), PRISM_ALIGNOF(pm_comment_t)); *comment = (pm_comment_t) { .type = type, @@ -9213,7 +9210,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9223,7 +9220,6 @@ lex_embdoc(pm_parser_t *parser) { // Now, create a comment that is going to be attached to the parser. const uint8_t *comment_start = parser->current.start; pm_comment_t *comment = parser_comment(parser, PM_COMMENT_EMBDOC); - if (comment == NULL) return PM_TOKEN_EOF; // Now, loop until we find the end of the embedded documentation or the end // of the file. @@ -9247,7 +9243,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9267,7 +9263,7 @@ lex_embdoc(pm_parser_t *parser) { if (newline == NULL) { parser->current.end = parser->end; } else { - pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(newline - parser->start + 1)); parser->current.end = newline + 1; } @@ -9577,7 +9573,7 @@ pm_lex_percent_delimiter(pm_parser_t *parser) { parser_flush_heredoc_end(parser); } else { // Otherwise, we'll add the newline to the list of newlines. - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + U32(eol_length)); } uint8_t delimiter = *parser->current.end; @@ -9681,7 +9677,7 @@ parser_lex(pm_parser_t *parser) { parser->heredoc_end = NULL; } else { parser->current.end += eol_length + 1; - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); space_seen = true; } } else if (pm_char_is_inline_whitespace(*parser->current.end)) { @@ -9783,7 +9779,7 @@ parser_lex(pm_parser_t *parser) { } if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } @@ -10309,7 +10305,7 @@ parser_lex(pm_parser_t *parser) { } else { // Otherwise, we want to indicate that the body of the // heredoc starts on the character after the next newline. - pm_line_offset_list_append(&parser->line_offsets, U32(body_start - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(body_start - parser->start + 1)); body_start++; } @@ -10950,7 +10946,7 @@ parser_lex(pm_parser_t *parser) { // correct column information for it. const uint8_t *cursor = parser->current.end; while ((cursor = next_newline(cursor, parser->end - cursor)) != NULL) { - pm_line_offset_list_append(&parser->line_offsets, U32(++cursor - parser->start)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(++cursor - parser->start)); } parser->current.end = parser->end; @@ -11011,7 +11007,7 @@ parser_lex(pm_parser_t *parser) { whitespace += 1; } } else { - whitespace = pm_strspn_whitespace_newlines(parser->current.end, parser->end - parser->current.end, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); + whitespace = pm_strspn_whitespace_newlines(parser->current.end, parser->end - parser->current.end, &parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } if (whitespace > 0) { @@ -11126,7 +11122,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11264,7 +11260,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11311,7 +11307,7 @@ parser_lex(pm_parser_t *parser) { // If we've hit a newline, then we need to track that in // the list of newlines. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false); break; @@ -11359,7 +11355,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11524,7 +11520,7 @@ parser_lex(pm_parser_t *parser) { // would have already have added the newline to the // list. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current)); } } else { parser->current.end = breakpoint + 1; @@ -11576,7 +11572,7 @@ parser_lex(pm_parser_t *parser) { // for the terminator in case the terminator is a // newline character. if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(breakpoint - parser->start + 1)); parser->current.end = breakpoint + 1; breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, true); break; @@ -11630,7 +11626,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } else { // ... else track the newline. - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); } parser->current.end++; @@ -11759,7 +11755,7 @@ parser_lex(pm_parser_t *parser) { (memcmp(terminator_start, ident_start, ident_length) == 0) ) { if (newline != NULL) { - pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(newline - parser->start + 1)); } parser->current.end = terminator_end; @@ -11831,7 +11827,7 @@ parser_lex(pm_parser_t *parser) { LEX(PM_TOKEN_STRING_CONTENT); } - pm_line_offset_list_append(&parser->line_offsets, U32(breakpoint - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(breakpoint - parser->start + 1)); // If we have a - or ~ heredoc, then we can match after // some leading whitespace. @@ -11951,7 +11947,7 @@ parser_lex(pm_parser_t *parser) { const uint8_t *end = parser->current.end; if (parser->heredoc_end == NULL) { - pm_line_offset_list_append(&parser->line_offsets, U32(end - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(end - parser->start + 1)); } // Here we want the buffer to only @@ -13177,6 +13173,7 @@ pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *liter pm_static_literal_inspect(&buffer, &parser->line_offsets, parser->start, parser->start_line, parser->encoding->name, duplicated); pm_diagnostic_list_append_format( + &parser->metadata_arena, &parser->warning_list, duplicated->location.start, duplicated->location.length, @@ -13200,6 +13197,7 @@ pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *li if ((previous = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, literals, node, false)) != NULL) { pm_diagnostic_list_append_format( + &parser->metadata_arena, &parser->warning_list, PM_NODE_START(node), PM_NODE_LENGTH(node), @@ -21884,6 +21882,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si *parser = (pm_parser_t) { .arena = arena, + .metadata_arena = { 0 }, .node_id = 0, .lex_state = PM_LEX_STATE_BEG, .enclosure_nesting = 0, @@ -21957,7 +21956,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si // guess at the number of newlines that we'll need based on the size of the // input. size_t newline_size = size / 22; - pm_line_offset_list_init(&parser->line_offsets, newline_size < 4 ? 4 : newline_size); + pm_line_offset_list_init(&parser->metadata_arena, &parser->line_offsets, newline_size < 4 ? 4 : newline_size); // If options were provided to this parse, establish them here. if (options != NULL) { @@ -22096,7 +22095,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si const uint8_t *newline = next_newline(cursor, parser->end - cursor); while (newline != NULL) { - pm_line_offset_list_append(&parser->line_offsets, U32(newline - parser->start + 1)); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, U32(newline - parser->start + 1)); cursor = newline + 1; newline = next_newline(cursor, parser->end - cursor); @@ -22145,48 +22144,14 @@ pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_ch parser->encoding_changed_callback = callback; } -/** - * Free all of the memory associated with the comment list. - */ -static inline void -pm_comment_list_free(pm_list_t *list) { - pm_list_node_t *node, *next; - - for (node = list->head; node != NULL; node = next) { - next = node->next; - - pm_comment_t *comment = (pm_comment_t *) node; - xfree_sized(comment, sizeof(pm_comment_t)); - } -} - -/** - * Free all of the memory associated with the magic comment list. - */ -static inline void -pm_magic_comment_list_free(pm_list_t *list) { - pm_list_node_t *node, *next; - - for (node = list->head; node != NULL; node = next) { - next = node->next; - - pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) node; - xfree_sized(magic_comment, sizeof(pm_magic_comment_t)); - } -} - /** * Free any memory associated with the given parser. */ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser) { pm_string_free(&parser->filepath); - pm_diagnostic_list_free(&parser->error_list); - pm_diagnostic_list_free(&parser->warning_list); - pm_comment_list_free(&parser->comment_list); - pm_magic_comment_list_free(&parser->magic_comment_list); pm_constant_pool_free(&parser->constant_pool); - pm_line_offset_list_free(&parser->line_offsets); + pm_arena_free(&parser->metadata_arena); while (parser->current_scope != NULL) { // Normally, popping the scope doesn't free the locals since it is diff --git a/src/util/pm_char.c b/src/util/pm_char.c index f0baf47784..ff8a88a687 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -83,7 +83,7 @@ pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length) { * searching past the given maximum number of characters. */ size_t -pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_offset_list_t *line_offsets, uint32_t start_offset) { +pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_arena_t *arena, pm_line_offset_list_t *line_offsets, uint32_t start_offset) { if (length <= 0) return 0; uint32_t size = 0; @@ -91,7 +91,7 @@ pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_line_o while (size < maximum && (pm_byte_table[string[size]] & PRISM_CHAR_BIT_WHITESPACE)) { if (string[size] == '\n') { - pm_line_offset_list_append(line_offsets, start_offset + size + 1); + pm_line_offset_list_append(arena, line_offsets, start_offset + size + 1); } size++; diff --git a/src/util/pm_line_offset_list.c b/src/util/pm_line_offset_list.c index d55b2f6874..c0b41df406 100644 --- a/src/util/pm_line_offset_list.c +++ b/src/util/pm_line_offset_list.c @@ -1,20 +1,16 @@ #include "prism/util/pm_line_offset_list.h" /** - * Initialize a new newline list with the given capacity. Returns true if the - * allocation of the offsets succeeds, otherwise returns false. + * Initialize a new line offset list with the given capacity. */ -bool -pm_line_offset_list_init(pm_line_offset_list_t *list, size_t capacity) { - list->offsets = (uint32_t *) xcalloc(capacity, sizeof(uint32_t)); - if (list->offsets == NULL) return false; +void +pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity) { + list->offsets = (uint32_t *) pm_arena_zalloc(arena, capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t)); // This is 1 instead of 0 because we want to include the first line of the - // file as having offset 0, which is set because of calloc. + // file as having offset 0, which is set because of the zero-initialization. list->size = 1; list->capacity = capacity; - - return true; } /** @@ -26,26 +22,22 @@ pm_line_offset_list_clear(pm_line_offset_list_t *list) { } /** - * Append a new offset to the newline list. Returns true if the reallocation of - * the offsets succeeds (if one was necessary), otherwise returns false. + * Append a new offset to the newline list. */ -bool -pm_line_offset_list_append(pm_line_offset_list_t *list, uint32_t cursor) { +void +pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) { if (list->size == list->capacity) { - uint32_t *original_offsets = list->offsets; + size_t new_capacity = (list->capacity * 3) / 2; + uint32_t *new_offsets = (uint32_t *) pm_arena_alloc(arena, new_capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t)); - list->capacity = (list->capacity * 3) / 2; - list->offsets = (uint32_t *) xcalloc(list->capacity, sizeof(uint32_t)); - if (list->offsets == NULL) return false; + memcpy(new_offsets, list->offsets, list->size * sizeof(uint32_t)); - memcpy(list->offsets, original_offsets, list->size * sizeof(uint32_t)); - xfree_sized(original_offsets, list->size * sizeof(uint32_t)); + list->offsets = new_offsets; + list->capacity = new_capacity; } assert(list->size == 0 || cursor > list->offsets[list->size - 1]); list->offsets[list->size++] = cursor; - - return true; } /** @@ -103,11 +95,3 @@ pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t curs .column = cursor - list->offsets[left - 1] }); } - -/** - * Free the internal memory allocated for the newline list. - */ -void -pm_line_offset_list_free(pm_line_offset_list_t *list) { - xfree_sized(list->offsets, list->capacity * sizeof(uint32_t)); -} diff --git a/src/util/pm_strpbrk.c b/src/util/pm_strpbrk.c index 60c67b2983..ddd6ef0ead 100644 --- a/src/util/pm_strpbrk.c +++ b/src/util/pm_strpbrk.c @@ -5,7 +5,7 @@ */ static inline void pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, uint32_t start, uint32_t length) { - pm_diagnostic_list_append_format(&parser->error_list, start, length, PM_ERR_INVALID_MULTIBYTE_CHARACTER, parser->start[start]); + pm_diagnostic_list_append_format(&parser->metadata_arena, &parser->error_list, start, length, PM_ERR_INVALID_MULTIBYTE_CHARACTER, parser->start[start]); } /** @@ -19,7 +19,7 @@ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, uint32_t start, uint32_t l } else if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { // Not okay, we already found a Unicode escape sequence and this // conflicts. - pm_diagnostic_list_append_format(&parser->error_list, start, length, PM_ERR_MIXED_ENCODING, parser->encoding->name); + pm_diagnostic_list_append_format(&parser->metadata_arena, &parser->error_list, start, length, PM_ERR_MIXED_ENCODING, parser->encoding->name); } else { // Should not be anything else. assert(false && "unreachable"); diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb index c1864e6021..935fb663ea 100644 --- a/templates/include/prism/diagnostic.h.erb +++ b/templates/include/prism/diagnostic.h.erb @@ -8,6 +8,7 @@ #include "prism/ast.h" #include "prism/defines.h" +#include "prism/util/pm_arena.h" #include "prism/util/pm_list.h" #include @@ -48,13 +49,6 @@ typedef struct { /** The message associated with the diagnostic. */ const char *message; - /** - * Whether or not the memory related to the message of this diagnostic is - * owned by this diagnostic. If it is, it needs to be freed when the - * diagnostic is freed. - */ - bool owned; - /** * The level of the diagnostic, see `pm_error_level_t` and * `pm_warning_level_t` for possible values. @@ -99,32 +93,25 @@ const char * pm_diagnostic_id_human(pm_diagnostic_id_t diag_id); * Append a diagnostic to the given list of diagnostics that is using shared * memory for its message. * + * @param arena The arena to allocate from. * @param list The list to append to. * @param start The source offset of the start of the diagnostic. * @param length The length of the diagnostic. * @param diag_id The diagnostic ID. - * @return Whether the diagnostic was successfully appended. */ -bool pm_diagnostic_list_append(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id); +void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id); /** * Append a diagnostic to the given list of diagnostics that is using a format * string for its message. * + * @param arena The arena to allocate from. * @param list The list to append to. * @param start The source offset of the start of the diagnostic. * @param length The length of the diagnostic. * @param diag_id The diagnostic ID. * @param ... The arguments to the format string for the message. - * @return Whether the diagnostic was successfully appended. - */ -bool pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); - -/** - * Deallocate the internal state of the given diagnostic list. - * - * @param list The list to deallocate. */ -void pm_diagnostic_list_free(pm_list_t *list); +void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); #endif diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 8fa47590c0..b02714637d 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -1,4 +1,5 @@ #include "prism/diagnostic.h" +#include "prism/util/pm_arena.h" #define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %> @@ -451,29 +452,26 @@ pm_diagnostic_level(pm_diagnostic_id_t diag_id) { /** * Append an error to the given list of diagnostic. */ -bool -pm_diagnostic_list_append(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) { - pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) xcalloc(1, sizeof(pm_diagnostic_t)); - if (diagnostic == NULL) return false; +void +pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) { + pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) pm_arena_zalloc(arena, sizeof(pm_diagnostic_t), PRISM_ALIGNOF(pm_diagnostic_t)); *diagnostic = (pm_diagnostic_t) { .location = { .start = start, .length = length }, .diag_id = diag_id, .message = pm_diagnostic_message(diag_id), - .owned = false, .level = pm_diagnostic_level(diag_id) }; pm_list_append(list, (pm_list_node_t *) diagnostic); - return true; } /** * Append a diagnostic to the given list of diagnostics that is using a format * string for its message. */ -bool -pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...) { +void +pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...) { va_list arguments; va_start(arguments, diag_id); @@ -482,20 +480,13 @@ pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t lengt va_end(arguments); if (result < 0) { - return false; + return; } - pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) xcalloc(1, sizeof(pm_diagnostic_t)); - if (diagnostic == NULL) { - return false; - } + pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) pm_arena_zalloc(arena, sizeof(pm_diagnostic_t), PRISM_ALIGNOF(pm_diagnostic_t)); size_t message_length = (size_t) (result + 1); - char *message = (char *) xmalloc(message_length); - if (message == NULL) { - xfree_sized(diagnostic, sizeof(pm_diagnostic_t)); - return false; - } + char *message = (char *) pm_arena_alloc(arena, message_length, 1); va_start(arguments, diag_id); vsnprintf(message, message_length, format, arguments); @@ -505,27 +496,9 @@ pm_diagnostic_list_append_format(pm_list_t *list, uint32_t start, uint32_t lengt .location = { .start = start, .length = length }, .diag_id = diag_id, .message = message, - .owned = true, .level = pm_diagnostic_level(diag_id) }; pm_list_append(list, (pm_list_node_t *) diagnostic); - return true; } -/** - * Deallocate the internal state of the given diagnostic list. - */ -void -pm_diagnostic_list_free(pm_list_t *list) { - pm_diagnostic_t *node = (pm_diagnostic_t *) list->head; - - while (node != NULL) { - pm_diagnostic_t *next = (pm_diagnostic_t *) node->node.next; - - if (node->owned) xfree((void *) node->message); - xfree_sized(node, sizeof(pm_diagnostic_t)); - - node = next; - } -} From 390bdaa1f16582a9a7daddbf7add09ce82106981 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 7 Mar 2026 12:09:39 -0500 Subject: [PATCH 118/289] Use the parser arena for the constant pool --- include/prism/util/pm_constant_pool.h | 15 ++--- src/prism.c | 21 +++---- src/util/pm_constant_pool.c | 81 +++++++-------------------- 3 files changed, 31 insertions(+), 86 deletions(-) diff --git a/include/prism/util/pm_constant_pool.h b/include/prism/util/pm_constant_pool.h index 1d4922a661..285a636a3a 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/util/pm_constant_pool.h @@ -146,7 +146,7 @@ typedef struct { * @param capacity The initial capacity of the pool. * @return Whether the initialization succeeded. */ -bool pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity); +void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity); /** * Return a pointer to the constant indicated by the given constant id. @@ -177,7 +177,7 @@ pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uin * @param length The length of the constant. * @return The id of the constant. */ -pm_constant_id_t pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, size_t length); +pm_constant_id_t pm_constant_pool_insert_shared(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); /** * Insert a constant into a constant pool from memory that is now owned by the @@ -189,7 +189,7 @@ pm_constant_id_t pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const * @param length The length of the constant. * @return The id of the constant. */ -pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, uint8_t *start, size_t length); +pm_constant_id_t pm_constant_pool_insert_owned(pm_arena_t *arena, pm_constant_pool_t *pool, uint8_t *start, size_t length); /** * Insert a constant into a constant pool from memory that is constant. Returns @@ -200,13 +200,6 @@ pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, uint8_t * @param length The length of the constant. * @return The id of the constant. */ -pm_constant_id_t pm_constant_pool_insert_constant(pm_constant_pool_t *pool, const uint8_t *start, size_t length); - -/** - * Free the memory associated with a constant pool. - * - * @param pool The pool to free. - */ -void pm_constant_pool_free(pm_constant_pool_t *pool); +pm_constant_id_t pm_constant_pool_insert_constant(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); #endif diff --git a/src/prism.c b/src/prism.c index f5902b6f98..602e3bfb99 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1028,7 +1028,7 @@ pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, */ static inline pm_constant_id_t pm_parser_constant_id_raw(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { - return pm_constant_pool_insert_shared(&parser->constant_pool, start, (size_t) (end - start)); + return pm_constant_pool_insert_shared(&parser->metadata_arena, &parser->constant_pool, start, (size_t) (end - start)); } /** @@ -1036,7 +1036,7 @@ pm_parser_constant_id_raw(pm_parser_t *parser, const uint8_t *start, const uint8 */ static inline pm_constant_id_t pm_parser_constant_id_owned(pm_parser_t *parser, uint8_t *start, size_t length) { - return pm_constant_pool_insert_owned(&parser->constant_pool, start, length); + return pm_constant_pool_insert_owned(&parser->metadata_arena, &parser->constant_pool, start, length); } /** @@ -1044,7 +1044,7 @@ pm_parser_constant_id_owned(pm_parser_t *parser, uint8_t *start, size_t length) */ static inline pm_constant_id_t pm_parser_constant_id_constant(pm_parser_t *parser, const char *start, size_t length) { - return pm_constant_pool_insert_constant(&parser->constant_pool, (const uint8_t *) start, length); + return pm_constant_pool_insert_constant(&parser->metadata_arena, &parser->constant_pool, (const uint8_t *) start, length); } /** @@ -2908,10 +2908,10 @@ pm_call_write_read_name_init(pm_parser_t *parser, pm_constant_id_t *read_name, p if (write_constant->length > 0) { size_t length = write_constant->length - 1; - void *memory = xmalloc(length); + uint8_t *memory = (uint8_t *) pm_arena_alloc(parser->arena, length, 1); memcpy(memory, write_constant->start, length); - *read_name = pm_constant_pool_insert_owned(&parser->constant_pool, (uint8_t *) memory, length); + *read_name = pm_constant_pool_insert_owned(&parser->metadata_arena, &parser->constant_pool, memory, length); } else { // We can get here if the message was missing because of a syntax error. *read_name = pm_parser_constant_id_constant(parser, "", 0); @@ -12543,16 +12543,12 @@ parse_write_name(pm_parser_t *parser, pm_constant_id_t *name_field) { // append an =. pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, *name_field); size_t length = constant->length; - uint8_t *name = xcalloc(length + 1, sizeof(uint8_t)); - if (name == NULL) return; + uint8_t *name = (uint8_t *) pm_arena_alloc(parser->arena, length + 1, 1); memcpy(name, constant->start, length); name[length] = '='; - // Now switch the name to the new string. - // This silences clang analyzer warning about leak of memory pointed by `name`. - // NOLINTNEXTLINE(clang-analyzer-*) - *name_field = pm_constant_pool_insert_owned(&parser->constant_pool, name, length + 1); + *name_field = pm_constant_pool_insert_owned(&parser->metadata_arena, &parser->constant_pool, name, length + 1); } /** @@ -21950,7 +21946,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si // This ratio will need to change if we add more constants to the constant // pool for another node type. uint32_t constant_size = ((uint32_t) size) / 95; - pm_constant_pool_init(&parser->constant_pool, constant_size < 4 ? 4 : constant_size); + pm_constant_pool_init(&parser->metadata_arena, &parser->constant_pool, constant_size < 4 ? 4 : constant_size); // Initialize the newline list. Similar to the constant pool, we're going to // guess at the number of newlines that we'll need based on the size of the @@ -22150,7 +22146,6 @@ pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_ch PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser) { pm_string_free(&parser->filepath); - pm_constant_pool_free(&parser->constant_pool); pm_arena_free(&parser->metadata_arena); while (parser->current_scope != NULL) { diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index f7173dd062..0c9a7dec9a 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -115,21 +115,15 @@ is_power_of_two(uint32_t size) { /** * Resize a constant pool to a given capacity. */ -static inline bool -pm_constant_pool_resize(pm_constant_pool_t *pool) { +static inline void +pm_constant_pool_resize(pm_arena_t *arena, pm_constant_pool_t *pool) { assert(is_power_of_two(pool->capacity)); uint32_t next_capacity = pool->capacity * 2; - if (next_capacity < pool->capacity) return false; - const uint32_t mask = next_capacity - 1; - const size_t element_size = sizeof(pm_constant_pool_bucket_t) + sizeof(pm_constant_t); - - void *next = xcalloc(next_capacity, element_size); - if (next == NULL) return false; - pm_constant_pool_bucket_t *next_buckets = next; - pm_constant_t *next_constants = (void *)(((char *) next) + next_capacity * sizeof(pm_constant_pool_bucket_t)); + pm_constant_pool_bucket_t *next_buckets = (pm_constant_pool_bucket_t *) pm_arena_zalloc(arena, next_capacity * sizeof(pm_constant_pool_bucket_t), PRISM_ALIGNOF(pm_constant_pool_bucket_t)); + pm_constant_t *next_constants = (pm_constant_t *) pm_arena_alloc(arena, next_capacity * sizeof(pm_constant_t), PRISM_ALIGNOF(pm_constant_t)); // For each bucket in the current constant pool, find the index in the // next constant pool, and insert it. @@ -157,33 +151,22 @@ pm_constant_pool_resize(pm_constant_pool_t *pool) { // The constants are stable with respect to hash table resizes. memcpy(next_constants, pool->constants, pool->size * sizeof(pm_constant_t)); - // pool->constants and pool->buckets are allocated out of the same chunk - // of memory, with the buckets coming first. - xfree_sized(pool->buckets, pool->capacity * element_size); pool->constants = next_constants; pool->buckets = next_buckets; pool->capacity = next_capacity; - return true; } /** * Initialize a new constant pool with a given capacity. */ -bool -pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity) { - const uint32_t maximum = (~((uint32_t) 0)); - if (capacity >= ((maximum / 2) + 1)) return false; - +void +pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity) { capacity = next_power_of_two(capacity); - const size_t element_size = sizeof(pm_constant_pool_bucket_t) + sizeof(pm_constant_t); - void *memory = xcalloc(capacity, element_size); - if (memory == NULL) return false; - pool->buckets = memory; - pool->constants = (void *)(((char *)memory) + capacity * sizeof(pm_constant_pool_bucket_t)); + pool->buckets = (pm_constant_pool_bucket_t *) pm_arena_zalloc(arena, capacity * sizeof(pm_constant_pool_bucket_t), PRISM_ALIGNOF(pm_constant_pool_bucket_t)); + pool->constants = (pm_constant_t *) pm_arena_alloc(arena, capacity * sizeof(pm_constant_t), PRISM_ALIGNOF(pm_constant_t)); pool->size = 0; pool->capacity = capacity; - return true; } /** @@ -224,9 +207,9 @@ pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size * Insert a constant into a constant pool and return its index in the pool. */ static inline pm_constant_id_t -pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t length, pm_constant_pool_bucket_type_t type) { +pm_constant_pool_insert(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length, pm_constant_pool_bucket_type_t type) { if (pool->size >= (pool->capacity / 4 * 3)) { - if (!pm_constant_pool_resize(pool)) return PM_CONSTANT_ID_UNSET; + pm_constant_pool_resize(arena, pool); } assert(is_power_of_two(pool->capacity)); @@ -246,17 +229,10 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l // Since we have found a match, we need to check if this is // attempting to insert a shared or an owned constant. We want to // prefer shared constants since they don't require allocations. - if (type == PM_CONSTANT_POOL_BUCKET_OWNED) { - // If we're attempting to insert an owned constant and we have - // an existing constant, then either way we don't want the given - // memory. Either it's duplicated with the existing constant or - // it's not necessary because we have a shared version. - xfree_sized((void *) start, length); - } else if (bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { + if (type != PM_CONSTANT_POOL_BUCKET_OWNED && bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { // If we're attempting to insert a shared constant and the - // existing constant is owned, then we can free the owned - // constant and replace it with the shared constant. - xfree_sized((void *) constant->start, constant->length); + // existing constant is owned, then we can replace it with the + // shared constant to prefer non-owned references. constant->start = start; bucket->type = (unsigned int) (type & 0x3); } @@ -291,8 +267,8 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l * PM_CONSTANT_ID_UNSET if any potential calls to resize fail. */ pm_constant_id_t -pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { - return pm_constant_pool_insert(pool, start, length, PM_CONSTANT_POOL_BUCKET_DEFAULT); +pm_constant_pool_insert_shared(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length) { + return pm_constant_pool_insert(arena, pool, start, length, PM_CONSTANT_POOL_BUCKET_DEFAULT); } /** @@ -301,8 +277,8 @@ pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, s * potential calls to resize fail. */ pm_constant_id_t -pm_constant_pool_insert_owned(pm_constant_pool_t *pool, uint8_t *start, size_t length) { - return pm_constant_pool_insert(pool, start, length, PM_CONSTANT_POOL_BUCKET_OWNED); +pm_constant_pool_insert_owned(pm_arena_t *arena, pm_constant_pool_t *pool, uint8_t *start, size_t length) { + return pm_constant_pool_insert(arena, pool, start, length, PM_CONSTANT_POOL_BUCKET_OWNED); } /** @@ -311,26 +287,7 @@ pm_constant_pool_insert_owned(pm_constant_pool_t *pool, uint8_t *start, size_t l * resize fail. */ pm_constant_id_t -pm_constant_pool_insert_constant(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { - return pm_constant_pool_insert(pool, start, length, PM_CONSTANT_POOL_BUCKET_CONSTANT); +pm_constant_pool_insert_constant(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length) { + return pm_constant_pool_insert(arena, pool, start, length, PM_CONSTANT_POOL_BUCKET_CONSTANT); } -/** - * Free the memory associated with a constant pool. - */ -void -pm_constant_pool_free(pm_constant_pool_t *pool) { - // For each constant in the current constant pool, free the contents if the - // contents are owned. - for (uint32_t index = 0; index < pool->capacity; index++) { - pm_constant_pool_bucket_t *bucket = &pool->buckets[index]; - - // If an id is set on this constant, then we know we have content here. - if (bucket->id != PM_CONSTANT_ID_UNSET && bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { - pm_constant_t *constant = &pool->constants[bucket->id - 1]; - xfree_sized((void *) constant->start, constant->length); - } - } - - xfree_sized(pool->buckets, pool->capacity * (sizeof(pm_constant_pool_bucket_t) + sizeof(pm_constant_t))); -} From 1dd985306f806dc9c275474b01f8c6f4b72a25ef Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 8 Mar 2026 14:26:57 -0400 Subject: [PATCH 119/289] Speed up the constant hash function --- src/util/pm_constant_pool.c | 50 +++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index 0c9a7dec9a..c8c27a9618 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -70,19 +70,55 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) { } /** - * A relatively simple hash function (djb2) that is used to hash strings. We are - * optimizing here for simplicity and speed. + * A multiply-xorshift hash that processes input a word at a time. This is + * significantly faster than the byte-at-a-time djb2 hash for the short strings + * typical in Ruby source (~15 bytes average). Each word is mixed into the hash + * by XOR followed by multiplication by a large odd constant, which spreads + * entropy across all bits. A final xorshift fold produces the 32-bit result. */ static inline uint32_t pm_constant_pool_hash(const uint8_t *start, size_t length) { - // This is a prime number used as the initial value for the hash function. - uint32_t value = 5381; + // This constant is borrowed from wyhash. It is a 64-bit odd integer with + // roughly equal 0/1 bits, chosen for good avalanche behavior when used in + // multiply-xorshift sequences. + static const uint64_t secret = 0x517cc1b727220a95ULL; + uint64_t hash = (uint64_t) length; + + const uint8_t *ptr = start; + size_t remaining = length; + + while (remaining >= 8) { + uint64_t word; + memcpy(&word, ptr, 8); + hash ^= word; + hash *= secret; + ptr += 8; + remaining -= 8; + } + + if (remaining >= 4) { + uint32_t word; + memcpy(&word, ptr, 4); + hash ^= (uint64_t) word; + hash *= secret; + ptr += 4; + remaining -= 4; + } + + if (remaining >= 2) { + hash ^= (uint64_t) ptr[0] | ((uint64_t) ptr[1] << 8); + hash *= secret; + ptr += 2; + remaining -= 2; + } - for (size_t index = 0; index < length; index++) { - value = ((value << 5) + value) + start[index]; + if (remaining >= 1) { + hash ^= (uint64_t) ptr[0]; + hash *= secret; } - return value; + hash ^= hash >> 32; + return (uint32_t) hash; } /** From e0708c495c7d5f37f5ddf7251b05f2bcff1151dc Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 8 Mar 2026 13:53:54 -0400 Subject: [PATCH 120/289] Small optimization for parser_lex_magic_comment --- src/prism.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/prism.c b/src/prism.c index 602e3bfb99..97c969ff90 100644 --- a/src/prism.c +++ b/src/prism.c @@ -7316,11 +7316,13 @@ pm_char_is_magic_comment_key_delimiter(const uint8_t b) { */ static inline const uint8_t * parser_lex_magic_comment_emacs_marker(pm_parser_t *parser, const uint8_t *cursor, const uint8_t *end) { - while ((cursor + 3 <= end) && (cursor = pm_memchr(cursor, '-', (size_t) (end - cursor), parser->encoding_changed, parser->encoding)) != NULL) { - if (cursor + 3 <= end && cursor[1] == '*' && cursor[2] == '-') { - return cursor; + // Scan for '*' as the middle character, since it is rarer than '-' in + // typical comments and avoids repeated memchr calls for '-' that hit + // dashes in words like "foo-bar". + while ((cursor + 3 <= end) && (cursor = pm_memchr(cursor + 1, '*', (size_t) (end - cursor - 1), parser->encoding_changed, parser->encoding)) != NULL) { + if (cursor[-1] == '-' && cursor + 1 < end && cursor[1] == '-') { + return cursor - 1; } - cursor++; } return NULL; } @@ -7357,6 +7359,13 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { // have a magic comment. return false; } + } else { + // Non-emacs magic comments must contain a colon for `key: value`. + // Reject early if there is no colon to avoid scanning the entire + // comment character-by-character. + if (pm_memchr(start, ':', (size_t) (end - start), parser->encoding_changed, parser->encoding) == NULL) { + return false; + } } cursor = start; From c1ad25ebf8b2e5215aaca18d277f459f2df89a90 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 8 Mar 2026 14:58:29 -0400 Subject: [PATCH 121/289] Scan forward through inline whitespace to avoid writing to parser->current.end continuously --- src/prism.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/prism.c b/src/prism.c index 97c969ff90..0f21b950dc 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9658,17 +9658,24 @@ parser_lex(pm_parser_t *parser) { bool space_seen = false; // First, we're going to skip past any whitespace at the front of the next - // token. + // token. Skip runs of inline whitespace in bulk to avoid per-character + // stores back to parser->current.end. bool chomping = true; while (parser->current.end < parser->end && chomping) { - switch (*parser->current.end) { - case ' ': - case '\t': - case '\f': - case '\v': - parser->current.end++; + { + static const uint8_t inline_whitespace[256] = { + [' '] = 1, ['\t'] = 1, ['\f'] = 1, ['\v'] = 1 + }; + const uint8_t *scan = parser->current.end; + while (scan < parser->end && inline_whitespace[*scan]) scan++; + if (scan > parser->current.end) { + parser->current.end = scan; space_seen = true; - break; + continue; + } + } + + switch (*parser->current.end) { case '\r': if (match_eol_offset(parser, 1)) { chomping = false; From fb526a824337f017d22f12689561cdcc4872226d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 8 Mar 2026 16:10:05 -0400 Subject: [PATCH 122/289] Fast-paths for ASCII-only identifiers --- include/prism/defines.h | 31 ++++++ src/prism.c | 225 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+) diff --git a/include/prism/defines.h b/include/prism/defines.h index c48a600b21..6afc239035 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -264,6 +264,37 @@ #define PRISM_UNLIKELY(x) (x) #endif +/** + * Count trailing zero bits in a 64-bit value. Used by SWAR identifier scanning + * to find the first non-matching byte in a word. + * + * Precondition: v must be nonzero. The result is undefined when v == 0 + * (matching the behavior of __builtin_ctzll and _BitScanForward64). + */ +#if defined(__GNUC__) || defined(__clang__) + #define pm_ctzll(v) ((unsigned) __builtin_ctzll(v)) +#elif defined(_MSC_VER) + #include + static inline unsigned pm_ctzll(uint64_t v) { + unsigned long index; + _BitScanForward64(&index, v); + return (unsigned) index; + } +#else + static inline unsigned + pm_ctzll(uint64_t v) { + unsigned c = 0; + v &= (uint64_t) (-(int64_t) v); + if (v & 0x00000000FFFFFFFFULL) c += 0; else c += 32; + if (v & 0x0000FFFF0000FFFFULL) c += 0; else c += 16; + if (v & 0x00FF00FF00FF00FFULL) c += 0; else c += 8; + if (v & 0x0F0F0F0F0F0F0F0FULL) c += 0; else c += 4; + if (v & 0x3333333333333333ULL) c += 0; else c += 2; + if (v & 0x5555555555555555ULL) c += 0; else c += 1; + return c; + } +#endif + /** * We use -Wimplicit-fallthrough to guard potentially unintended fall-through between cases of a switch. * Use PRISM_FALLTHROUGH to explicitly annotate cases where the fallthrough is intentional. diff --git a/src/prism.c b/src/prism.c index 0f21b950dc..dace322ee9 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1777,6 +1777,227 @@ char_is_identifier_utf8(const uint8_t *b, ptrdiff_t n) { } } +/** + * Scan forward through ASCII identifier characters (a-z, A-Z, 0-9, _) using + * wide operations. Returns the number of leading ASCII identifier bytes. + * Callers must handle any remaining bytes (short tail or non-ASCII/UTF-8) + * with a byte-at-a-time loop. + * + * Up to four optimized implementations are selected at compile time, with a + * no-op fallback for unsupported platforms: + * 1. NEON — processes 16 bytes per iteration on aarch64. + * 2. SSE2 — processes 16 bytes per iteration on x86-64. + * 3. WASM SIMD — processes 16 bytes per iteration on WebAssembly. + * 4. SWAR — little-endian fallback, processes 8 bytes per iteration. + * 5. No-op — returns 0; the caller's byte-at-a-time loop handles everything. + */ + +#if defined(__aarch64__) && defined(__ARM_NEON) +#include + +static inline size_t +scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { + const uint8_t *cursor = start; + + // Nibble-based lookup tables for classifying [a-zA-Z0-9_]. + // Each high nibble is assigned a unique bit; the low nibble table + // contains the OR of bits for all high nibbles that have an + // identifier character at that low nibble position. A byte is an + // identifier character iff (low_lut[lo] & high_lut[hi]) != 0. + const uint8x16_t low_lut = (uint8x16_t) { + 0x15, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1E, 0x0A, 0x0A, 0x0A, 0x0A, 0x0E + }; + const uint8x16_t high_lut = (uint8x16_t) { + 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + const uint8x16_t mask_0f = vdupq_n_u8(0x0F); + + while (cursor + 16 <= end) { + uint8x16_t v = vld1q_u8(cursor); + + uint8x16_t lo_class = vqtbl1q_u8(low_lut, vandq_u8(v, mask_0f)); + uint8x16_t hi_class = vqtbl1q_u8(high_lut, vshrq_n_u8(v, 4)); + uint8x16_t ident = vandq_u8(lo_class, hi_class); + + // Fast check: if the per-byte minimum is nonzero, every byte matched. + if (vminvq_u8(ident) != 0) { + cursor += 16; + continue; + } + + // Find the first non-identifier byte (zero in ident). + uint8x16_t is_zero = vceqq_u8(ident, vdupq_n_u8(0)); + uint64_t lo = vgetq_lane_u64(vreinterpretq_u64_u8(is_zero), 0); + + if (lo != 0) { + cursor += pm_ctzll(lo) / 8; + } else { + uint64_t hi = vgetq_lane_u64(vreinterpretq_u64_u8(is_zero), 1); + cursor += 8 + pm_ctzll(hi) / 8; + } + + return (size_t) (cursor - start); + } + + return (size_t) (cursor - start); +} + +#elif defined(__x86_64__) && defined(__SSE2__) +#include + +static inline size_t +scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { + const uint8_t *cursor = start; + + while (cursor + 16 <= end) { + __m128i v = _mm_loadu_si128((const __m128i *) cursor); + __m128i zero = _mm_setzero_si128(); + + // Unsigned range check via saturating subtraction: + // byte >= lo ⟺ saturate(lo - byte) == 0 + // byte <= hi ⟺ saturate(byte - hi) == 0 + + // Fold case: OR with 0x20 maps A-Z to a-z. + __m128i lowered = _mm_or_si128(v, _mm_set1_epi8(0x20)); + __m128i letter = _mm_and_si128( + _mm_cmpeq_epi8(_mm_subs_epu8(_mm_set1_epi8(0x61), lowered), zero), + _mm_cmpeq_epi8(_mm_subs_epu8(lowered, _mm_set1_epi8(0x7A)), zero)); + + __m128i digit = _mm_and_si128( + _mm_cmpeq_epi8(_mm_subs_epu8(_mm_set1_epi8(0x30), v), zero), + _mm_cmpeq_epi8(_mm_subs_epu8(v, _mm_set1_epi8(0x39)), zero)); + + __m128i underscore = _mm_cmpeq_epi8(v, _mm_set1_epi8(0x5F)); + + __m128i ident = _mm_or_si128(_mm_or_si128(letter, digit), underscore); + int mask = _mm_movemask_epi8(ident); + + if (mask == 0xFFFF) { + cursor += 16; + continue; + } + + cursor += pm_ctzll((uint64_t) (~mask & 0xFFFF)); + return (size_t) (cursor - start); + } + + return (size_t) (cursor - start); +} + +#elif defined(__wasm_simd128__) +#include + +static inline size_t +scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { + const uint8_t *cursor = start; + + while (cursor + 16 <= end) { + v128_t v = wasm_v128_load(cursor); + + // Range checks via subtract-and-unsigned-compare: (v - lo) < count + // is true iff v is in [lo, lo + count). One subtract + one compare + // per range instead of two comparisons + AND. + + // Fold case: OR with 0x20 maps A-Z to a-z. + v128_t lowered = wasm_v128_or(v, wasm_u8x16_splat(0x20)); + v128_t letter = wasm_u8x16_lt( + wasm_i8x16_sub(lowered, wasm_u8x16_splat(0x61)), + wasm_u8x16_splat(0x1A)); + + v128_t digit = wasm_u8x16_lt( + wasm_i8x16_sub(v, wasm_u8x16_splat(0x30)), + wasm_u8x16_splat(0x0A)); + + v128_t underscore = wasm_i8x16_eq(v, wasm_u8x16_splat(0x5F)); + + v128_t ident = wasm_v128_or(wasm_v128_or(letter, digit), underscore); + + // Fast path: if all 16 bytes are identifier chars, advance. + if (wasm_i8x16_all_true(ident)) { + cursor += 16; + continue; + } + + // Extract bitmask only on the exit path to find the first non-match. + uint32_t mask = wasm_i8x16_bitmask(ident); + cursor += pm_ctzll((uint64_t) (~mask & 0xFFFF)); + return (size_t) (cursor - start); + } + + return (size_t) (cursor - start); +} + +// The SWAR path uses pm_ctzll to find the first non-matching byte within a +// word, which only yields the correct byte index on little-endian targets. +// We gate on a positive little-endian check so that unknown-endianness +// platforms safely fall through to the no-op fallback. +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + +/** + * Portable SWAR fallback — processes 8 bytes per iteration. + * + * The byte-wise range checks avoid cross-byte borrows by pre-setting the high + * bit of each byte before subtraction: (byte | 0x80) - lo has a minimum value + * of 0x80 - 0x7F = 1, so underflow (and thus a borrow into the next byte) is + * impossible. The result has bit 7 set if and only if byte >= lo. The same + * reasoning applies to the upper-bound direction. + */ +static inline size_t +scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { + static const uint64_t ones = 0x0101010101010101ULL; + static const uint64_t highs = 0x8080808080808080ULL; + const uint8_t *cursor = start; + + while (cursor + 8 <= end) { + uint64_t word; + memcpy(&word, cursor, 8); + + // Bail on any non-ASCII byte. + if (word & highs) break; + + uint64_t digit = ((word | highs) - ones * 0x30) & ((ones * 0x39 | highs) - word) & highs; + + // Fold upper- and lowercase together by forcing bit 5 (OR 0x20), + // then check the lowercase range once. A-Z maps to a-z; the + // only non-letter byte that could alias into [0x61,0x7A] is one + // whose original value was in [0x41,0x5A] — which is exactly + // the uppercase letters we want to match. + uint64_t lowered = word | (ones * 0x20); + uint64_t letter = ((lowered | highs) - ones * 0x61) & ((ones * 0x7A | highs) - lowered) & highs; + + // Standard SWAR "has zero byte" idiom on (word XOR 0x5F) to find + // bytes equal to underscore. Safe from cross-byte borrows because + // the ASCII guard above ensures all bytes are < 0x80. + uint64_t xor_us = word ^ (ones * 0x5F); + uint64_t underscore = (xor_us - ones) & ~xor_us & highs; + + uint64_t ident = digit | letter | underscore; + + if (ident == highs) { + cursor += 8; + continue; + } + + // Find the first non-identifier byte. On little-endian the first + // byte sits in the least-significant position. + uint64_t not_ident = ~ident & highs; + cursor += pm_ctzll(not_ident) / 8; + return (size_t) (cursor - start); + } + + return (size_t) (cursor - start); +} + +#else + +// No-op fallback for big-endian or other unsupported platforms. +// The caller's byte-at-a-time loop handles everything. +#define scan_identifier_ascii(start, end) ((size_t) 0) + +#endif + /** * Like the above, this function is also used extremely frequently to lex all of * the identifiers in a source file once the first character has been found. So @@ -8155,6 +8376,10 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) { current_end += width; } } else { + // Fast path: scan ASCII identifier bytes using wide operations. + current_end += scan_identifier_ascii(current_end, end); + + // Byte-at-a-time fallback for the tail and any UTF-8 sequences. while ((width = char_is_identifier_utf8(current_end, end - current_end)) > 0) { current_end += width; } From bfa769271560436cfd032dba4796416b734c3f4f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 8 Mar 2026 23:04:27 -0400 Subject: [PATCH 123/289] Avoid unnecessary zero-ing of memory --- src/prism.c | 5 +++-- src/util/pm_line_offset_list.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/prism.c b/src/prism.c index dace322ee9..45333b8185 100644 --- a/src/prism.c +++ b/src/prism.c @@ -7755,7 +7755,8 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { pm_string_free(&key); // Allocate a new magic comment node to append to the parser's list. - pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) pm_arena_zalloc(&parser->metadata_arena, sizeof(pm_magic_comment_t), PRISM_ALIGNOF(pm_magic_comment_t)); + pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) pm_arena_alloc(&parser->metadata_arena, sizeof(pm_magic_comment_t), PRISM_ALIGNOF(pm_magic_comment_t)); + magic_comment->node.next = NULL; magic_comment->key = (pm_location_t) { .start = U32(key_start - parser->start), .length = U32(key_length) }; magic_comment->value = (pm_location_t) { .start = U32(value_start - parser->start), .length = value_length }; pm_list_append(&parser->magic_comment_list, (pm_list_node_t *) magic_comment); @@ -9421,7 +9422,7 @@ parser_lex_callback(pm_parser_t *parser) { */ static inline pm_comment_t * parser_comment(pm_parser_t *parser, pm_comment_type_t type) { - pm_comment_t *comment = (pm_comment_t *) pm_arena_zalloc(&parser->metadata_arena, sizeof(pm_comment_t), PRISM_ALIGNOF(pm_comment_t)); + pm_comment_t *comment = (pm_comment_t *) pm_arena_alloc(&parser->metadata_arena, sizeof(pm_comment_t), PRISM_ALIGNOF(pm_comment_t)); *comment = (pm_comment_t) { .type = type, diff --git a/src/util/pm_line_offset_list.c b/src/util/pm_line_offset_list.c index c0b41df406..41d3b2c81d 100644 --- a/src/util/pm_line_offset_list.c +++ b/src/util/pm_line_offset_list.c @@ -5,10 +5,10 @@ */ void pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity) { - list->offsets = (uint32_t *) pm_arena_zalloc(arena, capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t)); + list->offsets = (uint32_t *) pm_arena_alloc(arena, capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t)); - // This is 1 instead of 0 because we want to include the first line of the - // file as having offset 0, which is set because of the zero-initialization. + // The first line always has offset 0. + list->offsets[0] = 0; list->size = 1; list->capacity = capacity; } From f94fe6ba02d0fa1dbdf21618fd025dbdd4fdb362 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sun, 8 Mar 2026 23:43:18 -0400 Subject: [PATCH 124/289] Pre-size arena to avoid unnecessary growth --- include/prism/util/pm_arena.h | 10 +++++++ src/prism.c | 8 ++++++ src/util/pm_arena.c | 51 ++++++++++++++++++++++++++--------- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/include/prism/util/pm_arena.h b/include/prism/util/pm_arena.h index f376d13459..ac34c9b967 100644 --- a/include/prism/util/pm_arena.h +++ b/include/prism/util/pm_arena.h @@ -44,6 +44,16 @@ typedef struct { size_t block_count; } pm_arena_t; +/** + * Ensure the arena has at least `capacity` bytes available in its current + * block, allocating a new block if necessary. This allows callers to + * pre-size the arena to avoid repeated small block allocations. + * + * @param arena The arena to pre-size. + * @param capacity The minimum number of bytes to ensure are available. + */ +void pm_arena_reserve(pm_arena_t *arena, size_t capacity); + /** * Allocate memory from the arena. The returned memory is NOT zeroed. This * function is infallible — it aborts on allocation failure. diff --git a/src/prism.c b/src/prism.c index 45333b8185..25e11bab36 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22173,6 +22173,14 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si .warn_mismatched_indentation = true }; + // Pre-size the arenas based on input size to reduce the number of block + // allocations (and the kernel page zeroing they trigger). The ratios were + // measured empirically: AST arena ~3.3x input, metadata arena ~1.1x input. + // The reserve call is a no-op when the capacity is at or below the default + // arena block size, so small inputs don't waste an extra allocation. + if (size <= SIZE_MAX / 4) pm_arena_reserve(arena, size * 4); + if (size <= SIZE_MAX / 5 * 4) pm_arena_reserve(&parser->metadata_arena, size + size / 4); + // Initialize the constant pool. We're going to completely guess as to the // number of constants that we'll need based on the size of the input. The // ratio we chose here is actually less arbitrary than you might think. diff --git a/src/util/pm_arena.c b/src/util/pm_arena.c index a9b69b3c8d..5f1050ed03 100644 --- a/src/util/pm_arena.c +++ b/src/util/pm_arena.c @@ -1,5 +1,7 @@ #include "prism/util/pm_arena.h" +#include + /** * Compute the block allocation size using offsetof so it is correct regardless * of PM_FLEX_ARY_LEN. @@ -29,6 +31,42 @@ pm_arena_next_block_size(const pm_arena_t *arena, size_t min_size) { return size > min_size ? size : min_size; } +/** + * Allocate a new block with the given data capacity and initial usage, link it + * into the arena, and return it. Aborts on allocation failure. + */ +static pm_arena_block_t * +pm_arena_new_block(pm_arena_t *arena, size_t data_size, size_t initial_used) { + assert(initial_used <= data_size); + pm_arena_block_t *block = (pm_arena_block_t *) xmalloc(PM_ARENA_BLOCK_SIZE(data_size)); + + if (block == NULL) { + fprintf(stderr, "prism: out of memory; aborting\n"); + abort(); + } + + block->capacity = data_size; + block->used = initial_used; + block->prev = arena->current; + arena->current = block; + arena->block_count++; + + return block; +} + +/** + * Ensure the arena has at least `capacity` bytes available in its current + * block, allocating a new block if necessary. This allows callers to + * pre-size the arena to avoid repeated small block allocations. + */ +void +pm_arena_reserve(pm_arena_t *arena, size_t capacity) { + if (capacity <= PM_ARENA_INITIAL_SIZE) return; + if (arena->current != NULL && (arena->current->capacity - arena->current->used) >= capacity) return; + + pm_arena_new_block(arena, capacity, 0); +} + /** * Allocate memory from the arena. The returned memory is NOT zeroed. This * function is infallible — it aborts on allocation failure. @@ -51,18 +89,7 @@ pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { // New blocks from xmalloc are max-aligned, so data[] starts aligned for // any C type. No padding needed at the start. size_t block_data_size = pm_arena_next_block_size(arena, size); - pm_arena_block_t *block = (pm_arena_block_t *) xmalloc(PM_ARENA_BLOCK_SIZE(block_data_size)); - - if (block == NULL) { - fprintf(stderr, "prism: out of memory; aborting\n"); - abort(); - } - - block->capacity = block_data_size; - block->used = size; - block->prev = arena->current; - arena->current = block; - arena->block_count++; + pm_arena_block_t *block = pm_arena_new_block(arena, block_data_size, size); return block->data; } From dfdc9304566d6664df3c69e1881539f5586221fa Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 10:20:07 -0400 Subject: [PATCH 125/289] Force the allocation to be inlined --- include/prism/defines.h | 12 +++++++ include/prism/util/pm_arena.h | 42 ++++++++++++++++++++-- include/prism/util/pm_char.h | 1 + include/prism/util/pm_constant_pool.h | 5 ++- src/util/pm_arena.c | 52 ++++----------------------- 5 files changed, 63 insertions(+), 49 deletions(-) diff --git a/include/prism/defines.h b/include/prism/defines.h index 6afc239035..017f0b86e0 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -91,6 +91,18 @@ # define inline __inline #endif +/** + * Force a function to be inlined at every call site. Use sparingly — only for + * small, hot functions where the compiler's heuristics fail to inline. + */ +#if defined(_MSC_VER) +# define PRISM_FORCE_INLINE __forceinline +#elif defined(__GNUC__) || defined(__clang__) +# define PRISM_FORCE_INLINE inline __attribute__((always_inline)) +#else +# define PRISM_FORCE_INLINE inline +#endif + /** * Old Visual Studio versions before 2015 do not implement sprintf, but instead * implement _snprintf. We standard that here. diff --git a/include/prism/util/pm_arena.h b/include/prism/util/pm_arena.h index ac34c9b967..175b39c6df 100644 --- a/include/prism/util/pm_arena.h +++ b/include/prism/util/pm_arena.h @@ -54,16 +54,42 @@ typedef struct { */ void pm_arena_reserve(pm_arena_t *arena, size_t capacity); +/** + * Slow path for pm_arena_alloc: allocate a new block and return a pointer to + * the first `size` bytes. Do not call directly — use pm_arena_alloc instead. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @returns A pointer to the allocated memory. + */ +void * pm_arena_alloc_slow(pm_arena_t *arena, size_t size); + /** * Allocate memory from the arena. The returned memory is NOT zeroed. This * function is infallible — it aborts on allocation failure. * + * The fast path (bump pointer within the current block) is inlined at each + * call site. The slow path (new block allocation) is out-of-line. + * * @param arena The arena to allocate from. * @param size The number of bytes to allocate. * @param alignment The required alignment (must be a power of 2). * @returns A pointer to the allocated memory. */ -void * pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment); +static PRISM_FORCE_INLINE void * +pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { + if (arena->current != NULL) { + size_t used_aligned = (arena->current->used + alignment - 1) & ~(alignment - 1); + size_t needed = used_aligned + size; + + if (used_aligned >= arena->current->used && needed >= used_aligned && needed <= arena->current->capacity) { + arena->current->used = needed; + return arena->current->data + used_aligned; + } + } + + return pm_arena_alloc_slow(arena, size); +} /** * Allocate zero-initialized memory from the arena. This function is infallible @@ -74,7 +100,12 @@ void * pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment); * @param alignment The required alignment (must be a power of 2). * @returns A pointer to the allocated, zero-initialized memory. */ -void * pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment); +static inline void * +pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { + void *ptr = pm_arena_alloc(arena, size, alignment); + memset(ptr, 0, size); + return ptr; +} /** * Allocate memory from the arena and copy the given data into it. This is a @@ -86,7 +117,12 @@ void * pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment); * @param alignment The required alignment (must be a power of 2). * @returns A pointer to the allocated copy. */ -void * pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment); +static inline void * +pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { + void *dst = pm_arena_alloc(arena, size, alignment); + memcpy(dst, src, size); + return dst; +} /** * Free all blocks in the arena. After this call, all pointers returned by diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index f9a556cabe..06728ba938 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -30,6 +30,7 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); * * @param string The string to search. * @param length The maximum number of characters to search. + * @param arena The arena to allocate from when appending to line_offsets. * @param line_offsets The list of newlines to populate. * @param start_offset The offset at which the string occurs in the source, for * the purpose of tracking newlines. diff --git a/include/prism/util/pm_constant_pool.h b/include/prism/util/pm_constant_pool.h index 285a636a3a..fa74ee7b39 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/util/pm_constant_pool.h @@ -142,9 +142,9 @@ typedef struct { /** * Initialize a new constant pool with a given capacity. * + * @param arena The arena to allocate from. * @param pool The pool to initialize. * @param capacity The initial capacity of the pool. - * @return Whether the initialization succeeded. */ void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity); @@ -172,6 +172,7 @@ pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uin * Insert a constant into a constant pool that is a slice of a source string. * Returns the id of the constant, or 0 if any potential calls to resize fail. * + * @param arena The arena to allocate from. * @param pool The pool to insert the constant into. * @param start A pointer to the start of the constant. * @param length The length of the constant. @@ -184,6 +185,7 @@ pm_constant_id_t pm_constant_pool_insert_shared(pm_arena_t *arena, pm_constant_p * constant pool. Returns the id of the constant, or 0 if any potential calls to * resize fail. * + * @param arena The arena to allocate from. * @param pool The pool to insert the constant into. * @param start A pointer to the start of the constant. * @param length The length of the constant. @@ -195,6 +197,7 @@ pm_constant_id_t pm_constant_pool_insert_owned(pm_arena_t *arena, pm_constant_po * Insert a constant into a constant pool from memory that is constant. Returns * the id of the constant, or 0 if any potential calls to resize fail. * + * @param arena The arena to allocate from. * @param pool The pool to insert the constant into. * @param start A pointer to the start of the constant. * @param length The length of the constant. diff --git a/src/util/pm_arena.c b/src/util/pm_arena.c index 5f1050ed03..6b07e25210 100644 --- a/src/util/pm_arena.c +++ b/src/util/pm_arena.c @@ -24,7 +24,7 @@ static size_t pm_arena_next_block_size(const pm_arena_t *arena, size_t min_size) { size_t size = PM_ARENA_INITIAL_SIZE; - for (size_t i = PM_ARENA_GROWTH_INTERVAL; i <= arena->block_count; i += PM_ARENA_GROWTH_INTERVAL) { + for (size_t exp = PM_ARENA_GROWTH_INTERVAL; exp <= arena->block_count; exp += PM_ARENA_GROWTH_INTERVAL) { if (size < PM_ARENA_MAX_SIZE) size *= 2; } @@ -36,7 +36,7 @@ pm_arena_next_block_size(const pm_arena_t *arena, size_t min_size) { * into the arena, and return it. Aborts on allocation failure. */ static pm_arena_block_t * -pm_arena_new_block(pm_arena_t *arena, size_t data_size, size_t initial_used) { +pm_arena_block_new(pm_arena_t *arena, size_t data_size, size_t initial_used) { assert(initial_used <= data_size); pm_arena_block_t *block = (pm_arena_block_t *) xmalloc(PM_ARENA_BLOCK_SIZE(data_size)); @@ -63,58 +63,20 @@ void pm_arena_reserve(pm_arena_t *arena, size_t capacity) { if (capacity <= PM_ARENA_INITIAL_SIZE) return; if (arena->current != NULL && (arena->current->capacity - arena->current->used) >= capacity) return; - - pm_arena_new_block(arena, capacity, 0); + pm_arena_block_new(arena, capacity, 0); } /** - * Allocate memory from the arena. The returned memory is NOT zeroed. This - * function is infallible — it aborts on allocation failure. + * Slow path for pm_arena_alloc: allocate a new block and return a pointer to + * the first `size` bytes. Called when the current block has insufficient space. */ void * -pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { - // Try current block. - if (arena->current != NULL) { - size_t used_aligned = (arena->current->used + alignment - 1) & ~(alignment - 1); - size_t needed = used_aligned + size; - - // Guard against overflow in the alignment or size arithmetic. - if (used_aligned >= arena->current->used && needed >= used_aligned && needed <= arena->current->capacity) { - arena->current->used = needed; - return arena->current->data + used_aligned; - } - } - - // Allocate new block via xmalloc — memory is NOT zeroed. - // New blocks from xmalloc are max-aligned, so data[] starts aligned for - // any C type. No padding needed at the start. +pm_arena_alloc_slow(pm_arena_t *arena, size_t size) { size_t block_data_size = pm_arena_next_block_size(arena, size); - pm_arena_block_t *block = pm_arena_new_block(arena, block_data_size, size); - + pm_arena_block_t *block = pm_arena_block_new(arena, block_data_size, size); return block->data; } -/** - * Allocate zero-initialized memory from the arena. This function is infallible - * — it aborts on allocation failure. - */ -void * -pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { - void *ptr = pm_arena_alloc(arena, size, alignment); - memset(ptr, 0, size); - return ptr; -} - -/** - * Allocate memory from the arena and copy the given data into it. - */ -void * -pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { - void *dst = pm_arena_alloc(arena, size, alignment); - memcpy(dst, src, size); - return dst; -} - /** * Free all blocks in the arena. */ From 83f54c2dc2fb6b139c32533ffa25181d5a23f380 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 10:39:37 -0400 Subject: [PATCH 126/289] Inline pm_node_list_append, pm_char_is_whitespace, and pm_char_is_inline_whitespace --- include/prism/node.h | 19 +++++++++++++- include/prism/util/pm_char.h | 49 +++++++++++++++++++++++++----------- src/util/pm_char.c | 19 +------------- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/include/prism/node.h b/include/prism/node.h index 253f890055..f02f8ba892 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -17,6 +17,16 @@ #define PM_NODE_LIST_FOREACH(list, index, node) \ for (size_t index = 0; index < (list)->size && ((node) = (list)->nodes[index]); index++) +/** + * Slow path for pm_node_list_append: grow the list and append the node. + * Do not call directly — use pm_node_list_append instead. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param node The node to append. + */ +void pm_node_list_append_slow(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); + /** * Append a new node onto the end of the node list. * @@ -24,7 +34,14 @@ * @param list The list to append to. * @param node The node to append. */ -void pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); +static PRISM_FORCE_INLINE void +pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { + if (list->size < list->capacity) { + list->nodes[list->size++] = node; + } else { + pm_node_list_append_slow(arena, list, node); + } +} /** * Prepend a new node onto the beginning of the node list. diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index 06728ba938..f93ba6fe32 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -12,6 +12,40 @@ #include #include +/** Bit flag for whitespace characters in pm_byte_table. */ +#define PRISM_CHAR_BIT_WHITESPACE (1 << 0) + +/** Bit flag for inline whitespace characters in pm_byte_table. */ +#define PRISM_CHAR_BIT_INLINE_WHITESPACE (1 << 1) + +/** + * A lookup table for classifying bytes. Each entry is a bitfield of + * PRISM_CHAR_BIT_* flags. Defined in pm_char.c. + */ +extern const uint8_t pm_byte_table[256]; + +/** + * Returns true if the given character is a whitespace character. + * + * @param b The character to check. + * @return True if the given character is a whitespace character. + */ +static PRISM_FORCE_INLINE bool +pm_char_is_whitespace(const uint8_t b) { + return (pm_byte_table[b] & PRISM_CHAR_BIT_WHITESPACE) != 0; +} + +/** + * Returns true if the given character is an inline whitespace character. + * + * @param b The character to check. + * @return True if the given character is an inline whitespace character. + */ +static PRISM_FORCE_INLINE bool +pm_char_is_inline_whitespace(const uint8_t b) { + return (pm_byte_table[b] & PRISM_CHAR_BIT_INLINE_WHITESPACE) != 0; +} + /** * Returns the number of characters at the start of the string that are * whitespace. Disallows searching past the given maximum number of characters. @@ -156,21 +190,6 @@ size_t pm_strspn_regexp_option(const uint8_t *string, ptrdiff_t length); */ size_t pm_strspn_binary_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid); -/** - * Returns true if the given character is a whitespace character. - * - * @param b The character to check. - * @return True if the given character is a whitespace character. - */ -bool pm_char_is_whitespace(const uint8_t b); - -/** - * Returns true if the given character is an inline whitespace character. - * - * @param b The character to check. - * @return True if the given character is an inline whitespace character. - */ -bool pm_char_is_inline_whitespace(const uint8_t b); /** * Returns true if the given character is a binary digit. diff --git a/src/util/pm_char.c b/src/util/pm_char.c index ff8a88a687..3308d410b7 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -1,7 +1,5 @@ #include "prism/util/pm_char.h" -#define PRISM_CHAR_BIT_WHITESPACE (1 << 0) -#define PRISM_CHAR_BIT_INLINE_WHITESPACE (1 << 1) #define PRISM_CHAR_BIT_REGEXP_OPTION (1 << 2) #define PRISM_NUMBER_BIT_BINARY_DIGIT (1 << 0) @@ -13,7 +11,7 @@ #define PRISM_NUMBER_BIT_HEXADECIMAL_DIGIT (1 << 6) #define PRISM_NUMBER_BIT_HEXADECIMAL_NUMBER (1 << 7) -static const uint8_t pm_byte_table[256] = { +const uint8_t pm_byte_table[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, 0, 0, // 0x 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x @@ -126,21 +124,6 @@ pm_char_is_char_kind(const uint8_t b, uint8_t kind) { return (pm_byte_table[b] & kind) != 0; } -/** - * Returns true if the given character is a whitespace character. - */ -bool -pm_char_is_whitespace(const uint8_t b) { - return pm_char_is_char_kind(b, PRISM_CHAR_BIT_WHITESPACE); -} - -/** - * Returns true if the given character is an inline whitespace character. - */ -bool -pm_char_is_inline_whitespace(const uint8_t b) { - return pm_char_is_char_kind(b, PRISM_CHAR_BIT_INLINE_WHITESPACE); -} /** * Scan through the string and return the number of characters at the start of From a14431c2f1419e688403b754a6c34e04b4dea01e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 13:12:32 -0400 Subject: [PATCH 127/289] Avoid redundant whitespace scanning in magic comment lexing --- src/prism.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/prism.c b/src/prism.c index 25e11bab36..6f47f734cf 100644 --- a/src/prism.c +++ b/src/prism.c @@ -7587,11 +7587,17 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { if (pm_memchr(start, ':', (size_t) (end - start), parser->encoding_changed, parser->encoding) == NULL) { return false; } + + // Advance start past leading whitespace so the main loop begins + // directly at the key, avoiding a redundant whitespace scan. + start += pm_strspn_whitespace(start, end - start); } cursor = start; while (cursor < end) { - while (cursor < end && (pm_char_is_magic_comment_key_delimiter(*cursor) || pm_char_is_whitespace(*cursor))) cursor++; + if (indicator) { + cursor += pm_strspn_whitespace(cursor, end - cursor); + } const uint8_t *key_start = cursor; while (cursor < end && (!pm_char_is_magic_comment_key_delimiter(*cursor) && !pm_char_is_whitespace(*cursor))) cursor++; From b5b88bae803f793151c9c3515cf15e6cb8ecd8b9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 14:50:22 -0400 Subject: [PATCH 128/289] Potentially skip whitespace scanning for speed --- src/prism.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/prism.c b/src/prism.c index 6f47f734cf..2d9c414e0f 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9894,17 +9894,12 @@ parser_lex(pm_parser_t *parser) { // stores back to parser->current.end. bool chomping = true; while (parser->current.end < parser->end && chomping) { - { - static const uint8_t inline_whitespace[256] = { - [' '] = 1, ['\t'] = 1, ['\f'] = 1, ['\v'] = 1 - }; - const uint8_t *scan = parser->current.end; - while (scan < parser->end && inline_whitespace[*scan]) scan++; - if (scan > parser->current.end) { - parser->current.end = scan; - space_seen = true; - continue; - } + if (pm_char_is_inline_whitespace(*parser->current.end)) { + const uint8_t *scan = parser->current.end + 1; + while (scan < parser->end && pm_char_is_inline_whitespace(*scan)) scan++; + parser->current.end = scan; + space_seen = true; + continue; } switch (*parser->current.end) { From fbcd3fc69e47fa8064c3ce5612625d10d10b896d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 16:57:44 -0400 Subject: [PATCH 129/289] Inline three more functions, and lower the hash threshold for locals --- include/prism/util/pm_char.h | 29 +++++++++++++++--------- include/prism/util/pm_line_offset_list.h | 18 ++++++++++++++- src/prism.c | 2 +- src/util/pm_char.c | 9 -------- src/util/pm_line_offset_list.c | 16 ++++++------- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index f93ba6fe32..516390b21c 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -46,6 +46,24 @@ pm_char_is_inline_whitespace(const uint8_t b) { return (pm_byte_table[b] & PRISM_CHAR_BIT_INLINE_WHITESPACE) != 0; } +/** + * Returns the number of characters at the start of the string that are inline + * whitespace (space/tab). Scans the byte table directly for use in hot paths. + * + * @param string The string to search. + * @param length The maximum number of characters to search. + * @return The number of characters at the start of the string that are inline + * whitespace. + */ +static PRISM_FORCE_INLINE size_t +pm_strspn_inline_whitespace(const uint8_t *string, ptrdiff_t length) { + if (length <= 0) return 0; + size_t size = 0; + size_t maximum = (size_t) length; + while (size < maximum && (pm_byte_table[string[size]] & PRISM_CHAR_BIT_INLINE_WHITESPACE)) size++; + return size; +} + /** * Returns the number of characters at the start of the string that are * whitespace. Disallows searching past the given maximum number of characters. @@ -73,17 +91,6 @@ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); */ size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_arena_t *arena, pm_line_offset_list_t *line_offsets, uint32_t start_offset); -/** - * Returns the number of characters at the start of the string that are inline - * whitespace. Disallows searching past the given maximum number of characters. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @return The number of characters at the start of the string that are inline - * whitespace. - */ -size_t pm_strspn_inline_whitespace(const uint8_t *string, ptrdiff_t length); - /** * Returns the number of characters at the start of the string that are decimal * digits. Disallows searching past the given maximum number of characters. diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/util/pm_line_offset_list.h index 2b14b060a1..62a52da4ec 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/util/pm_line_offset_list.h @@ -64,6 +64,15 @@ void pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, si */ void pm_line_offset_list_clear(pm_line_offset_list_t *list); +/** + * Append a new offset to the list (slow path with resize). + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param cursor The offset to append. + */ +void pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor); + /** * Append a new offset to the list. * @@ -71,7 +80,14 @@ void pm_line_offset_list_clear(pm_line_offset_list_t *list); * @param list The list to append to. * @param cursor The offset to append. */ -void pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor); +static PRISM_FORCE_INLINE void +pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) { + if (list->size < list->capacity) { + list->offsets[list->size++] = cursor; + } else { + pm_line_offset_list_append_slow(arena, list, cursor); + } +} /** * Returns the line of the given offset. If the offset is not in the list, the diff --git a/src/prism.c b/src/prism.c index 2d9c414e0f..c17397c7b7 100644 --- a/src/prism.c +++ b/src/prism.c @@ -773,7 +773,7 @@ pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constan /** * The point at which the set of locals switches from being a list to a hash. */ -#define PM_LOCALS_HASH_THRESHOLD 9 +#define PM_LOCALS_HASH_THRESHOLD 5 static void pm_locals_free(pm_locals_t *locals) { diff --git a/src/util/pm_char.c b/src/util/pm_char.c index 3308d410b7..fc41b90601 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -98,15 +98,6 @@ pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_arena_ return size; } -/** - * Returns the number of characters at the start of the string that are inline - * whitespace. Disallows searching past the given maximum number of characters. - */ -size_t -pm_strspn_inline_whitespace(const uint8_t *string, ptrdiff_t length) { - return pm_strspn_char_kind(string, length, PRISM_CHAR_BIT_INLINE_WHITESPACE); -} - /** * Returns the number of characters at the start of the string that are regexp * options. Disallows searching past the given maximum number of characters. diff --git a/src/util/pm_line_offset_list.c b/src/util/pm_line_offset_list.c index 41d3b2c81d..0648901e29 100644 --- a/src/util/pm_line_offset_list.c +++ b/src/util/pm_line_offset_list.c @@ -22,19 +22,17 @@ pm_line_offset_list_clear(pm_line_offset_list_t *list) { } /** - * Append a new offset to the newline list. + * Append a new offset to the newline list (slow path: resize and store). */ void -pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) { - if (list->size == list->capacity) { - size_t new_capacity = (list->capacity * 3) / 2; - uint32_t *new_offsets = (uint32_t *) pm_arena_alloc(arena, new_capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t)); +pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) { + size_t new_capacity = (list->capacity * 3) / 2; + uint32_t *new_offsets = (uint32_t *) pm_arena_alloc(arena, new_capacity * sizeof(uint32_t), PRISM_ALIGNOF(uint32_t)); - memcpy(new_offsets, list->offsets, list->size * sizeof(uint32_t)); + memcpy(new_offsets, list->offsets, list->size * sizeof(uint32_t)); - list->offsets = new_offsets; - list->capacity = new_capacity; - } + list->offsets = new_offsets; + list->capacity = new_capacity; assert(list->size == 0 || cursor > list->offsets[list->size - 1]); list->offsets[list->size++] = cursor; From 20e626ada5038e1ec0de00b1a8629318284337c1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 22:35:55 -0400 Subject: [PATCH 130/289] Lex simple integer values as we are lexing --- include/prism/parser.h | 24 ++++++++--- src/prism.c | 92 ++++++++++++++++++++++++++++++++---------- 2 files changed, 90 insertions(+), 26 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index caa08538c6..60306a9974 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -793,12 +793,26 @@ struct pm_parser { pm_line_offset_list_t line_offsets; /** - * We want to add a flag to integer nodes that indicates their base. We only - * want to parse these once, but we don't have space on the token itself to - * communicate this information. So we store it here and pass it through - * when we find tokens that we need it for. + * State communicated from the lexer to the parser for integer tokens. */ - pm_node_flags_t integer_base; + struct { + /** + * A flag indicating the base of the integer (binary, octal, decimal, + * hexadecimal). Set during lexing and read during node creation. + */ + pm_node_flags_t base; + + /** + * When lexing a decimal integer that fits in a uint32_t, we compute + * the value during lexing to avoid re-scanning the digits during + * parsing. If lexed is true, this holds the result and + * pm_integer_parse can be skipped. + */ + uint32_t value; + + /** Whether value holds a valid pre-computed integer. */ + bool lexed; + } integer; /** * This string is used to pass information from the lexer to the parser. It diff --git a/src/prism.c b/src/prism.c index c17397c7b7..6a73adb2c4 100644 --- a/src/prism.c +++ b/src/prism.c @@ -4710,17 +4710,24 @@ pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token ((pm_integer_t) { 0 }) ); - pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; - switch (base) { - case PM_INTEGER_BASE_FLAGS_BINARY: integer_base = PM_INTEGER_BASE_BINARY; break; - case PM_INTEGER_BASE_FLAGS_OCTAL: integer_base = PM_INTEGER_BASE_OCTAL; break; - case PM_INTEGER_BASE_FLAGS_DECIMAL: break; - case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: integer_base = PM_INTEGER_BASE_HEXADECIMAL; break; - default: assert(false && "unreachable"); break; + if (parser->integer.lexed) { + // The value was already computed during lexing. + node->value.value = parser->integer.value; + parser->integer.lexed = false; + } else { + pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; + switch (base) { + case PM_INTEGER_BASE_FLAGS_BINARY: integer_base = PM_INTEGER_BASE_BINARY; break; + case PM_INTEGER_BASE_FLAGS_OCTAL: integer_base = PM_INTEGER_BASE_OCTAL; break; + case PM_INTEGER_BASE_FLAGS_DECIMAL: break; + case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: integer_base = PM_INTEGER_BASE_HEXADECIMAL; break; + default: assert(false && "unreachable"); break; + } + + pm_integer_parse(&node->value, integer_base, token->start, token->end); + pm_integer_arena_move(parser->arena, &node->value); } - pm_integer_parse(&node->value, integer_base, token->start, token->end); - pm_integer_arena_move(parser->arena, &node->value); return node; } @@ -8112,7 +8119,7 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { pm_parser_err_current(parser, PM_ERR_INVALID_NUMBER_BINARY); } - parser->integer_base = PM_INTEGER_BASE_FLAGS_BINARY; + parser->integer.base = PM_INTEGER_BASE_FLAGS_BINARY; break; // 0o1111 is an octal number @@ -8126,7 +8133,7 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { pm_parser_err_current(parser, PM_ERR_INVALID_NUMBER_OCTAL); } - parser->integer_base = PM_INTEGER_BASE_FLAGS_OCTAL; + parser->integer.base = PM_INTEGER_BASE_FLAGS_OCTAL; break; // 01111 is an octal number @@ -8140,7 +8147,7 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { case '6': case '7': parser->current.end += pm_strspn_octal_number_validate(parser, parser->current.end); - parser->integer_base = PM_INTEGER_BASE_FLAGS_OCTAL; + parser->integer.base = PM_INTEGER_BASE_FLAGS_OCTAL; break; // 0x1111 is a hexadecimal number @@ -8154,7 +8161,7 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { pm_parser_err_current(parser, PM_ERR_INVALID_NUMBER_HEXADECIMAL); } - parser->integer_base = PM_INTEGER_BASE_FLAGS_HEXADECIMAL; + parser->integer.base = PM_INTEGER_BASE_FLAGS_HEXADECIMAL; break; // 0.xxx is a float @@ -8172,11 +8179,53 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { } } else { // If it didn't start with a 0, then we'll lex as far as we can into a - // decimal number. - parser->current.end += pm_strspn_decimal_number_validate(parser, parser->current.end); + // decimal number. We compute the integer value inline to avoid + // re-scanning the digits later in pm_integer_parse. + { + const uint8_t *cursor = parser->current.end; + const uint8_t *end = parser->end; + uint64_t value = (uint64_t) (cursor[-1] - '0'); + + bool has_underscore = false; + bool prev_underscore = false; + const uint8_t *invalid = NULL; + + while (cursor < end) { + uint8_t c = *cursor; + if (c >= '0' && c <= '9') { + if (value <= UINT32_MAX) value = value * 10 + (uint64_t) (c - '0'); + prev_underscore = false; + cursor++; + } else if (c == '_') { + has_underscore = true; + if (prev_underscore && invalid == NULL) invalid = cursor; + prev_underscore = true; + cursor++; + } else { + break; + } + } + + if (has_underscore) { + if (prev_underscore && invalid == NULL) invalid = cursor - 1; + pm_strspn_number_validate(parser, parser->current.end, (size_t) (cursor - parser->current.end), invalid); + } + + if (value <= UINT32_MAX) { + parser->integer.value = (uint32_t) value; + parser->integer.lexed = true; + } + + parser->current.end = cursor; + } // Afterward, we'll lex as far as we can into an optional float suffix. type = lex_optional_float_suffix(parser, seen_e); + + // If it turned out to be a float, the cached integer value is invalid. + if (type != PM_TOKEN_INTEGER) { + parser->integer.lexed = false; + } } // At this point we have a completed number, but we want to provide the user @@ -8195,7 +8244,8 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { static pm_token_type_t lex_numeric(pm_parser_t *parser) { pm_token_type_t type = PM_TOKEN_INTEGER; - parser->integer_base = PM_INTEGER_BASE_FLAGS_DECIMAL; + parser->integer.base = PM_INTEGER_BASE_FLAGS_DECIMAL; + parser->integer.lexed = false; if (parser->current.end < parser->end) { bool seen_e = false; @@ -18302,22 +18352,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u return node; } case PM_TOKEN_INTEGER: { - pm_node_flags_t base = parser->integer_base; + pm_node_flags_t base = parser->integer.base; parser_lex(parser); return UP(pm_integer_node_create(parser, base, &parser->previous)); } case PM_TOKEN_INTEGER_IMAGINARY: { - pm_node_flags_t base = parser->integer_base; + pm_node_flags_t base = parser->integer.base; parser_lex(parser); return UP(pm_integer_node_imaginary_create(parser, base, &parser->previous)); } case PM_TOKEN_INTEGER_RATIONAL: { - pm_node_flags_t base = parser->integer_base; + pm_node_flags_t base = parser->integer.base; parser_lex(parser); return UP(pm_integer_node_rational_create(parser, base, &parser->previous)); } case PM_TOKEN_INTEGER_RATIONAL_IMAGINARY: { - pm_node_flags_t base = parser->integer_base; + pm_node_flags_t base = parser->integer.base; parser_lex(parser); return UP(pm_integer_node_rational_imaginary_create(parser, base, &parser->previous)); } @@ -22154,7 +22204,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si .filepath = { 0 }, .constant_pool = { 0 }, .line_offsets = { 0 }, - .integer_base = 0, + .integer = { 0 }, .current_string = PM_STRING_EMPTY, .start_line = 1, .explicit_encoding = NULL, From 2a1dc7930e19d6e2621c7a986ce33b7cd485e7b8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 9 Mar 2026 23:01:04 -0400 Subject: [PATCH 131/289] Only dispatch to lex_optional_float_suffix when it is possible --- src/prism.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/prism.c b/src/prism.c index 6a73adb2c4..561149764c 100644 --- a/src/prism.c +++ b/src/prism.c @@ -8220,11 +8220,20 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { } // Afterward, we'll lex as far as we can into an optional float suffix. - type = lex_optional_float_suffix(parser, seen_e); + // Guard the function call: the vast majority of decimal numbers are + // plain integers, so avoid the call when the next byte cannot start a + // float suffix. + { + uint8_t next = peek(parser); + if (next == '.' || next == 'e' || next == 'E') { + type = lex_optional_float_suffix(parser, seen_e); - // If it turned out to be a float, the cached integer value is invalid. - if (type != PM_TOKEN_INTEGER) { - parser->integer.lexed = false; + // If it turned out to be a float, the cached integer value is + // invalid. + if (type != PM_TOKEN_INTEGER) { + parser->integer.lexed = false; + } + } } } From a52c2bd2c0a8b410851deac6bb212c7364ead9d8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 04:19:53 +0000 Subject: [PATCH 132/289] Optimize constant pool hash for short strings --- src/util/pm_constant_pool.c | 63 ++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index c8c27a9618..4822130073 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -84,37 +84,48 @@ pm_constant_pool_hash(const uint8_t *start, size_t length) { static const uint64_t secret = 0x517cc1b727220a95ULL; uint64_t hash = (uint64_t) length; - const uint8_t *ptr = start; - size_t remaining = length; - - while (remaining >= 8) { + if (length <= 8) { + // Short strings: read first and last 4 bytes (overlapping for len < 8). + // This covers the majority of Ruby identifiers with a single multiply. + if (length >= 4) { + uint32_t a, b; + memcpy(&a, start, 4); + memcpy(&b, start + length - 4, 4); + hash ^= (uint64_t) a | ((uint64_t) b << 32); + } else if (length > 0) { + hash ^= (uint64_t) start[0] | ((uint64_t) start[length >> 1] << 8) | ((uint64_t) start[length - 1] << 16); + } + hash *= secret; + } else if (length <= 16) { + // Medium strings: read first and last 8 bytes (overlapping). + // Two multiplies instead of the three the loop-based approach needs. uint64_t word; - memcpy(&word, ptr, 8); + memcpy(&word, start, 8); hash ^= word; hash *= secret; - ptr += 8; - remaining -= 8; - } - - if (remaining >= 4) { - uint32_t word; - memcpy(&word, ptr, 4); - hash ^= (uint64_t) word; - hash *= secret; - ptr += 4; - remaining -= 4; - } - - if (remaining >= 2) { - hash ^= (uint64_t) ptr[0] | ((uint64_t) ptr[1] << 8); + memcpy(&word, start + length - 8, 8); + hash ^= word; hash *= secret; - ptr += 2; - remaining -= 2; - } + } else { + const uint8_t *ptr = start; + size_t remaining = length; + + while (remaining >= 8) { + uint64_t word; + memcpy(&word, ptr, 8); + hash ^= word; + hash *= secret; + ptr += 8; + remaining -= 8; + } - if (remaining >= 1) { - hash ^= (uint64_t) ptr[0]; - hash *= secret; + if (remaining > 0) { + // Read the last 8 bytes (overlapping with already-processed data). + uint64_t word; + memcpy(&word, start + length - 8, 8); + hash ^= word; + hash *= secret; + } } hash ^= hash >> 32; From dcb2e8c924026133e93d8e0910736c8272d4dd29 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 09:26:11 -0400 Subject: [PATCH 133/289] Include string in constant pool entry to avoid chasing pointer --- include/prism/util/pm_constant_pool.h | 9 +++++++ src/prism.c | 37 ++++++++++----------------- src/util/pm_constant_pool.c | 14 +++++----- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/prism/util/pm_constant_pool.h b/include/prism/util/pm_constant_pool.h index fa74ee7b39..c527343273 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/util/pm_constant_pool.h @@ -113,6 +113,15 @@ typedef struct { /** The hash of the bucket. */ uint32_t hash; + + /** + * A pointer to the start of the string, stored directly in the bucket to + * avoid a pointer chase to the constants array during probing. + */ + const uint8_t *start; + + /** The length of the string. */ + size_t length; } pm_constant_pool_bucket_t; /** A constant in the pool which effectively stores a string. */ diff --git a/src/prism.c b/src/prism.c index 561149764c..738231a2ef 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22233,34 +22233,25 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si .warn_mismatched_indentation = true }; - // Pre-size the arenas based on input size to reduce the number of block - // allocations (and the kernel page zeroing they trigger). The ratios were - // measured empirically: AST arena ~3.3x input, metadata arena ~1.1x input. - // The reserve call is a no-op when the capacity is at or below the default - // arena block size, so small inputs don't waste an extra allocation. + /* Pre-size the arenas based on input size to reduce the number of block + * allocations (and the kernel page zeroing they trigger). The ratios were + * measured empirically: AST arena ~3.3x input, metadata arena ~1.1x input. + * The reserve call is a no-op when the capacity is at or below the default + * arena block size, so small inputs don't waste an extra allocation. */ if (size <= SIZE_MAX / 4) pm_arena_reserve(arena, size * 4); if (size <= SIZE_MAX / 5 * 4) pm_arena_reserve(&parser->metadata_arena, size + size / 4); - // Initialize the constant pool. We're going to completely guess as to the - // number of constants that we'll need based on the size of the input. The - // ratio we chose here is actually less arbitrary than you might think. - // - // We took ~50K Ruby files and measured the size of the file versus the - // number of constants that were found in those files. Then we found the - // average and standard deviation of the ratios of constants/bytesize. Then - // we added 1.34 standard deviations to the average to get a ratio that - // would fit 75% of the files (for a two-tailed distribution). This works - // because there was about a 0.77 correlation and the distribution was - // roughly normal. - // - // This ratio will need to change if we add more constants to the constant - // pool for another node type. - uint32_t constant_size = ((uint32_t) size) / 95; + /* Initialize the constant pool. Measured across 1532 Ruby stdlib files, the + * bytes/constant ratio has a median of ~56 and a 90th percentile of ~135. + * We use 120 as a balance between over-allocation waste and resize + * frequency. Resizes are cheap with arena allocation, so we lean toward + * under-estimating. */ + uint32_t constant_size = ((uint32_t) size) / 120; pm_constant_pool_init(&parser->metadata_arena, &parser->constant_pool, constant_size < 4 ? 4 : constant_size); - // Initialize the newline list. Similar to the constant pool, we're going to - // guess at the number of newlines that we'll need based on the size of the - // input. + /* Initialize the line offset list. Similar to the constant pool, we are + * going to estimate the number of newlines that we will need based on the + * size of the input. */ size_t newline_size = size / 22; pm_line_offset_list_init(&parser->metadata_arena, &parser->line_offsets, newline_size < 4 ? 4 : newline_size); diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index 4822130073..74e2a12524 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -239,8 +239,7 @@ pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size pm_constant_pool_bucket_t *bucket; while (bucket = &pool->buckets[index], bucket->id != PM_CONSTANT_ID_UNSET) { - pm_constant_t *constant = &pool->constants[bucket->id - 1]; - if ((constant->length == length) && memcmp(constant->start, start, length) == 0) { + if ((bucket->length == length) && memcmp(bucket->start, start, length) == 0) { return bucket->id; } @@ -270,9 +269,7 @@ pm_constant_pool_insert(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8 // If there is a collision, then we need to check if the content is the // same as the content we are trying to insert. If it is, then we can // return the id of the existing constant. - pm_constant_t *constant = &pool->constants[bucket->id - 1]; - - if ((constant->length == length) && memcmp(constant->start, start, length) == 0) { + if ((bucket->length == length) && memcmp(bucket->start, start, length) == 0) { // Since we have found a match, we need to check if this is // attempting to insert a shared or an owned constant. We want to // prefer shared constants since they don't require allocations. @@ -280,8 +277,9 @@ pm_constant_pool_insert(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8 // If we're attempting to insert a shared constant and the // existing constant is owned, then we can replace it with the // shared constant to prefer non-owned references. - constant->start = start; + bucket->start = start; bucket->type = (unsigned int) (type & 0x3); + pool->constants[bucket->id - 1].start = start; } return bucket->id; @@ -298,7 +296,9 @@ pm_constant_pool_insert(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8 *bucket = (pm_constant_pool_bucket_t) { .id = (unsigned int) (id & 0x3fffffff), .type = (unsigned int) (type & 0x3), - .hash = hash + .hash = hash, + .start = start, + .length = length }; pool->constants[id - 1] = (pm_constant_t) { From c464b298aa44de699a66041d10a344d807be7f84 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 13:26:18 -0400 Subject: [PATCH 134/289] SIMD/SWAR for strpbrk --- include/prism/defines.h | 12 ++ src/prism.c | 59 ++-------- src/util/pm_strpbrk.c | 235 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 237 insertions(+), 69 deletions(-) diff --git a/include/prism/defines.h b/include/prism/defines.h index 017f0b86e0..0c131dbaed 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -276,6 +276,18 @@ #define PRISM_UNLIKELY(x) (x) #endif +/** + * Platform detection for SIMD / fast-path implementations. At most one of + * these macros is defined, selecting the best available vectorization strategy. + */ +#if (defined(__aarch64__) && defined(__ARM_NEON)) || defined(_M_ARM64) + #define PRISM_HAS_NEON +#elif (defined(__x86_64__) && defined(__SSSE3__)) || defined(_M_X64) + #define PRISM_HAS_SSSE3 +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define PRISM_HAS_SWAR +#endif + /** * Count trailing zero bits in a 64-bit value. Used by SWAR identifier scanning * to find the first non-matching byte in a word. diff --git a/src/prism.c b/src/prism.c index 738231a2ef..61a0417b4c 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1783,16 +1783,14 @@ char_is_identifier_utf8(const uint8_t *b, ptrdiff_t n) { * Callers must handle any remaining bytes (short tail or non-ASCII/UTF-8) * with a byte-at-a-time loop. * - * Up to four optimized implementations are selected at compile time, with a + * Up to three optimized implementations are selected at compile time, with a * no-op fallback for unsupported platforms: * 1. NEON — processes 16 bytes per iteration on aarch64. - * 2. SSE2 — processes 16 bytes per iteration on x86-64. - * 3. WASM SIMD — processes 16 bytes per iteration on WebAssembly. - * 4. SWAR — little-endian fallback, processes 8 bytes per iteration. - * 5. No-op — returns 0; the caller's byte-at-a-time loop handles everything. + * 2. SSSE3 — processes 16 bytes per iteration on x86-64. + * 3. SWAR — little-endian fallback, processes 8 bytes per iteration. */ -#if defined(__aarch64__) && defined(__ARM_NEON) +#if defined(PRISM_HAS_NEON) #include static inline size_t @@ -1844,8 +1842,8 @@ scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { return (size_t) (cursor - start); } -#elif defined(__x86_64__) && defined(__SSE2__) -#include +#elif defined(PRISM_HAS_SSSE3) +#include static inline size_t scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { @@ -1886,54 +1884,11 @@ scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { return (size_t) (cursor - start); } -#elif defined(__wasm_simd128__) -#include - -static inline size_t -scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { - const uint8_t *cursor = start; - - while (cursor + 16 <= end) { - v128_t v = wasm_v128_load(cursor); - - // Range checks via subtract-and-unsigned-compare: (v - lo) < count - // is true iff v is in [lo, lo + count). One subtract + one compare - // per range instead of two comparisons + AND. - - // Fold case: OR with 0x20 maps A-Z to a-z. - v128_t lowered = wasm_v128_or(v, wasm_u8x16_splat(0x20)); - v128_t letter = wasm_u8x16_lt( - wasm_i8x16_sub(lowered, wasm_u8x16_splat(0x61)), - wasm_u8x16_splat(0x1A)); - - v128_t digit = wasm_u8x16_lt( - wasm_i8x16_sub(v, wasm_u8x16_splat(0x30)), - wasm_u8x16_splat(0x0A)); - - v128_t underscore = wasm_i8x16_eq(v, wasm_u8x16_splat(0x5F)); - - v128_t ident = wasm_v128_or(wasm_v128_or(letter, digit), underscore); - - // Fast path: if all 16 bytes are identifier chars, advance. - if (wasm_i8x16_all_true(ident)) { - cursor += 16; - continue; - } - - // Extract bitmask only on the exit path to find the first non-match. - uint32_t mask = wasm_i8x16_bitmask(ident); - cursor += pm_ctzll((uint64_t) (~mask & 0xFFFF)); - return (size_t) (cursor - start); - } - - return (size_t) (cursor - start); -} - // The SWAR path uses pm_ctzll to find the first non-matching byte within a // word, which only yields the correct byte index on little-endian targets. // We gate on a positive little-endian check so that unknown-endianness // platforms safely fall through to the no-op fallback. -#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#elif defined(PRISM_HAS_SWAR) /** * Portable SWAR fallback — processes 8 bytes per iteration. diff --git a/src/util/pm_strpbrk.c b/src/util/pm_strpbrk.c index ddd6ef0ead..b1e4c9c6de 100644 --- a/src/util/pm_strpbrk.c +++ b/src/util/pm_strpbrk.c @@ -29,13 +29,214 @@ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, uint32_t start, uint32_t l parser->explicit_encoding = parser->encoding; } +/** + * Scan forward through ASCII bytes looking for a byte that is in the given + * charset. Returns true if a match was found, storing its offset in *index. + * Returns false if no match was found, storing the number of ASCII bytes + * consumed in *index (so the caller can skip past them). + * + * All charset characters must be ASCII (< 0x80). The scanner stops at non-ASCII + * bytes, returning control to the caller's encoding-aware loop. + * + * Up to three optimized implementations are selected at compile time, with a + * no-op fallback for unsupported platforms: + * 1. NEON — processes 16 bytes per iteration on aarch64. + * 2. SSSE3 — processes 16 bytes per iteration on x86-64. + * 3. SWAR — little-endian fallback, processes 8 bytes per iteration. + */ + +#if defined(PRISM_HAS_NEON) +#include + +static inline bool +scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { + // Build nibble-based lookup tables from the charset. All breakpoint + // characters are ASCII (< 0x80), so they fit within high nibbles 0-7. + // + // For each charset byte c, we set bit (1 << (c >> 4)) in low_lut[c & 0xF]. + // high_lut[h] = (1 << h) for each high nibble h present in the charset. + // A source byte s matches iff (low_lut[s & 0xF] & high_lut[s >> 4]) != 0. + uint8_t low_arr[16] = { 0 }; + uint8_t high_arr[16] = { 0 }; + uint64_t table[4] = { 0 }; + + for (const uint8_t *c = charset; *c != '\0'; c++) { + low_arr[*c & 0x0F] |= (uint8_t) (1 << (*c >> 4)); + high_arr[*c >> 4] = (uint8_t) (1 << (*c >> 4)); + table[*c >> 6] |= (uint64_t) 1 << (*c & 0x3F); + } + + uint8x16_t low_lut = vld1q_u8(low_arr); + uint8x16_t high_lut = vld1q_u8(high_arr); + uint8x16_t mask_0f = vdupq_n_u8(0x0F); + uint8x16_t mask_80 = vdupq_n_u8(0x80); + + size_t idx = 0; + + while (idx + 16 <= maximum) { + uint8x16_t v = vld1q_u8(source + idx); + + // If any byte has the high bit set, we have non-ASCII data. + // Return to let the caller's encoding-aware loop handle it. + if (vmaxvq_u8(vandq_u8(v, mask_80)) != 0) break; + + uint8x16_t lo_class = vqtbl1q_u8(low_lut, vandq_u8(v, mask_0f)); + uint8x16_t hi_class = vqtbl1q_u8(high_lut, vshrq_n_u8(v, 4)); + uint8x16_t matched = vtstq_u8(lo_class, hi_class); + + if (vmaxvq_u8(matched) == 0) { + idx += 16; + continue; + } + + // Find the position of the first matching byte. + uint64_t lo64 = vgetq_lane_u64(vreinterpretq_u64_u8(matched), 0); + if (lo64 != 0) { + *index = idx + pm_ctzll(lo64) / 8; + return true; + } + uint64_t hi64 = vgetq_lane_u64(vreinterpretq_u64_u8(matched), 1); + *index = idx + 8 + pm_ctzll(hi64) / 8; + return true; + } + + // Scalar tail for remaining < 16 ASCII bytes. + while (idx < maximum && source[idx] < 0x80) { + uint8_t byte = source[idx]; + if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + *index = idx; + return true; + } + idx++; + } + + *index = idx; + return false; +} + +#elif defined(PRISM_HAS_SSSE3) +#include + +static inline bool +scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { + // Build nibble-based lookup tables and bitmap table in a single pass. + uint8_t low_arr[16] = { 0 }; + uint8_t high_arr[16] = { 0 }; + uint64_t table[4] = { 0 }; + + for (const uint8_t *c = charset; *c != '\0'; c++) { + low_arr[*c & 0x0F] |= (uint8_t) (1 << (*c >> 4)); + high_arr[*c >> 4] = (uint8_t) (1 << (*c >> 4)); + table[*c >> 6] |= (uint64_t) 1 << (*c & 0x3F); + } + + __m128i low_lut = _mm_loadu_si128((const __m128i *) low_arr); + __m128i high_lut = _mm_loadu_si128((const __m128i *) high_arr); + __m128i mask_0f = _mm_set1_epi8(0x0F); + + size_t idx = 0; + + while (idx + 16 <= maximum) { + __m128i v = _mm_loadu_si128((const __m128i *) (source + idx)); + + // If any byte has the high bit set, stop. + if (_mm_movemask_epi8(v) != 0) break; + + // Nibble-based classification using pshufb (SSSE3), same as NEON + // vqtbl1q_u8. A byte matches iff (low_lut[lo_nib] & high_lut[hi_nib]) != 0. + __m128i lo_class = _mm_shuffle_epi8(low_lut, _mm_and_si128(v, mask_0f)); + __m128i hi_class = _mm_shuffle_epi8(high_lut, _mm_and_si128(_mm_srli_epi16(v, 4), mask_0f)); + __m128i matched = _mm_and_si128(lo_class, hi_class); + + // Check if any byte matched. + int mask = _mm_movemask_epi8(_mm_cmpeq_epi8(matched, _mm_setzero_si128())); + + if (mask == 0xFFFF) { + // All bytes were zero — no match in this chunk. + idx += 16; + continue; + } + + // Find the first matching byte (first non-zero in matched). + *index = idx + pm_ctzll((uint64_t) (~mask & 0xFFFF)); + return true; + } + + // Scalar tail. + while (idx < maximum && source[idx] < 0x80) { + uint8_t byte = source[idx]; + if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + *index = idx; + return true; + } + idx++; + } + + *index = idx; + return false; +} + +#elif defined(PRISM_HAS_SWAR) + +static inline bool +scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { + // Build a 256-bit lookup table (one bit per ASCII value). + uint64_t table[4] = { 0 }; + for (const uint8_t *c = charset; *c != '\0'; c++) { + table[*c >> 6] |= (uint64_t) 1 << (*c & 0x3F); + } + + static const uint64_t highs = 0x8080808080808080ULL; + size_t idx = 0; + + while (idx + 8 <= maximum) { + uint64_t word; + memcpy(&word, source + idx, 8); + + // Bail on any non-ASCII byte. + if (word & highs) break; + + // Check each byte against the charset table. + for (size_t j = 0; j < 8; j++) { + uint8_t byte = source[idx + j]; + if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + *index = idx + j; + return true; + } + } + + idx += 8; + } + + // Scalar tail. + while (idx < maximum && source[idx] < 0x80) { + uint8_t byte = source[idx]; + if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + *index = idx; + return true; + } + idx++; + } + + *index = idx; + return false; +} + +#else + +static inline bool +scan_strpbrk_ascii(PRISM_ATTRIBUTE_UNUSED const uint8_t *source, PRISM_ATTRIBUTE_UNUSED size_t maximum, PRISM_ATTRIBUTE_UNUSED const uint8_t *charset, size_t *index) { + *index = 0; + return false; +} + +#endif + /** * This is the default path. */ static inline const uint8_t * -pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { - size_t index = 0; - +pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { return source + index; @@ -73,9 +274,7 @@ pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *chars * This is the path when the encoding is ASCII-8BIT. */ static inline const uint8_t * -pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { - size_t index = 0; - +pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { return source + index; @@ -92,8 +291,7 @@ pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t * This is the slow path that does care about the encoding. */ static inline const uint8_t * -pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { - size_t index = 0; +pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { const pm_encoding_t *encoding = parser->encoding; while (index < maximum) { @@ -135,8 +333,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t * the encoding only supports single-byte characters. */ static inline const uint8_t * -pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { - size_t index = 0; +pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { const pm_encoding_t *encoding = parser->encoding; while (index < maximum) { @@ -192,15 +389,19 @@ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t */ const uint8_t * pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, ptrdiff_t length, bool validate) { - if (length <= 0) { - return NULL; - } else if (!parser->encoding_changed) { - return pm_strpbrk_utf8(parser, source, charset, (size_t) length, validate); + if (length <= 0) return NULL; + + size_t maximum = (size_t) length; + size_t index = 0; + if (scan_strpbrk_ascii(source, maximum, charset, &index)) return source + index; + + if (!parser->encoding_changed) { + return pm_strpbrk_utf8(parser, source, charset, index, maximum, validate); } else if (parser->encoding == PM_ENCODING_ASCII_8BIT_ENTRY) { - return pm_strpbrk_ascii_8bit(parser, source, charset, (size_t) length, validate); + return pm_strpbrk_ascii_8bit(parser, source, charset, index, maximum, validate); } else if (parser->encoding->multibyte) { - return pm_strpbrk_multi_byte(parser, source, charset, (size_t) length, validate); + return pm_strpbrk_multi_byte(parser, source, charset, index, maximum, validate); } else { - return pm_strpbrk_single_byte(parser, source, charset, (size_t) length, validate); + return pm_strpbrk_single_byte(parser, source, charset, index, maximum, validate); } } From 559f24fae05e399056cf88fd2f498691e0b0f117 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 15:08:59 -0400 Subject: [PATCH 135/289] Fix a bug where we removed the \r warning --- src/prism.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/prism.c b/src/prism.c index 61a0417b4c..9556161342 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9908,12 +9908,17 @@ parser_lex(pm_parser_t *parser) { // stores back to parser->current.end. bool chomping = true; while (parser->current.end < parser->end && chomping) { - if (pm_char_is_inline_whitespace(*parser->current.end)) { - const uint8_t *scan = parser->current.end + 1; - while (scan < parser->end && pm_char_is_inline_whitespace(*scan)) scan++; - parser->current.end = scan; - space_seen = true; - continue; + { + static const uint8_t inline_whitespace[256] = { + [' '] = 1, ['\t'] = 1, ['\f'] = 1, ['\v'] = 1 + }; + const uint8_t *scan = parser->current.end; + while (scan < parser->end && inline_whitespace[*scan]) scan++; + if (scan > parser->current.end) { + parser->current.end = scan; + space_seen = true; + continue; + } } switch (*parser->current.end) { From fc0ec4c9f487f37b6dfa32331b927bfbc66c26e2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 20:06:11 -0400 Subject: [PATCH 136/289] Use a bloom filter to quickly reject local lookups --- include/prism/parser.h | 7 +++++++ src/prism.c | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/include/prism/parser.h b/include/prism/parser.h index 60306a9974..b7fe1a3c97 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -556,6 +556,13 @@ typedef struct pm_locals { /** The capacity of the local variables set. */ uint32_t capacity; + /** + * A bloom filter over constant IDs stored in this set. Used to quickly + * reject lookups for names that are definitely not present, avoiding the + * cost of a linear scan or hash probe. + */ + uint32_t bloom; + /** The nullable allocated memory for the local variables in the set. */ pm_local_t *locals; } pm_locals_t; diff --git a/src/prism.c b/src/prism.c index 9556161342..dd56c71c64 100644 --- a/src/prism.c +++ b/src/prism.c @@ -855,6 +855,8 @@ pm_locals_write(pm_locals_t *locals, pm_constant_id_t name, uint32_t start, uint pm_locals_resize(locals); } + locals->bloom |= (1u << (name & 31)); + if (locals->capacity < PM_LOCALS_HASH_THRESHOLD) { for (uint32_t index = 0; index < locals->capacity; index++) { pm_local_t *local = &locals->locals[index]; @@ -907,6 +909,8 @@ pm_locals_write(pm_locals_t *locals, pm_constant_id_t name, uint32_t start, uint */ static uint32_t pm_locals_find(pm_locals_t *locals, pm_constant_id_t name) { + if (!(locals->bloom & (1u << (name & 31)))) return UINT32_MAX; + if (locals->capacity < PM_LOCALS_HASH_THRESHOLD) { for (uint32_t index = 0; index < locals->size; index++) { pm_local_t *local = &locals->locals[index]; From 46656b2fd5999ba6302b933394b10d59d3b15077 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 10 Mar 2026 22:18:26 -0400 Subject: [PATCH 137/289] Cache strpbrk lookup tables --- include/prism/parser.h | 21 +++++++++ src/util/pm_strpbrk.c | 96 +++++++++++++++++++++++------------------- 2 files changed, 74 insertions(+), 43 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index b7fe1a3c97..b68d56b564 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -962,6 +962,27 @@ struct pm_parser { * toggled with a magic comment. */ bool warn_mismatched_indentation; + +#if defined(PRISM_HAS_NEON) || defined(PRISM_HAS_SSSE3) || defined(PRISM_HAS_SWAR) + /** + * Cached lookup tables for pm_strpbrk's SIMD fast path. Avoids rebuilding + * the nibble-based tables on every call when the charset hasn't changed + * (which is the common case during string/regex/list lexing). + */ + struct { + /** The cached charset (null-terminated, max 11 chars + NUL). */ + uint8_t charset[12]; + + /** Nibble-based low lookup table for SIMD matching. */ + uint8_t low_lut[16]; + + /** Nibble-based high lookup table for SIMD matching. */ + uint8_t high_lut[16]; + + /** Scalar fallback table (4 x 64-bit bitmasks covering all ASCII). */ + uint64_t table[4]; + } strpbrk_cache; +#endif }; #endif diff --git a/src/util/pm_strpbrk.c b/src/util/pm_strpbrk.c index b1e4c9c6de..f9b5bc85eb 100644 --- a/src/util/pm_strpbrk.c +++ b/src/util/pm_strpbrk.c @@ -45,29 +45,52 @@ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, uint32_t start, uint32_t l * 3. SWAR — little-endian fallback, processes 8 bytes per iteration. */ -#if defined(PRISM_HAS_NEON) -#include +#if defined(PRISM_HAS_NEON) || defined(PRISM_HAS_SSSE3) || defined(PRISM_HAS_SWAR) -static inline bool -scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { - // Build nibble-based lookup tables from the charset. All breakpoint - // characters are ASCII (< 0x80), so they fit within high nibbles 0-7. - // - // For each charset byte c, we set bit (1 << (c >> 4)) in low_lut[c & 0xF]. - // high_lut[h] = (1 << h) for each high nibble h present in the charset. - // A source byte s matches iff (low_lut[s & 0xF] & high_lut[s >> 4]) != 0. - uint8_t low_arr[16] = { 0 }; - uint8_t high_arr[16] = { 0 }; - uint64_t table[4] = { 0 }; +/** + * Update the cached strpbrk lookup tables if the charset has changed. The + * parser caches the last charset's precomputed tables so that repeated calls + * with the same breakpoints (the common case during string/regex/list lexing) + * skip table construction entirely. + * + * Builds three structures: + * - low_lut/high_lut: nibble-based lookup tables for SIMD matching (NEON/SSSE3) + * - table: 256-bit bitmap for scalar fallback matching (all platforms) + */ +static inline void +pm_strpbrk_cache_update(pm_parser_t *parser, const uint8_t *charset) { + // The cache key is the full 12-byte charset buffer. Since it is always + // NUL-padded, a fixed-size comparison covers both content and length. + if (memcmp(parser->strpbrk_cache.charset, charset, sizeof(parser->strpbrk_cache.charset)) == 0) return; + + memset(parser->strpbrk_cache.low_lut, 0, sizeof(parser->strpbrk_cache.low_lut)); + memset(parser->strpbrk_cache.high_lut, 0, sizeof(parser->strpbrk_cache.high_lut)); + memset(parser->strpbrk_cache.table, 0, sizeof(parser->strpbrk_cache.table)); + size_t charset_len = 0; for (const uint8_t *c = charset; *c != '\0'; c++) { - low_arr[*c & 0x0F] |= (uint8_t) (1 << (*c >> 4)); - high_arr[*c >> 4] = (uint8_t) (1 << (*c >> 4)); - table[*c >> 6] |= (uint64_t) 1 << (*c & 0x3F); + parser->strpbrk_cache.low_lut[*c & 0x0F] |= (uint8_t) (1 << (*c >> 4)); + parser->strpbrk_cache.high_lut[*c >> 4] = (uint8_t) (1 << (*c >> 4)); + parser->strpbrk_cache.table[*c >> 6] |= (uint64_t) 1 << (*c & 0x3F); + charset_len++; } - uint8x16_t low_lut = vld1q_u8(low_arr); - uint8x16_t high_lut = vld1q_u8(high_arr); + // Store the new charset key, NUL-padded to the full buffer size. + memcpy(parser->strpbrk_cache.charset, charset, charset_len + 1); + memset(parser->strpbrk_cache.charset + charset_len + 1, 0, sizeof(parser->strpbrk_cache.charset) - charset_len - 1); +} + +#endif + +#if defined(PRISM_HAS_NEON) +#include + +static inline bool +scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { + pm_strpbrk_cache_update(parser, charset); + + uint8x16_t low_lut = vld1q_u8(parser->strpbrk_cache.low_lut); + uint8x16_t high_lut = vld1q_u8(parser->strpbrk_cache.high_lut); uint8x16_t mask_0f = vdupq_n_u8(0x0F); uint8x16_t mask_80 = vdupq_n_u8(0x80); @@ -103,7 +126,7 @@ scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset // Scalar tail for remaining < 16 ASCII bytes. while (idx < maximum && source[idx] < 0x80) { uint8_t byte = source[idx]; - if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + if (parser->strpbrk_cache.table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { *index = idx; return true; } @@ -118,20 +141,11 @@ scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset #include static inline bool -scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { - // Build nibble-based lookup tables and bitmap table in a single pass. - uint8_t low_arr[16] = { 0 }; - uint8_t high_arr[16] = { 0 }; - uint64_t table[4] = { 0 }; +scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { + pm_strpbrk_cache_update(parser, charset); - for (const uint8_t *c = charset; *c != '\0'; c++) { - low_arr[*c & 0x0F] |= (uint8_t) (1 << (*c >> 4)); - high_arr[*c >> 4] = (uint8_t) (1 << (*c >> 4)); - table[*c >> 6] |= (uint64_t) 1 << (*c & 0x3F); - } - - __m128i low_lut = _mm_loadu_si128((const __m128i *) low_arr); - __m128i high_lut = _mm_loadu_si128((const __m128i *) high_arr); + __m128i low_lut = _mm_loadu_si128((const __m128i *) parser->strpbrk_cache.low_lut); + __m128i high_lut = _mm_loadu_si128((const __m128i *) parser->strpbrk_cache.high_lut); __m128i mask_0f = _mm_set1_epi8(0x0F); size_t idx = 0; @@ -165,7 +179,7 @@ scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset // Scalar tail. while (idx < maximum && source[idx] < 0x80) { uint8_t byte = source[idx]; - if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + if (parser->strpbrk_cache.table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { *index = idx; return true; } @@ -179,12 +193,8 @@ scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset #elif defined(PRISM_HAS_SWAR) static inline bool -scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { - // Build a 256-bit lookup table (one bit per ASCII value). - uint64_t table[4] = { 0 }; - for (const uint8_t *c = charset; *c != '\0'; c++) { - table[*c >> 6] |= (uint64_t) 1 << (*c & 0x3F); - } +scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { + pm_strpbrk_cache_update(parser, charset); static const uint64_t highs = 0x8080808080808080ULL; size_t idx = 0; @@ -199,7 +209,7 @@ scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset // Check each byte against the charset table. for (size_t j = 0; j < 8; j++) { uint8_t byte = source[idx + j]; - if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + if (parser->strpbrk_cache.table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { *index = idx + j; return true; } @@ -211,7 +221,7 @@ scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset // Scalar tail. while (idx < maximum && source[idx] < 0x80) { uint8_t byte = source[idx]; - if (table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { + if (parser->strpbrk_cache.table[byte >> 6] & ((uint64_t) 1 << (byte & 0x3F))) { *index = idx; return true; } @@ -225,7 +235,7 @@ scan_strpbrk_ascii(const uint8_t *source, size_t maximum, const uint8_t *charset #else static inline bool -scan_strpbrk_ascii(PRISM_ATTRIBUTE_UNUSED const uint8_t *source, PRISM_ATTRIBUTE_UNUSED size_t maximum, PRISM_ATTRIBUTE_UNUSED const uint8_t *charset, size_t *index) { +scan_strpbrk_ascii(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, PRISM_ATTRIBUTE_UNUSED const uint8_t *source, PRISM_ATTRIBUTE_UNUSED size_t maximum, PRISM_ATTRIBUTE_UNUSED const uint8_t *charset, size_t *index) { *index = 0; return false; } @@ -393,7 +403,7 @@ pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, p size_t maximum = (size_t) length; size_t index = 0; - if (scan_strpbrk_ascii(source, maximum, charset, &index)) return source + index; + if (scan_strpbrk_ascii(parser, source, maximum, charset, &index)) return source + index; if (!parser->encoding_changed) { return pm_strpbrk_utf8(parser, source, charset, index, maximum, validate); From b2658d2262f13774c4beb9feffd7b3c4f7aadecc Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 16 Mar 2026 23:16:41 -0400 Subject: [PATCH 138/289] Fix up rebase errors --- src/prism.c | 10 +++++----- src/regexp.c | 5 +++-- src/util/pm_char.c | 8 -------- src/util/pm_strpbrk.c | 8 ++++++++ templates/src/node.c.erb | 5 +++-- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/prism.c b/src/prism.c index dd56c71c64..d98f82d8fe 100644 --- a/src/prism.c +++ b/src/prism.c @@ -8851,7 +8851,7 @@ escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_ } if (width == 1) { - if (*parser->current.end == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); + if (*parser->current.end == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(*parser->current.end++, flags)); } else if (width > 1) { // Valid multibyte character. Just ignore escape. @@ -9168,7 +9168,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } - if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); + if (peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL)); return; @@ -9227,7 +9227,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } - if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); + if (peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL)); return; @@ -9281,7 +9281,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } - if (peeked == '\n') pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); + if (peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1); parser->current.end++; escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META)); return; @@ -9289,7 +9289,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } case '\r': { if (peek_offset(parser, 1) == '\n') { - pm_line_offset_list_append(&parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 2); + pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 2); parser->current.end += 2; escape_write_byte_encoded(parser, buffer, flags, escape_byte('\n', flags)); return; diff --git a/src/regexp.c b/src/regexp.c index f864e187c9..df8bb69b21 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -128,7 +128,7 @@ pm_regexp_parse_error(pm_regexp_parser_t *parser, const uint8_t *start, const ui loc_length = (uint32_t) (parser->node_end - parser->node_start); } - pm_diagnostic_list_append_format(&pm->error_list, loc_start, loc_length, PM_ERR_REGEXP_PARSE_ERROR, message); + pm_diagnostic_list_append_format(&pm->metadata_arena, &pm->error_list, loc_start, loc_length, PM_ERR_REGEXP_PARSE_ERROR, message); } /** @@ -146,7 +146,7 @@ pm_regexp_parse_error(pm_regexp_parser_t *parser, const uint8_t *start, const ui loc_start__ = (uint32_t) ((parser_)->node_start - pm__->start); \ loc_length__ = (uint32_t) ((parser_)->node_end - (parser_)->node_start); \ } \ - pm_diagnostic_list_append_format(&pm__->error_list, loc_start__, loc_length__, diag_id, __VA_ARGS__); \ + pm_diagnostic_list_append_format(&pm__->metadata_arena, &pm__->error_list, loc_start__, loc_length__, diag_id, __VA_ARGS__); \ } while (0) /** @@ -1397,6 +1397,7 @@ pm_regexp_format_for_error(pm_buffer_t *buffer, const pm_encoding_t *encoding, c */ #define PM_REGEXP_ENCODING_ERROR(parser, diag_id, ...) \ pm_diagnostic_list_append_format( \ + &(parser)->parser->metadata_arena, \ &(parser)->parser->error_list, \ (uint32_t) ((parser)->node_start - (parser)->parser->start), \ (uint32_t) ((parser)->node_end - (parser)->node_start), \ diff --git a/src/util/pm_char.c b/src/util/pm_char.c index fc41b90601..ac283af356 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -107,14 +107,6 @@ pm_strspn_regexp_option(const uint8_t *string, ptrdiff_t length) { return pm_strspn_char_kind(string, length, PRISM_CHAR_BIT_REGEXP_OPTION); } -/** - * Returns true if the given character matches the given kind. - */ -static inline bool -pm_char_is_char_kind(const uint8_t b, uint8_t kind) { - return (pm_byte_table[b] & kind) != 0; -} - /** * Scan through the string and return the number of characters at the start of diff --git a/src/util/pm_strpbrk.c b/src/util/pm_strpbrk.c index f9b5bc85eb..496739c9f8 100644 --- a/src/util/pm_strpbrk.c +++ b/src/util/pm_strpbrk.c @@ -67,6 +67,14 @@ pm_strpbrk_cache_update(pm_parser_t *parser, const uint8_t *charset) { memset(parser->strpbrk_cache.high_lut, 0, sizeof(parser->strpbrk_cache.high_lut)); memset(parser->strpbrk_cache.table, 0, sizeof(parser->strpbrk_cache.table)); + // Always include NUL in the tables. The slow path uses strchr, which + // always matches NUL (it finds the C string terminator), so NUL is + // effectively always a breakpoint. Replicating that here lets the fast + // scanner handle NUL at full speed instead of bailing to the slow path. + parser->strpbrk_cache.low_lut[0x00] |= (uint8_t) (1 << 0); + parser->strpbrk_cache.high_lut[0x00] = (uint8_t) (1 << 0); + parser->strpbrk_cache.table[0] |= (uint64_t) 1; + size_t charset_len = 0; for (const uint8_t *c = charset; *c != '\0'; c++) { parser->strpbrk_cache.low_lut[*c & 0x0F] |= (uint8_t) (1 << (*c >> 4)); diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index df59545129..93ea275a54 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -39,10 +39,11 @@ pm_node_list_grow(pm_arena_t *arena, pm_node_list_t *list, size_t size) { } /** - * Append a new node onto the end of the node list. + * Slow path for pm_node_list_append: grow the list and append the node. + * Do not call directly - use pm_node_list_append instead. */ void -pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { +pm_node_list_append_slow(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { pm_node_list_grow(arena, list, 1); list->nodes[list->size++] = node; } From 5fe0448219e9756832b9447111a452620003b99c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 06:48:50 -0400 Subject: [PATCH 139/289] More correctly detect SIMD on MSVC --- include/prism/defines.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/prism/defines.h b/include/prism/defines.h index 0c131dbaed..d666582b17 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -280,9 +280,9 @@ * Platform detection for SIMD / fast-path implementations. At most one of * these macros is defined, selecting the best available vectorization strategy. */ -#if (defined(__aarch64__) && defined(__ARM_NEON)) || defined(_M_ARM64) +#if (defined(__aarch64__) && defined(__ARM_NEON)) || (defined(_MSC_VER) && defined(_M_ARM64)) #define PRISM_HAS_NEON -#elif (defined(__x86_64__) && defined(__SSSE3__)) || defined(_M_X64) +#elif (defined(__x86_64__) && defined(__SSSE3__)) || (defined(_MSC_VER) && defined(_M_X64)) #define PRISM_HAS_SSSE3 #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define PRISM_HAS_SWAR From 29578689798cd329a3ce2bf0c9af04a1e10c0d8d Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Tue, 17 Mar 2026 12:17:28 +0100 Subject: [PATCH 140/289] Add workflow changes from 4.0 branch There should be no harm in having them and it will hopefully remind me to udpate this for newer branches --- .github/workflows/cpp-bindings.yml | 1 + .github/workflows/cruby-bindings.yml | 2 ++ .github/workflows/documentation.yml | 1 + .github/workflows/java-wasm-bindings.yml | 1 + .github/workflows/javascript-bindings.yml | 1 + .github/workflows/main.yml | 1 + .github/workflows/rust-bindings.yml | 1 + .github/workflows/sync-ruby.yml | 14 ++++++++++++-- 8 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cpp-bindings.yml b/.github/workflows/cpp-bindings.yml index 54593ff548..2a53272c4b 100644 --- a/.github/workflows/cpp-bindings.yml +++ b/.github/workflows/cpp-bindings.yml @@ -10,6 +10,7 @@ on: - "*akefile*" branches: - main + - ruby-4.0 pull_request: jobs: diff --git a/.github/workflows/cruby-bindings.yml b/.github/workflows/cruby-bindings.yml index d635e550f0..6fed2aa44a 100644 --- a/.github/workflows/cruby-bindings.yml +++ b/.github/workflows/cruby-bindings.yml @@ -9,6 +9,8 @@ on: branches: - main pull_request: + branches: + - main jobs: test-all: diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index c5258a2f5e..e3fc52303c 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -8,6 +8,7 @@ on: push: branches: - main + - ruby-4.0 pull_request: jobs: diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index d7fe81f171..4715d6f93b 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -9,6 +9,7 @@ on: - "*akefile*" branches: - main + - ruby-4.0 pull_request: jobs: diff --git a/.github/workflows/javascript-bindings.yml b/.github/workflows/javascript-bindings.yml index 3753ea2ce9..2e4330b2be 100644 --- a/.github/workflows/javascript-bindings.yml +++ b/.github/workflows/javascript-bindings.yml @@ -9,6 +9,7 @@ on: - "*akefile*" branches: - main + - ruby-4.0 pull_request: jobs: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9ed312d4d5..356956ec8f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,6 +8,7 @@ on: push: branches: - main + - ruby-4.0 pull_request: jobs: diff --git a/.github/workflows/rust-bindings.yml b/.github/workflows/rust-bindings.yml index 51e90fdaf0..850646c772 100644 --- a/.github/workflows/rust-bindings.yml +++ b/.github/workflows/rust-bindings.yml @@ -10,6 +10,7 @@ on: - "*akefile*" branches: - main + - ruby-4.0 pull_request: env: diff --git a/.github/workflows/sync-ruby.yml b/.github/workflows/sync-ruby.yml index 72be2a09c5..55401876f9 100644 --- a/.github/workflows/sync-ruby.yml +++ b/.github/workflows/sync-ruby.yml @@ -1,7 +1,9 @@ name: Sync ruby on: push: - branches: [main] + branches: + - main + - ruby-4.0 jobs: sync: name: Sync ruby @@ -10,6 +12,14 @@ jobs: steps: - uses: actions/checkout@v6 + - name: Set ruby/ruby target branch + id: target + run: | + case "$GITHUB_REF_NAME" in + main) echo "ref=master" >> "$GITHUB_OUTPUT" ;; + ruby-4.0) echo "ref=ruby_4_0" >> "$GITHUB_OUTPUT" ;; + esac + - name: Create GitHub App token id: app-token uses: actions/create-github-app-token@v3 @@ -26,7 +36,7 @@ jobs: repo: ruby workflow_file_name: sync_default_gems.yml github_token: ${{ steps.app-token.outputs.token }} - ref: master + ref: ${{ steps.target.outputs.ref }} client_payload: | {"gem":"${{ github.event.repository.name }}","before":"${{ github.event.before }}","after":"${{ github.event.after }}"} propagate_failure: true From f5ae7b73eea485959347ebb73c92e7a40d3b8aa8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 07:18:05 -0400 Subject: [PATCH 141/289] Ensure allocations to the constant pool are through the arena --- src/prism.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/prism.c b/src/prism.c index d98f82d8fe..783e624947 100644 --- a/src/prism.c +++ b/src/prism.c @@ -20717,11 +20717,9 @@ parse_regular_expression_named_capture(pm_parser_t *parser, const pm_string_t *c start = parser->start + PM_NODE_START(call->receiver); end = parser->start + PM_NODE_END(call->receiver); - void *memory = xmalloc(length); - if (memory == NULL) abort(); - + uint8_t *memory = (uint8_t *) pm_arena_alloc(parser->arena, length, 1); memcpy(memory, source, length); - name = pm_parser_constant_id_owned(parser, (uint8_t *) memory, length); + name = pm_parser_constant_id_owned(parser, memory, length); } // Add this name to the list of constants if it is valid, not duplicated, @@ -22267,11 +22265,9 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si const uint8_t *source = pm_string_source(local); size_t length = pm_string_length(local); - void *allocated = xmalloc(length); - if (allocated == NULL) continue; - + uint8_t *allocated = (uint8_t *) pm_arena_alloc(&parser->metadata_arena, length, 1); memcpy(allocated, source, length); - pm_parser_local_add_owned(parser, (uint8_t *) allocated, length); + pm_parser_local_add_owned(parser, allocated, length); } } } From 7d7870e88c7828bd2ba61541f719450967ed923a Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:20:39 +0100 Subject: [PATCH 142/289] Sync changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f384df570..5f9d3b5a4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - Fixed location of opening tokens when invalid syntax is parsed. - Fix RBI for parsing options. +## [1.8.1] - 2026-03-16 (Ruby 4.0.2 maintenance release) + +### Changed + +- Fix `not` binding power in endless methods. +- Correctly handle `and?` and similar on Ruby 4.0. +- Fix error message for block/lambda with `...` argument. +- Fix `in` handling. + ## [1.8.0] - 2026-01-12 ### Added @@ -746,6 +755,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a [unreleased]: https://github.com/ruby/prism/compare/v1.9.0...HEAD [1.9.0]: https://github.com/ruby/prism/compare/v1.8.0...v1.9.0 +[1.8.1]: https://github.com/ruby/prism/compare/v1.8.0...v1.8.1 [1.8.0]: https://github.com/ruby/prism/compare/v1.7.0...v1.8.0 [1.7.0]: https://github.com/ruby/prism/compare/v1.6.0...v1.7.0 [1.6.0]: https://github.com/ruby/prism/compare/v1.5.2...v1.6.0 From 1cabef7946746d9468891c8827d10754bbeee281 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 18 Mar 2026 08:40:25 +0100 Subject: [PATCH 143/289] Fix ASAN reading off end of strpbrk cache https://github.com/ruby/ruby/commit/968b999fe25f77ea556b5e962c4781e38a7e6863 Co-Authored-By: Kevin Newton --- include/prism/parser.h | 17 ++++++++++++----- src/prism.c | 11 +++++++---- src/util/pm_strpbrk.c | 5 +++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index b68d56b564..8187d8685a 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -107,6 +107,13 @@ typedef struct { * that the lexer is now in the PM_LEX_STRING mode, and will return tokens that * are found as part of a string. */ +/** + * The size of the breakpoints and strpbrk cache charset buffers. All + * breakpoint arrays and the strpbrk cache charset must share this size so + * that memcmp can safely compare the full buffer without overreading. + */ +#define PM_STRPBRK_CACHE_SIZE 16 + typedef struct pm_lex_mode { /** The type of this lex mode. */ enum { @@ -169,7 +176,7 @@ typedef struct pm_lex_mode { * This is the character set that should be used to delimit the * tokens within the list. */ - uint8_t breakpoints[11]; + uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE]; } list; struct { @@ -191,7 +198,7 @@ typedef struct pm_lex_mode { * This is the character set that should be used to delimit the * tokens within the regular expression. */ - uint8_t breakpoints[7]; + uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE]; } regexp; struct { @@ -224,7 +231,7 @@ typedef struct pm_lex_mode { * This is the character set that should be used to delimit the * tokens within the string. */ - uint8_t breakpoints[7]; + uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE]; } string; struct { @@ -970,8 +977,8 @@ struct pm_parser { * (which is the common case during string/regex/list lexing). */ struct { - /** The cached charset (null-terminated, max 11 chars + NUL). */ - uint8_t charset[12]; + /** The cached charset (null-terminated, NUL-padded). */ + uint8_t charset[PM_STRPBRK_CACHE_SIZE]; /** Nibble-based low lookup table for SIMD matching. */ uint8_t low_lut[16]; diff --git a/src/prism.c b/src/prism.c index 783e624947..d0bd2e1973 100644 --- a/src/prism.c +++ b/src/prism.c @@ -149,7 +149,8 @@ lex_mode_push_list(pm_parser_t *parser, bool interpolation, uint8_t delimiter) { // These are the places where we need to split up the content of the list. // We'll use strpbrk to find the first of these characters. uint8_t *breakpoints = lex_mode.as.list.breakpoints; - memcpy(breakpoints, "\\ \t\f\r\v\n\0\0\0", sizeof(lex_mode.as.list.breakpoints)); + memset(breakpoints, 0, PM_STRPBRK_CACHE_SIZE); + memcpy(breakpoints, "\\ \t\f\r\v\n", sizeof("\\ \t\f\r\v\n") - 1); size_t index = 7; // Now we'll add the terminator to the list of breakpoints. If the @@ -201,7 +202,8 @@ lex_mode_push_regexp(pm_parser_t *parser, uint8_t incrementor, uint8_t terminato // regular expression. We'll use strpbrk to find the first of these // characters. uint8_t *breakpoints = lex_mode.as.regexp.breakpoints; - memcpy(breakpoints, "\r\n\\#\0\0", sizeof(lex_mode.as.regexp.breakpoints)); + memset(breakpoints, 0, PM_STRPBRK_CACHE_SIZE); + memcpy(breakpoints, "\r\n\\#", sizeof("\r\n\\#") - 1); size_t index = 4; // First we'll add the terminator. @@ -237,7 +239,8 @@ lex_mode_push_string(pm_parser_t *parser, bool interpolation, bool label_allowed // These are the places where we need to split up the content of the // string. We'll use strpbrk to find the first of these characters. uint8_t *breakpoints = lex_mode.as.string.breakpoints; - memcpy(breakpoints, "\r\n\\\0\0\0", sizeof(lex_mode.as.string.breakpoints)); + memset(breakpoints, 0, PM_STRPBRK_CACHE_SIZE); + memcpy(breakpoints, "\r\n\\", sizeof("\r\n\\") - 1); size_t index = 3; // Now add in the terminator. If the terminator is not already a NULL byte, @@ -12052,7 +12055,7 @@ parser_lex(pm_parser_t *parser) { // Otherwise we'll be parsing string content. These are the places // where we need to split up the content of the heredoc. We'll use // strpbrk to find the first of these characters. - uint8_t breakpoints[] = "\r\n\\#"; + uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE] = "\r\n\\#"; pm_heredoc_quote_t quote = heredoc_lex_mode->quote; if (quote == PM_HEREDOC_QUOTE_SINGLE) { diff --git a/src/util/pm_strpbrk.c b/src/util/pm_strpbrk.c index 496739c9f8..fdd2ab4567 100644 --- a/src/util/pm_strpbrk.c +++ b/src/util/pm_strpbrk.c @@ -59,8 +59,9 @@ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, uint32_t start, uint32_t l */ static inline void pm_strpbrk_cache_update(pm_parser_t *parser, const uint8_t *charset) { - // The cache key is the full 12-byte charset buffer. Since it is always - // NUL-padded, a fixed-size comparison covers both content and length. + // The cache key is the full charset buffer (PM_STRPBRK_CACHE_SIZE bytes). + // Since it is always NUL-padded, a fixed-size comparison covers both + // content and length. if (memcmp(parser->strpbrk_cache.charset, charset, sizeof(parser->strpbrk_cache.charset)) == 0) return; memset(parser->strpbrk_cache.low_lut, 0, sizeof(parser->strpbrk_cache.low_lut)); From 898241c76c4aee13fca0800b9c2b017533521531 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 18 Mar 2026 08:42:15 +0100 Subject: [PATCH 144/289] Do not use GCC-specific syntax for lookup tables https://github.com/ruby/ruby/commit/5026acfb6433f531a5cd24e904857a8d54b4473c Co-Authored-By: Kevin Newton --- src/prism.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/prism.c b/src/prism.c index d0bd2e1973..7b6482b090 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1809,14 +1809,16 @@ scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { // contains the OR of bits for all high nibbles that have an // identifier character at that low nibble position. A byte is an // identifier character iff (low_lut[lo] & high_lut[hi]) != 0. - const uint8x16_t low_lut = (uint8x16_t) { + static const uint8_t low_lut_data[16] = { 0x15, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x0A, 0x0A, 0x0A, 0x0A, 0x0E }; - const uint8x16_t high_lut = (uint8x16_t) { + static const uint8_t high_lut_data[16] = { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const uint8x16_t low_lut = vld1q_u8(low_lut_data); + const uint8x16_t high_lut = vld1q_u8(high_lut_data); const uint8x16_t mask_0f = vdupq_n_u8(0x0F); while (cursor + 16 <= end) { From ec2cf2e26160a2419838320f1de859265ecd4ae3 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 18 Mar 2026 08:51:15 +0100 Subject: [PATCH 145/289] Fix infinite loop in parser_lex_magic_comment https://github.com/ruby/ruby/commit/ec3162cafc601cdb18af0032a23f3798d4551dea Co-Authored-By: Kevin Newton --- src/prism.c | 2 +- test/prism/magic_comment_test.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/prism.c b/src/prism.c index 7b6482b090..dc7cbef2d4 100644 --- a/src/prism.c +++ b/src/prism.c @@ -7567,7 +7567,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { cursor = start; while (cursor < end) { if (indicator) { - cursor += pm_strspn_whitespace(cursor, end - cursor); + while (cursor < end && (pm_char_is_magic_comment_key_delimiter(*cursor) || pm_char_is_whitespace(*cursor))) cursor++; } const uint8_t *key_start = cursor; diff --git a/test/prism/magic_comment_test.rb b/test/prism/magic_comment_test.rb index ccfe5a5d0a..7985bae568 100644 --- a/test/prism/magic_comment_test.rb +++ b/test/prism/magic_comment_test.rb @@ -69,6 +69,10 @@ def test_emacs_multiple assert_magic_encoding(Encoding::US_ASCII, "# -*- foo: bar; encoding: ascii -*-") end + def test_emacs_missing_delimiter + assert_magic_encoding(Encoding::US_ASCII, '# -*- \1; encoding: ascii -*-') + end + def test_coding_whitespace assert_magic_encoding(Encoding::ASCII_8BIT, "# coding \t \r \v : \t \v \r ascii-8bit") end From eab6f33ba502ba36a18de010f253e8f3e1b1a065 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 18 Mar 2026 08:57:21 +0100 Subject: [PATCH 146/289] Fix C coverage by moving stuff slightly around --- include/prism/parser.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index 8187d8685a..66df791244 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -100,13 +100,6 @@ typedef struct { pm_heredoc_indent_t indent; } pm_heredoc_lex_mode_t; -/** - * When lexing Ruby source, the lexer has a small amount of state to tell which - * kind of token it is currently lexing. For example, when we find the start of - * a string, the first token that we return is a TOKEN_STRING_BEGIN token. After - * that the lexer is now in the PM_LEX_STRING mode, and will return tokens that - * are found as part of a string. - */ /** * The size of the breakpoints and strpbrk cache charset buffers. All * breakpoint arrays and the strpbrk cache charset must share this size so @@ -114,6 +107,13 @@ typedef struct { */ #define PM_STRPBRK_CACHE_SIZE 16 +/** + * When lexing Ruby source, the lexer has a small amount of state to tell which + * kind of token it is currently lexing. For example, when we find the start of + * a string, the first token that we return is a TOKEN_STRING_BEGIN token. After + * that the lexer is now in the PM_LEX_STRING mode, and will return tokens that + * are found as part of a string. + */ typedef struct pm_lex_mode { /** The type of this lex mode. */ enum { From 7c1927efd6dbc77d6421375d9b656af190d48982 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 18 Mar 2026 18:42:43 +0900 Subject: [PATCH 147/289] Fix assignments (#4012) Useless comparisons, probably typos. --- ext/prism/extension.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 147434c975..c248b0c123 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -208,10 +208,10 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { if (!pm_options_version_set(options, ruby_version, 3)) { // Prism doesn't know this specific version. Is it lower? if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { - options->version == PM_OPTIONS_VERSION_CRUBY_3_3; + options->version = PM_OPTIONS_VERSION_CRUBY_3_3; } else { // Must be higher. - options->version == PM_OPTIONS_VERSION_LATEST; + options->version = PM_OPTIONS_VERSION_LATEST; } } } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { From 429672ea58cd53e152f29fecf79ad1437cb4edae Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:04:33 -0400 Subject: [PATCH 148/289] Move buffer out of utils --- include/prism.h | 2 +- include/prism/{util/pm_buffer.h => buffer.h} | 8 +------- include/prism/node.h | 2 +- include/prism/prettyprint.h | 2 +- include/prism/util/pm_integer.h | 2 +- lib/prism/ffi.rb | 2 +- prism.gemspec | 4 ++-- src/{util/pm_buffer.c => buffer.c} | 8 +++++++- src/regexp.c | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) rename include/prism/{util/pm_buffer.h => buffer.h} (98%) rename src/{util/pm_buffer.c => buffer.c} (98%) diff --git a/include/prism.h b/include/prism.h index 76733b8aaf..7b81dd6513 100644 --- a/include/prism.h +++ b/include/prism.h @@ -12,13 +12,13 @@ extern "C" { #include "prism/defines.h" #include "prism/util/pm_arena.h" -#include "prism/util/pm_buffer.h" #include "prism/util/pm_char.h" #include "prism/util/pm_integer.h" #include "prism/util/pm_memchr.h" #include "prism/util/pm_strncasecmp.h" #include "prism/util/pm_strpbrk.h" #include "prism/ast.h" +#include "prism/buffer.h" #include "prism/diagnostic.h" #include "prism/node.h" #include "prism/options.h" diff --git a/include/prism/util/pm_buffer.h b/include/prism/buffer.h similarity index 98% rename from include/prism/util/pm_buffer.h rename to include/prism/buffer.h index cb80f8b3ce..e6e21b6895 100644 --- a/include/prism/util/pm_buffer.h +++ b/include/prism/buffer.h @@ -1,5 +1,5 @@ /** - * @file pm_buffer.h + * @file buffer.h * * A wrapper around a contiguous block of allocated memory. */ @@ -9,12 +9,6 @@ #include "prism/defines.h" #include "prism/util/pm_char.h" -#include -#include -#include -#include -#include - /** * A pm_buffer_t is a simple memory buffer that stores data in a contiguous * block of memory. diff --git a/include/prism/node.h b/include/prism/node.h index f02f8ba892..a4ead730bc 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -7,8 +7,8 @@ #define PRISM_NODE_H #include "prism/defines.h" +#include "prism/buffer.h" #include "prism/parser.h" -#include "prism/util/pm_buffer.h" /** * Loop through each node in the node list, writing each node to the given diff --git a/include/prism/prettyprint.h b/include/prism/prettyprint.h index 5a52b2b6b8..55da182f53 100644 --- a/include/prism/prettyprint.h +++ b/include/prism/prettyprint.h @@ -17,8 +17,8 @@ void pm_prettyprint(void); #include #include "prism/ast.h" +#include "prism/buffer.h" #include "prism/parser.h" -#include "prism/util/pm_buffer.h" /** * Pretty-prints the AST represented by the given node to the given buffer. diff --git a/include/prism/util/pm_integer.h b/include/prism/util/pm_integer.h index 304665e620..b50446deff 100644 --- a/include/prism/util/pm_integer.h +++ b/include/prism/util/pm_integer.h @@ -7,7 +7,7 @@ #define PRISM_NUMBER_H #include "prism/defines.h" -#include "prism/util/pm_buffer.h" +#include "prism/buffer.h" #include #include diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 1bcbfc367c..72187fa490 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -106,7 +106,7 @@ def self.load_exported_functions_from(header, *functions, callbacks) ) load_exported_functions_from( - "prism/util/pm_buffer.h", + "prism/buffer.h", "pm_buffer_sizeof", "pm_buffer_init", "pm_buffer_value", diff --git a/prism.gemspec b/prism.gemspec index d8b86c6fba..2ad20a692d 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -47,6 +47,7 @@ Gem::Specification.new do |spec| "ext/prism/extension.h", "include/prism.h", "include/prism/ast.h", + "include/prism/buffer.h", "include/prism/debug_allocator.h", "include/prism/defines.h", "include/prism/diagnostic.h", @@ -59,7 +60,6 @@ Gem::Specification.new do |spec| "include/prism/regexp.h", "include/prism/static_literals.h", "include/prism/util/pm_arena.h", - "include/prism/util/pm_buffer.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_integer.h", @@ -158,6 +158,7 @@ Gem::Specification.new do |spec| "sig/generated/prism/parse_result/comments.rbs", "sig/generated/prism/parse_result/errors.rbs", "sig/generated/prism/parse_result/newlines.rbs", + "src/buffer.c", "src/diagnostic.c", "src/encoding.c", "src/node.c", @@ -169,7 +170,6 @@ Gem::Specification.new do |spec| "src/static_literals.c", "src/token_type.c", "src/util/pm_arena.c", - "src/util/pm_buffer.c", "src/util/pm_char.c", "src/util/pm_constant_pool.c", "src/util/pm_integer.c", diff --git a/src/util/pm_buffer.c b/src/buffer.c similarity index 98% rename from src/util/pm_buffer.c rename to src/buffer.c index 9e392427c6..5d1f2a9118 100644 --- a/src/util/pm_buffer.c +++ b/src/buffer.c @@ -1,4 +1,10 @@ -#include "prism/util/pm_buffer.h" +#include "prism/buffer.h" + +#include +#include +#include +#include +#include /** * Return the size of the pm_buffer_t struct. diff --git a/src/regexp.c b/src/regexp.c index df8bb69b21..cc626290b7 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,6 +1,6 @@ +#include "prism/buffer.h" #include "prism/regexp.h" #include "prism/diagnostic.h" -#include "prism/util/pm_buffer.h" #include "prism/util/pm_strncasecmp.h" /** The maximum depth of nested groups allowed in a regular expression. */ From bda0f889b57e50ef5a90c7c29d00ae2812960d51 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:08:16 -0400 Subject: [PATCH 149/289] Split up buffer headers between internal and external --- include/prism.h | 2 +- include/prism/buffer.h | 157 ----------------------------- include/prism/internal/buffer.h | 169 ++++++++++++++++++++++++++++++++ include/prism/node.h | 2 +- include/prism/util/pm_integer.h | 2 +- prism.gemspec | 1 + src/buffer.c | 2 +- src/regexp.c | 2 +- 8 files changed, 175 insertions(+), 162 deletions(-) create mode 100644 include/prism/internal/buffer.h diff --git a/include/prism.h b/include/prism.h index 7b81dd6513..73cc5bfc03 100644 --- a/include/prism.h +++ b/include/prism.h @@ -17,8 +17,8 @@ extern "C" { #include "prism/util/pm_memchr.h" #include "prism/util/pm_strncasecmp.h" #include "prism/util/pm_strpbrk.h" +#include "prism/internal/buffer.h" #include "prism/ast.h" -#include "prism/buffer.h" #include "prism/diagnostic.h" #include "prism/node.h" #include "prism/options.h" diff --git a/include/prism/buffer.h b/include/prism/buffer.h index e6e21b6895..335dae6811 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -31,15 +31,6 @@ typedef struct { */ PRISM_EXPORTED_FUNCTION size_t pm_buffer_sizeof(void); -/** - * Initialize a pm_buffer_t with the given capacity. - * - * @param buffer The buffer to initialize. - * @param capacity The capacity of the buffer. - * @returns True if the buffer was initialized successfully, false otherwise. - */ -bool pm_buffer_init_capacity(pm_buffer_t *buffer, size_t capacity); - /** * Initialize a pm_buffer_t with its default values. * @@ -70,154 +61,6 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer); */ PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer); -/** - * Append the given amount of space as zeroes to the buffer. - * - * @param buffer The buffer to append to. - * @param length The amount of space to append and zero. - */ -void pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length); - -/** - * Append a formatted string to the buffer. - * - * @param buffer The buffer to append to. - * @param format The format string to append. - * @param ... The arguments to the format string. - */ -void pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...) PRISM_ATTRIBUTE_FORMAT(2, 3); - -/** - * Append a string to the buffer. - * - * @param buffer The buffer to append to. - * @param value The string to append. - * @param length The length of the string to append. - */ -void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length); - -/** - * Append a list of bytes to the buffer. - * - * @param buffer The buffer to append to. - * @param value The bytes to append. - * @param length The length of the bytes to append. - */ -void pm_buffer_append_bytes(pm_buffer_t *buffer, const uint8_t *value, size_t length); - -/** - * Append a single byte to the buffer. - * - * @param buffer The buffer to append to. - * @param value The byte to append. - */ -void pm_buffer_append_byte(pm_buffer_t *buffer, uint8_t value); - -/** - * Append a 32-bit unsigned integer to the buffer as a variable-length integer. - * - * @param buffer The buffer to append to. - * @param value The integer to append. - */ -void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value); - -/** - * Append a 32-bit signed integer to the buffer as a variable-length integer. - * - * @param buffer The buffer to append to. - * @param value The integer to append. - */ -void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value); - -/** - * Append a double to the buffer. - * - * @param buffer The buffer to append to. - * @param value The double to append. - */ -void pm_buffer_append_double(pm_buffer_t *buffer, double value); - -/** - * Append a unicode codepoint to the buffer. - * - * @param buffer The buffer to append to. - * @param value The character to append. - * @returns True if the codepoint was valid and appended successfully, false - * otherwise. - */ -bool pm_buffer_append_unicode_codepoint(pm_buffer_t *buffer, uint32_t value); - -/** - * The different types of escaping that can be performed by the buffer when - * appending a slice of Ruby source code. - */ -typedef enum { - PM_BUFFER_ESCAPING_RUBY, - PM_BUFFER_ESCAPING_JSON -} pm_buffer_escaping_t; - -/** - * Append a slice of source code to the buffer. - * - * @param buffer The buffer to append to. - * @param source The source code to append. - * @param length The length of the source code to append. - * @param escaping The type of escaping to perform. - */ -void pm_buffer_append_source(pm_buffer_t *buffer, const uint8_t *source, size_t length, pm_buffer_escaping_t escaping); - -/** - * Prepend the given string to the buffer. - * - * @param buffer The buffer to prepend to. - * @param value The string to prepend. - * @param length The length of the string to prepend. - */ -void pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t length); - -/** - * Concatenate one buffer onto another. - * - * @param destination The buffer to concatenate onto. - * @param source The buffer to concatenate. - */ -void pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source); - -/** - * Clear the buffer by reducing its size to 0. This does not free the allocated - * memory, but it does allow the buffer to be reused. - * - * @param buffer The buffer to clear. - */ -void pm_buffer_clear(pm_buffer_t *buffer); - -/** - * Strip the whitespace from the end of the buffer. - * - * @param buffer The buffer to strip. - */ -void pm_buffer_rstrip(pm_buffer_t *buffer); - -/** - * Checks if the buffer includes the given value. - * - * @param buffer The buffer to check. - * @param value The value to check for. - * @returns The index of the first occurrence of the value in the buffer, or - * SIZE_MAX if the value is not found. - */ -size_t pm_buffer_index(const pm_buffer_t *buffer, char value); - -/** - * Insert the given string into the buffer at the given index. - * - * @param buffer The buffer to insert into. - * @param index The index to insert at. - * @param value The string to insert. - * @param length The length of the string to insert. - */ -void pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t length); - /** * Free the memory associated with the buffer. * diff --git a/include/prism/internal/buffer.h b/include/prism/internal/buffer.h new file mode 100644 index 0000000000..b76cf54ca8 --- /dev/null +++ b/include/prism/internal/buffer.h @@ -0,0 +1,169 @@ +/** + * @file internal/buffer.h + * + * A wrapper around a contiguous block of allocated memory. + */ +#ifndef PRISM_INTERNAL_BUFFER_H +#define PRISM_INTERNAL_BUFFER_H + +#include "prism/defines.h" +#include "prism/buffer.h" + +/** + * Initialize a pm_buffer_t with the given capacity. + * + * @param buffer The buffer to initialize. + * @param capacity The capacity of the buffer. + * @returns True if the buffer was initialized successfully, false otherwise. + */ +bool pm_buffer_init_capacity(pm_buffer_t *buffer, size_t capacity); + +/** + * Append the given amount of space as zeroes to the buffer. + * + * @param buffer The buffer to append to. + * @param length The amount of space to append and zero. + */ +void pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length); + +/** + * Append a formatted string to the buffer. + * + * @param buffer The buffer to append to. + * @param format The format string to append. + * @param ... The arguments to the format string. + */ +void pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...) PRISM_ATTRIBUTE_FORMAT(2, 3); + +/** + * Append a string to the buffer. + * + * @param buffer The buffer to append to. + * @param value The string to append. + * @param length The length of the string to append. + */ +void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length); + +/** + * Append a list of bytes to the buffer. + * + * @param buffer The buffer to append to. + * @param value The bytes to append. + * @param length The length of the bytes to append. + */ +void pm_buffer_append_bytes(pm_buffer_t *buffer, const uint8_t *value, size_t length); + +/** + * Append a single byte to the buffer. + * + * @param buffer The buffer to append to. + * @param value The byte to append. + */ +void pm_buffer_append_byte(pm_buffer_t *buffer, uint8_t value); + +/** + * Append a 32-bit unsigned integer to the buffer as a variable-length integer. + * + * @param buffer The buffer to append to. + * @param value The integer to append. + */ +void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value); + +/** + * Append a 32-bit signed integer to the buffer as a variable-length integer. + * + * @param buffer The buffer to append to. + * @param value The integer to append. + */ +void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value); + +/** + * Append a double to the buffer. + * + * @param buffer The buffer to append to. + * @param value The double to append. + */ +void pm_buffer_append_double(pm_buffer_t *buffer, double value); + +/** + * Append a unicode codepoint to the buffer. + * + * @param buffer The buffer to append to. + * @param value The character to append. + * @returns True if the codepoint was valid and appended successfully, false + * otherwise. + */ +bool pm_buffer_append_unicode_codepoint(pm_buffer_t *buffer, uint32_t value); + +/** + * The different types of escaping that can be performed by the buffer when + * appending a slice of Ruby source code. + */ +typedef enum { + PM_BUFFER_ESCAPING_RUBY, + PM_BUFFER_ESCAPING_JSON +} pm_buffer_escaping_t; + +/** + * Append a slice of source code to the buffer. + * + * @param buffer The buffer to append to. + * @param source The source code to append. + * @param length The length of the source code to append. + * @param escaping The type of escaping to perform. + */ +void pm_buffer_append_source(pm_buffer_t *buffer, const uint8_t *source, size_t length, pm_buffer_escaping_t escaping); + +/** + * Prepend the given string to the buffer. + * + * @param buffer The buffer to prepend to. + * @param value The string to prepend. + * @param length The length of the string to prepend. + */ +void pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t length); + +/** + * Concatenate one buffer onto another. + * + * @param destination The buffer to concatenate onto. + * @param source The buffer to concatenate. + */ +void pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source); + +/** + * Clear the buffer by reducing its size to 0. This does not free the allocated + * memory, but it does allow the buffer to be reused. + * + * @param buffer The buffer to clear. + */ +void pm_buffer_clear(pm_buffer_t *buffer); + +/** + * Strip the whitespace from the end of the buffer. + * + * @param buffer The buffer to strip. + */ +void pm_buffer_rstrip(pm_buffer_t *buffer); + +/** + * Checks if the buffer includes the given value. + * + * @param buffer The buffer to check. + * @param value The value to check for. + * @returns The index of the first occurrence of the value in the buffer, or + * SIZE_MAX if the value is not found. + */ +size_t pm_buffer_index(const pm_buffer_t *buffer, char value); + +/** + * Insert the given string into the buffer at the given index. + * + * @param buffer The buffer to insert into. + * @param index The index to insert at. + * @param value The string to insert. + * @param length The length of the string to insert. + */ +void pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t length); + +#endif diff --git a/include/prism/node.h b/include/prism/node.h index a4ead730bc..560936dc08 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -7,7 +7,7 @@ #define PRISM_NODE_H #include "prism/defines.h" -#include "prism/buffer.h" +#include "prism/internal/buffer.h" #include "prism/parser.h" /** diff --git a/include/prism/util/pm_integer.h b/include/prism/util/pm_integer.h index b50446deff..673db20419 100644 --- a/include/prism/util/pm_integer.h +++ b/include/prism/util/pm_integer.h @@ -7,7 +7,7 @@ #define PRISM_NUMBER_H #include "prism/defines.h" -#include "prism/buffer.h" +#include "prism/internal/buffer.h" #include #include diff --git a/prism.gemspec b/prism.gemspec index 2ad20a692d..7d6ea6ea08 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -59,6 +59,7 @@ Gem::Specification.new do |spec| "include/prism/prettyprint.h", "include/prism/regexp.h", "include/prism/static_literals.h", + "include/prism/internal/buffer.h", "include/prism/util/pm_arena.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", diff --git a/src/buffer.c b/src/buffer.c index 5d1f2a9118..111e02ea06 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,4 +1,4 @@ -#include "prism/buffer.h" +#include "prism/internal/buffer.h" #include #include diff --git a/src/regexp.c b/src/regexp.c index cc626290b7..5fc5b983d4 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,4 +1,4 @@ -#include "prism/buffer.h" +#include "prism/internal/buffer.h" #include "prism/regexp.h" #include "prism/diagnostic.h" #include "prism/util/pm_strncasecmp.h" From 1039dff6ca5747b67e7ef97bbf22a5f08d9efac3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:21:05 -0400 Subject: [PATCH 150/289] Only include what is necessary for buffer --- include/prism/allocator.h | 85 +++++++++++++++++++++++++++++++++ include/prism/buffer.h | 6 ++- include/prism/defines.h | 39 ++------------- include/prism/exported.h | 26 ++++++++++ include/prism/format.h | 28 +++++++++++ include/prism/internal/buffer.h | 4 +- src/buffer.c | 7 +-- 7 files changed, 154 insertions(+), 41 deletions(-) create mode 100644 include/prism/allocator.h create mode 100644 include/prism/exported.h create mode 100644 include/prism/format.h diff --git a/include/prism/allocator.h b/include/prism/allocator.h new file mode 100644 index 0000000000..6b1c26e84e --- /dev/null +++ b/include/prism/allocator.h @@ -0,0 +1,85 @@ +/** + * @file allocator.h + * + * Macro definitions for defining the main and a custom allocator for Prism. + */ +#ifndef PRISM_ALLOCATOR_H +#define PRISM_ALLOCATOR_H + +/** + * If you build Prism with a custom allocator, configure it with + * "-D PRISM_XALLOCATOR" to use your own allocator that defines xmalloc, + * xrealloc, xcalloc, and xfree. + * + * For example, your `prism_xallocator.h` file could look like this: + * + * ``` + * #ifndef PRISM_XALLOCATOR_H + * #define PRISM_XALLOCATOR_H + * #define xmalloc my_malloc + * #define xrealloc my_realloc + * #define xcalloc my_calloc + * #define xfree my_free + * #define xrealloc_sized my_realloc_sized // (optional) + * #define xfree_sized my_free_sized // (optional) + * #endif + * ``` + */ +#ifdef PRISM_XALLOCATOR + #include "prism_xallocator.h" +#else + #ifndef xmalloc + /** + * The malloc function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. + */ + #define xmalloc malloc + #endif + + #ifndef xrealloc + /** + * The realloc function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. + */ + #define xrealloc realloc + #endif + + #ifndef xcalloc + /** + * The calloc function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. + */ + #define xcalloc calloc + #endif + + #ifndef xfree + /** + * The free function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. + */ + #define xfree free + #endif +#endif + +#ifndef xfree_sized + /** + * The free_sized function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. If not defined, defaults to calling xfree. + */ + #define xfree_sized(p, s) xfree(((void)(s), (p))) +#endif + +#ifndef xrealloc_sized + /** + * The xrealloc_sized function that should be used. This can be overridden + * with the PRISM_XALLOCATOR define. If not defined, defaults to calling + * xrealloc. + */ + #define xrealloc_sized(p, ns, os) xrealloc((p), ((void)(os), (ns))) +#endif + +#ifdef PRISM_BUILD_DEBUG + #include "prism/debug_allocator.h" +#endif + +#endif diff --git a/include/prism/buffer.h b/include/prism/buffer.h index 335dae6811..ffc07461fc 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -6,8 +6,10 @@ #ifndef PRISM_BUFFER_H #define PRISM_BUFFER_H -#include "prism/defines.h" -#include "prism/util/pm_char.h" +#include "prism/exported.h" + +#include +#include /** * A pm_buffer_t is a simple memory buffer that stores data in a contiguous diff --git a/include/prism/defines.h b/include/prism/defines.h index d666582b17..c533ba4ffe 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -9,6 +9,10 @@ #ifndef PRISM_DEFINES_H #define PRISM_DEFINES_H +#include "prism/allocator.h" +#include "prism/exported.h" +#include "prism/format.h" + #include #include #include @@ -37,41 +41,6 @@ #define PRISM_DEPTH_MAXIMUM 10000 #endif -/** - * By default, we compile with -fvisibility=hidden. When this is enabled, we - * need to mark certain functions as being publically-visible. This macro does - * that in a compiler-agnostic way. - */ -#ifndef PRISM_EXPORTED_FUNCTION -# ifdef PRISM_EXPORT_SYMBOLS -# ifdef _WIN32 -# define PRISM_EXPORTED_FUNCTION __declspec(dllexport) extern -# else -# define PRISM_EXPORTED_FUNCTION __attribute__((__visibility__("default"))) extern -# endif -# else -# define PRISM_EXPORTED_FUNCTION -# endif -#endif - -/** - * Certain compilers support specifying that a function accepts variadic - * parameters that look like printf format strings to provide a better developer - * experience when someone is using the function. This macro does that in a - * compiler-agnostic way. - */ -#if defined(__GNUC__) -# if defined(__MINGW_PRINTF_FORMAT) -# define PRISM_ATTRIBUTE_FORMAT(string_index, argument_index) __attribute__((format(__MINGW_PRINTF_FORMAT, string_index, argument_index))) -# else -# define PRISM_ATTRIBUTE_FORMAT(string_index, argument_index) __attribute__((format(printf, string_index, argument_index))) -# endif -#elif defined(__clang__) -# define PRISM_ATTRIBUTE_FORMAT(string_index, argument_index) __attribute__((__format__(__printf__, string_index, argument_index))) -#else -# define PRISM_ATTRIBUTE_FORMAT(string_index, argument_index) -#endif - /** * GCC will warn if you specify a function or parameter that is unused at * runtime. This macro allows you to mark a function or parameter as unused in a diff --git a/include/prism/exported.h b/include/prism/exported.h new file mode 100644 index 0000000000..74476b0efb --- /dev/null +++ b/include/prism/exported.h @@ -0,0 +1,26 @@ +/** + * @file exported.h + * + * Macro definitions for make functions publically visible. + */ +#ifndef PRISM_EXPORTED_H +#define PRISM_EXPORTED_H + +/** + * By default, we compile with -fvisibility=hidden. When this is enabled, we + * need to mark certain functions as being publically-visible. This macro does + * that in a compiler-agnostic way. + */ +#ifndef PRISM_EXPORTED_FUNCTION +# ifdef PRISM_EXPORT_SYMBOLS +# ifdef _WIN32 +# define PRISM_EXPORTED_FUNCTION __declspec(dllexport) extern +# else +# define PRISM_EXPORTED_FUNCTION __attribute__((__visibility__("default"))) extern +# endif +# else +# define PRISM_EXPORTED_FUNCTION +# endif +#endif + +#endif diff --git a/include/prism/format.h b/include/prism/format.h new file mode 100644 index 0000000000..973fc3fe4e --- /dev/null +++ b/include/prism/format.h @@ -0,0 +1,28 @@ +/** + * @file format.h + * + * Macro definition for specifying that a function accepts variadic parameters + * that look like printf format strings. + */ +#ifndef PRISM_FORMAT_H +#define PRISM_FORMAT_H + +/** + * Certain compilers support specifying that a function accepts variadic + * parameters that look like printf format strings to provide a better developer + * experience when someone is using the function. This macro does that in a + * compiler-agnostic way. + */ +#if defined(__GNUC__) +# if defined(__MINGW_PRINTF_FORMAT) +# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) __attribute__((format(__MINGW_PRINTF_FORMAT, string_index_, argument_index_))) +# else +# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) __attribute__((format(printf, string_index_, argument_index_))) +# endif +#elif defined(__clang__) +# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) __attribute__((__format__(__printf__, string_index_, argument_index_))) +#else +# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) +#endif + +#endif diff --git a/include/prism/internal/buffer.h b/include/prism/internal/buffer.h index b76cf54ca8..a5c46ed530 100644 --- a/include/prism/internal/buffer.h +++ b/include/prism/internal/buffer.h @@ -6,8 +6,10 @@ #ifndef PRISM_INTERNAL_BUFFER_H #define PRISM_INTERNAL_BUFFER_H -#include "prism/defines.h" #include "prism/buffer.h" +#include "prism/format.h" + +#include /** * Initialize a pm_buffer_t with the given capacity. diff --git a/src/buffer.c b/src/buffer.c index 111e02ea06..dbbb05c7ef 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,8 +1,9 @@ #include "prism/internal/buffer.h" +#include "prism/allocator.h" +#include "prism/util/pm_char.h" -#include -#include -#include +#include +#include #include #include From e4df04157a1e28bfd02d2c5f492ba6d0907c7ce9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:26:07 -0400 Subject: [PATCH 151/289] Move strncasecmp out of utils and make internal only --- include/prism.h | 2 +- include/prism/encoding.h | 2 +- .../{util/pm_strncasecmp.h => internal/strncasecmp.h} | 9 +++------ prism.gemspec | 4 ++-- src/regexp.c | 2 +- src/{util/pm_strncasecmp.c => strncasecmp.c} | 5 ++--- 6 files changed, 10 insertions(+), 14 deletions(-) rename include/prism/{util/pm_strncasecmp.h => internal/strncasecmp.h} (87%) rename src/{util/pm_strncasecmp.c => strncasecmp.c} (94%) diff --git a/include/prism.h b/include/prism.h index 73cc5bfc03..50451f45ed 100644 --- a/include/prism.h +++ b/include/prism.h @@ -15,9 +15,9 @@ extern "C" { #include "prism/util/pm_char.h" #include "prism/util/pm_integer.h" #include "prism/util/pm_memchr.h" -#include "prism/util/pm_strncasecmp.h" #include "prism/util/pm_strpbrk.h" #include "prism/internal/buffer.h" +#include "prism/internal/strncasecmp.h" #include "prism/ast.h" #include "prism/diagnostic.h" #include "prism/node.h" diff --git a/include/prism/encoding.h b/include/prism/encoding.h index 5f7724821f..99c2397bdc 100644 --- a/include/prism/encoding.h +++ b/include/prism/encoding.h @@ -7,7 +7,7 @@ #define PRISM_ENCODING_H #include "prism/defines.h" -#include "prism/util/pm_strncasecmp.h" +#include "prism/internal/strncasecmp.h" #include #include diff --git a/include/prism/util/pm_strncasecmp.h b/include/prism/internal/strncasecmp.h similarity index 87% rename from include/prism/util/pm_strncasecmp.h rename to include/prism/internal/strncasecmp.h index 5cb88cb5eb..c6cabe9c23 100644 --- a/include/prism/util/pm_strncasecmp.h +++ b/include/prism/internal/strncasecmp.h @@ -1,14 +1,11 @@ /** - * @file pm_strncasecmp.h + * @file internal/strncasecmp.h * * A custom strncasecmp implementation. */ -#ifndef PRISM_STRNCASECMP_H -#define PRISM_STRNCASECMP_H +#ifndef PRISM_INTERNAL_STRNCASECMP_H +#define PRISM_INTERNAL_STRNCASECMP_H -#include "prism/defines.h" - -#include #include #include diff --git a/prism.gemspec b/prism.gemspec index 7d6ea6ea08..10a0a6bffe 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -60,6 +60,7 @@ Gem::Specification.new do |spec| "include/prism/regexp.h", "include/prism/static_literals.h", "include/prism/internal/buffer.h", + "include/prism/internal/strncasecmp.h", "include/prism/util/pm_arena.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", @@ -67,7 +68,6 @@ Gem::Specification.new do |spec| "include/prism/util/pm_list.h", "include/prism/util/pm_memchr.h", "include/prism/util/pm_line_offset_list.h", - "include/prism/util/pm_strncasecmp.h", "include/prism/util/pm_string.h", "include/prism/util/pm_strpbrk.h", "include/prism/version.h", @@ -169,6 +169,7 @@ Gem::Specification.new do |spec| "src/regexp.c", "src/serialize.c", "src/static_literals.c", + "src/strncasecmp.c", "src/token_type.c", "src/util/pm_arena.c", "src/util/pm_char.c", @@ -178,7 +179,6 @@ Gem::Specification.new do |spec| "src/util/pm_memchr.c", "src/util/pm_line_offset_list.c", "src/util/pm_string.c", - "src/util/pm_strncasecmp.c", "src/util/pm_strpbrk.c" ] diff --git a/src/regexp.c b/src/regexp.c index 5fc5b983d4..115b3ed7e1 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,7 +1,7 @@ #include "prism/internal/buffer.h" +#include "prism/internal/strncasecmp.h" #include "prism/regexp.h" #include "prism/diagnostic.h" -#include "prism/util/pm_strncasecmp.h" /** The maximum depth of nested groups allowed in a regular expression. */ #define PM_REGEXP_PARSE_DEPTH_MAX 4096 diff --git a/src/util/pm_strncasecmp.c b/src/strncasecmp.c similarity index 94% rename from src/util/pm_strncasecmp.c rename to src/strncasecmp.c index 3f58421554..c4e2214ee1 100644 --- a/src/util/pm_strncasecmp.c +++ b/src/strncasecmp.c @@ -1,11 +1,10 @@ -#include "prism/util/pm_strncasecmp.h" +#include "prism/internal/strncasecmp.h" /** * A locale-insensitive version of `tolower(3)` */ static inline int -pm_tolower(int c) -{ +pm_tolower(int c) { if ('A' <= c && c <= 'Z') { return c | 0x20; } From cdf8bed9ba36b8d1bea693e8155961a4f8a3118e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:30:12 -0400 Subject: [PATCH 152/289] Make memchr implementation internal --- include/prism.h | 2 +- .../prism/{util/pm_memchr.h => internal/memchr.h} | 7 +++---- include/prism/regexp.h | 2 +- prism.gemspec | 4 ++-- src/{util/pm_memchr.c => memchr.c} | 12 +++++++----- 5 files changed, 14 insertions(+), 13 deletions(-) rename include/prism/{util/pm_memchr.h => internal/memchr.h} (89%) rename src/{util/pm_memchr.c => memchr.c} (85%) diff --git a/include/prism.h b/include/prism.h index 50451f45ed..9d18c8ccb2 100644 --- a/include/prism.h +++ b/include/prism.h @@ -14,9 +14,9 @@ extern "C" { #include "prism/util/pm_arena.h" #include "prism/util/pm_char.h" #include "prism/util/pm_integer.h" -#include "prism/util/pm_memchr.h" #include "prism/util/pm_strpbrk.h" #include "prism/internal/buffer.h" +#include "prism/internal/memchr.h" #include "prism/internal/strncasecmp.h" #include "prism/ast.h" #include "prism/diagnostic.h" diff --git a/include/prism/util/pm_memchr.h b/include/prism/internal/memchr.h similarity index 89% rename from include/prism/util/pm_memchr.h rename to include/prism/internal/memchr.h index e0671eaed3..7277971681 100644 --- a/include/prism/util/pm_memchr.h +++ b/include/prism/internal/memchr.h @@ -1,12 +1,11 @@ /** - * @file pm_memchr.h + * @file internal/memchr.h * * A custom memchr implementation. */ -#ifndef PRISM_MEMCHR_H -#define PRISM_MEMCHR_H +#ifndef PRISM_INTERNAL_MEMCHR_H +#define PRISM_INTERNAL_MEMCHR_H -#include "prism/defines.h" #include "prism/encoding.h" #include diff --git a/include/prism/regexp.h b/include/prism/regexp.h index b3e739b457..60a84b9838 100644 --- a/include/prism/regexp.h +++ b/include/prism/regexp.h @@ -9,7 +9,7 @@ #include "prism/defines.h" #include "prism/parser.h" #include "prism/encoding.h" -#include "prism/util/pm_memchr.h" +#include "prism/internal/memchr.h" #include "prism/util/pm_string.h" #include diff --git a/prism.gemspec b/prism.gemspec index 10a0a6bffe..43bb030c98 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -60,13 +60,13 @@ Gem::Specification.new do |spec| "include/prism/regexp.h", "include/prism/static_literals.h", "include/prism/internal/buffer.h", + "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", "include/prism/util/pm_arena.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_integer.h", "include/prism/util/pm_list.h", - "include/prism/util/pm_memchr.h", "include/prism/util/pm_line_offset_list.h", "include/prism/util/pm_string.h", "include/prism/util/pm_strpbrk.h", @@ -162,6 +162,7 @@ Gem::Specification.new do |spec| "src/buffer.c", "src/diagnostic.c", "src/encoding.c", + "src/memchr.c", "src/node.c", "src/options.c", "src/prettyprint.c", @@ -176,7 +177,6 @@ Gem::Specification.new do |spec| "src/util/pm_constant_pool.c", "src/util/pm_integer.c", "src/util/pm_list.c", - "src/util/pm_memchr.c", "src/util/pm_line_offset_list.c", "src/util/pm_string.c", "src/util/pm_strpbrk.c" diff --git a/src/util/pm_memchr.c b/src/memchr.c similarity index 85% rename from src/util/pm_memchr.c rename to src/memchr.c index 7ea20ace6d..6266d4ca7a 100644 --- a/src/util/pm_memchr.c +++ b/src/memchr.c @@ -1,6 +1,10 @@ -#include "prism/util/pm_memchr.h" +#include "prism/internal/memchr.h" -#define PRISM_MEMCHR_TRAILING_BYTE_MINIMUM 0x40 +#include +#include +#include + +#define TRAILING_BYTE_MINIMUM 0x40 /** * We need to roll our own memchr to handle cases where the encoding changes and @@ -9,7 +13,7 @@ */ void * pm_memchr(const void *memory, int character, size_t number, bool encoding_changed, const pm_encoding_t *encoding) { - if (encoding_changed && encoding->multibyte && character >= PRISM_MEMCHR_TRAILING_BYTE_MINIMUM) { + if (encoding_changed && encoding->multibyte && character >= TRAILING_BYTE_MINIMUM) { const uint8_t *source = (const uint8_t *) memory; size_t index = 0; @@ -31,5 +35,3 @@ pm_memchr(const void *memory, int character, size_t number, bool encoding_change return memchr(memory, character, number); } } - -#undef PRISM_MEMCHR_TRAILING_BYTE_MINIMUM From 0862b48f0c1fb81fa353f8e4b06996cb9fbbe764 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:32:29 -0400 Subject: [PATCH 153/289] Remove unnecessary PRISM_EXPORTED_FUNCTION from source files --- src/options.c | 34 ++++++++++++++++----------------- src/prism.c | 26 ++++++++++++------------- src/regexp.c | 2 +- src/util/pm_integer.c | 4 ++-- src/util/pm_list.c | 6 +++--- src/util/pm_string.c | 12 ++++++------ templates/src/node.c.erb | 8 ++++---- templates/src/prettyprint.c.erb | 2 +- templates/src/serialize.c.erb | 4 ++-- templates/src/token_type.c.erb | 2 +- 10 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/options.c b/src/options.c index 961d52330f..ecd88a8021 100644 --- a/src/options.c +++ b/src/options.c @@ -3,7 +3,7 @@ /** * Set the shebang callback option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data) { options->shebang_callback = shebang_callback; options->shebang_callback_data = shebang_callback_data; @@ -12,7 +12,7 @@ pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callba /** * Set the filepath option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_filepath_set(pm_options_t *options, const char *filepath) { pm_string_constant_init(&options->filepath, filepath, strlen(filepath)); } @@ -20,7 +20,7 @@ pm_options_filepath_set(pm_options_t *options, const char *filepath) { /** * Set the encoding option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_encoding_set(pm_options_t *options, const char *encoding) { pm_string_constant_init(&options->encoding, encoding, strlen(encoding)); } @@ -28,7 +28,7 @@ pm_options_encoding_set(pm_options_t *options, const char *encoding) { /** * Set the encoding_locked option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) { options->encoding_locked = encoding_locked; } @@ -36,7 +36,7 @@ pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) { /** * Set the line option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_line_set(pm_options_t *options, int32_t line) { options->line = line; } @@ -44,7 +44,7 @@ pm_options_line_set(pm_options_t *options, int32_t line) { /** * Set the frozen string literal option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal) { options->frozen_string_literal = frozen_string_literal ? PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED : PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED; } @@ -52,7 +52,7 @@ pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_l /** * Sets the command line option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_command_line_set(pm_options_t *options, uint8_t command_line) { options->command_line = command_line; } @@ -70,7 +70,7 @@ is_number(const char *string, size_t length) { * string. If the string contains an invalid option, this returns false. * Otherwise, it returns true. */ -PRISM_EXPORTED_FUNCTION bool +bool pm_options_version_set(pm_options_t *options, const char *version, size_t length) { if (version == NULL) { options->version = PM_OPTIONS_VERSION_LATEST; @@ -136,7 +136,7 @@ pm_options_version_set(pm_options_t *options, const char *version, size_t length /** * Set the main script option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_main_script_set(pm_options_t *options, bool main_script) { options->main_script = main_script; } @@ -144,7 +144,7 @@ pm_options_main_script_set(pm_options_t *options, bool main_script) { /** * Set the partial script option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_partial_script_set(pm_options_t *options, bool partial_script) { options->partial_script = partial_script; } @@ -152,7 +152,7 @@ pm_options_partial_script_set(pm_options_t *options, bool partial_script) { /** * Set the freeze option on the given options struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_freeze_set(pm_options_t *options, bool freeze) { options->freeze = freeze; } @@ -168,7 +168,7 @@ pm_options_freeze_set(pm_options_t *options, bool freeze) { /** * Allocate and zero out the scopes array on the given options struct. */ -PRISM_EXPORTED_FUNCTION bool +bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count) { options->scopes_count = scopes_count; options->scopes = xcalloc(scopes_count, sizeof(pm_options_scope_t)); @@ -178,7 +178,7 @@ pm_options_scopes_init(pm_options_t *options, size_t scopes_count) { /** * Return a pointer to the scope at the given index within the given options. */ -PRISM_EXPORTED_FUNCTION const pm_options_scope_t * +const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index) { return &options->scopes[index]; } @@ -187,7 +187,7 @@ pm_options_scope_get(const pm_options_t *options, size_t index) { * Create a new options scope struct. This will hold a set of locals that are in * scope surrounding the code that is being parsed. */ -PRISM_EXPORTED_FUNCTION bool +bool pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) { scope->locals_count = locals_count; scope->locals = xcalloc(locals_count, sizeof(pm_string_t)); @@ -198,7 +198,7 @@ pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) { /** * Return a pointer to the local at the given index within the given scope. */ -PRISM_EXPORTED_FUNCTION const pm_string_t * +const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { return &scope->locals[index]; } @@ -206,7 +206,7 @@ pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { /** * Set the forwarding option on the given scope struct. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) { scope->forwarding = forwarding; } @@ -214,7 +214,7 @@ pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) { /** * Free the internal memory associated with the options. */ -PRISM_EXPORTED_FUNCTION void +void pm_options_free(pm_options_t *options) { pm_string_free(&options->filepath); pm_string_free(&options->encoding); diff --git a/src/prism.c b/src/prism.c index dc7cbef2d4..8dfaf085eb 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22140,7 +22140,7 @@ pm_parser_init_shebang(pm_parser_t *parser, const pm_options_t *options, const c /** * Initialize a parser with the given start and end pointers. */ -PRISM_EXPORTED_FUNCTION void +void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options) { assert(arena != NULL); assert(source != NULL); @@ -22401,7 +22401,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si * Register a callback that will be called whenever prism changes the encoding * it is using to parse based on the magic comment. */ -PRISM_EXPORTED_FUNCTION void +void pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_changed_callback_t callback) { parser->encoding_changed_callback = callback; } @@ -22409,7 +22409,7 @@ pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_ch /** * Free any memory associated with the given parser. */ -PRISM_EXPORTED_FUNCTION void +void pm_parser_free(pm_parser_t *parser) { pm_string_free(&parser->filepath); pm_arena_free(&parser->metadata_arena); @@ -22592,7 +22592,7 @@ pm_parse_continuable(pm_parser_t *parser) { /** * Parse the Ruby source associated with the given parser and return the tree. */ -PRISM_EXPORTED_FUNCTION pm_node_t * +pm_node_t * pm_parse(pm_parser_t *parser) { pm_node_t *node = parse_program(parser); pm_parse_continuable(parser); @@ -22659,7 +22659,7 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t * Prism is designed around having the entire source in memory at once, but you * can stream stdin in to Ruby so we need to support a streaming API. */ -PRISM_EXPORTED_FUNCTION pm_node_t * +pm_node_t * pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { pm_buffer_init(buffer); @@ -22683,7 +22683,7 @@ pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, voi /** * Parse the source and return true if it parses without errors or warnings. */ -PRISM_EXPORTED_FUNCTION bool +bool pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { pm_options_t options = { 0 }; pm_options_read(&options, data); @@ -22724,7 +22724,7 @@ pm_serialize_header(pm_buffer_t *buffer) { /** * Serialize the AST represented by the given node to the given buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_serialize_header(buffer); pm_serialize_content(parser, node, buffer); @@ -22735,7 +22735,7 @@ pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { * Parse and serialize the AST represented by the given source to the given * buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) { pm_options_t options = { 0 }; pm_options_read(&options, data); @@ -22759,7 +22759,7 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons * Parse and serialize the AST represented by the source that is read out of the * given stream into to the given buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) { pm_arena_t arena = { 0 }; pm_parser_t parser; @@ -22781,7 +22781,7 @@ pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fge /** * Parse and serialize the comments in the given source to the given buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) { pm_options_t options = { 0 }; pm_options_read(&options, data); @@ -22887,7 +22887,7 @@ pm_slice_type(const uint8_t *source, size_t length, const char *encoding_name) { /** * Check that the slice is a valid local variable name. */ -PRISM_EXPORTED_FUNCTION pm_string_query_t +pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) { switch (pm_slice_type(source, length, encoding_name)) { case PM_SLICE_TYPE_ERROR: @@ -22907,7 +22907,7 @@ pm_string_query_local(const uint8_t *source, size_t length, const char *encoding /** * Check that the slice is a valid constant name. */ -PRISM_EXPORTED_FUNCTION pm_string_query_t +pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) { switch (pm_slice_type(source, length, encoding_name)) { case PM_SLICE_TYPE_ERROR: @@ -22927,7 +22927,7 @@ pm_string_query_constant(const uint8_t *source, size_t length, const char *encod /** * Check that the slice is a valid method name. */ -PRISM_EXPORTED_FUNCTION pm_string_query_t +pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) { #define B(p) ((p) ? PM_STRING_QUERY_TRUE : PM_STRING_QUERY_FALSE) #define C1(c) (*source == c) diff --git a/src/regexp.c b/src/regexp.c index 115b3ed7e1..33a546dde8 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1595,7 +1595,7 @@ pm_regexp_validate_encoding(pm_regexp_parser_t *parser, bool ascii_only, pm_node * extraction walks the unescaped content since escape sequences in group names * (e.g., line continuations) have already been processed by the lexer. */ -PRISM_EXPORTED_FUNCTION pm_node_flags_t +pm_node_flags_t pm_regexp_parse(pm_parser_t *parser, pm_regular_expression_node_t *node, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data) { const uint8_t *source = parser->start + node->content_loc.start; size_t size = node->content_loc.length; diff --git a/src/util/pm_integer.c b/src/util/pm_integer.c index 2b77a4b5d2..8e3404d03b 100644 --- a/src/util/pm_integer.c +++ b/src/util/pm_integer.c @@ -604,7 +604,7 @@ void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator) { /** * Convert an integer to a decimal string. */ -PRISM_EXPORTED_FUNCTION void +void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { if (integer->negative) { pm_buffer_append_byte(buffer, '-'); @@ -663,7 +663,7 @@ pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { * Free the internal memory of an integer. This memory will only be allocated if * the integer exceeds the size of a single uint32_t. */ -PRISM_EXPORTED_FUNCTION void +void pm_integer_free(pm_integer_t *integer) { if (integer->values) { xfree(integer->values); diff --git a/src/util/pm_list.c b/src/util/pm_list.c index 940baffb64..48486d6cf9 100644 --- a/src/util/pm_list.c +++ b/src/util/pm_list.c @@ -3,7 +3,7 @@ /** * Returns true if the given list is empty. */ -PRISM_EXPORTED_FUNCTION bool +bool pm_list_empty_p(pm_list_t *list) { return list->head == NULL; } @@ -11,7 +11,7 @@ pm_list_empty_p(pm_list_t *list) { /** * Returns the size of the list. */ -PRISM_EXPORTED_FUNCTION size_t +size_t pm_list_size(pm_list_t *list) { return list->size; } @@ -34,7 +34,7 @@ pm_list_append(pm_list_t *list, pm_list_node_t *node) { /** * Deallocate the internal state of the given list. */ -PRISM_EXPORTED_FUNCTION void +void pm_list_free(pm_list_t *list) { pm_list_node_t *node = list->head; pm_list_node_t *next; diff --git a/src/util/pm_string.c b/src/util/pm_string.c index 5ba8c78ec1..c2c85e1614 100644 --- a/src/util/pm_string.c +++ b/src/util/pm_string.c @@ -6,7 +6,7 @@ static const uint8_t empty_source[] = ""; * Returns the size of the pm_string_t struct. This is necessary to allocate the * correct amount of memory in the FFI backend. */ -PRISM_EXPORTED_FUNCTION size_t +size_t pm_string_sizeof(void) { return sizeof(pm_string_t); } @@ -117,7 +117,7 @@ pm_string_file_handle_close(pm_string_file_handle_t *handle) { * `MapViewOfFile`, on POSIX systems that have access to `mmap` we'll use * `mmap`, and on other POSIX systems we'll use `read`. */ -PRISM_EXPORTED_FUNCTION pm_string_init_result_t +pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath) { #ifdef _WIN32 // Open the file for reading. @@ -207,7 +207,7 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { * contents and size into the given `pm_string_t`. The given `pm_string_t` * should be freed using `pm_string_free` when it is no longer used. */ -PRISM_EXPORTED_FUNCTION pm_string_init_result_t +pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath) { #ifdef _WIN32 // Open the file for reading. @@ -348,7 +348,7 @@ pm_string_compare(const pm_string_t *left, const pm_string_t *right) { /** * Returns the length associated with the string. */ -PRISM_EXPORTED_FUNCTION size_t +size_t pm_string_length(const pm_string_t *string) { return string->length; } @@ -356,7 +356,7 @@ pm_string_length(const pm_string_t *string) { /** * Returns the start pointer associated with the string. */ -PRISM_EXPORTED_FUNCTION const uint8_t * +const uint8_t * pm_string_source(const pm_string_t *string) { return string->source; } @@ -364,7 +364,7 @@ pm_string_source(const pm_string_t *string) { /** * Free the associated memory of the given string. */ -PRISM_EXPORTED_FUNCTION void +void pm_string_free(pm_string_t *string) { void *memory = (void *) string->source; diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 93ea275a54..f7a2089d30 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -74,7 +74,7 @@ pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *oth /** * Returns a string representation of the given node type. */ -PRISM_EXPORTED_FUNCTION const char * +const char * pm_node_type_to_str(pm_node_type_t node_type) { switch (node_type) { @@ -94,7 +94,7 @@ pm_node_type_to_str(pm_node_type_t node_type) * pointer and is passed to the visitor callback for consumers to use as they * see fit. */ -PRISM_EXPORTED_FUNCTION void +void pm_visit_node(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) { if (visitor(node, data)) pm_visit_child_nodes(node, visitor, data); } @@ -104,7 +104,7 @@ pm_visit_node(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void * default behavior for walking the tree that is called from pm_visit_node if * the callback returns true. */ -PRISM_EXPORTED_FUNCTION void +void pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) { switch (PM_NODE_TYPE(node)) { <%- nodes.each do |node| -%> @@ -161,7 +161,7 @@ pm_dump_json_location(pm_buffer_t *buffer, const pm_location_t *location) { /** * Dump JSON to the given buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) { switch (PM_NODE_TYPE(node)) { <%- nodes.each do |node| -%> diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 44423ca42b..05386336ab 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -156,7 +156,7 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm /** * Pretty-prints the AST represented by the given node to the given buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node) { pm_buffer_t prefix_buffer = { 0 }; prettyprint_node(output_buffer, parser, node, &prefix_buffer); diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 78e4f34893..f6da95f031 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -310,7 +310,7 @@ serialize_token(void *data, pm_parser_t *parser, pm_token_t *token) { /** * Lex the given source and serialize to the given buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) { pm_options_t options = { 0 }; pm_options_read(&options, data); @@ -341,7 +341,7 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const * Parse and serialize both the AST and the tokens represented by the given * source to the given buffer. */ -PRISM_EXPORTED_FUNCTION void +void pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) { pm_options_t options = { 0 }; pm_options_read(&options, data); diff --git a/templates/src/token_type.c.erb b/templates/src/token_type.c.erb index 94e41ec4ba..c08a0e7921 100644 --- a/templates/src/token_type.c.erb +++ b/templates/src/token_type.c.erb @@ -5,7 +5,7 @@ /** * Returns a string representation of the given token type. */ -PRISM_EXPORTED_FUNCTION const char * +const char * pm_token_type_name(pm_token_type_t token_type) { switch (token_type) { <%- tokens.each do |token| -%> From cdc9b97f4d420146a3c78ad0eeac3e9a7fcdda48 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:37:48 -0400 Subject: [PATCH 154/289] Move integer out of utils --- include/prism.h | 2 +- include/prism/{util/pm_integer.h => integer.h} | 6 +++--- prism.gemspec | 4 ++-- src/{util/pm_integer.c => integer.c} | 2 +- templates/include/prism/ast.h.erb | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) rename include/prism/{util/pm_integer.h => integer.h} (98%) rename src/{util/pm_integer.c => integer.c} (99%) diff --git a/include/prism.h b/include/prism.h index 9d18c8ccb2..f9e410bab7 100644 --- a/include/prism.h +++ b/include/prism.h @@ -13,13 +13,13 @@ extern "C" { #include "prism/defines.h" #include "prism/util/pm_arena.h" #include "prism/util/pm_char.h" -#include "prism/util/pm_integer.h" #include "prism/util/pm_strpbrk.h" #include "prism/internal/buffer.h" #include "prism/internal/memchr.h" #include "prism/internal/strncasecmp.h" #include "prism/ast.h" #include "prism/diagnostic.h" +#include "prism/integer.h" #include "prism/node.h" #include "prism/options.h" #include "prism/parser.h" diff --git a/include/prism/util/pm_integer.h b/include/prism/integer.h similarity index 98% rename from include/prism/util/pm_integer.h rename to include/prism/integer.h index 673db20419..dddf29ce10 100644 --- a/include/prism/util/pm_integer.h +++ b/include/prism/integer.h @@ -1,10 +1,10 @@ /** - * @file pm_integer.h + * @file integer.h * * This module provides functions for working with arbitrary-sized integers. */ -#ifndef PRISM_NUMBER_H -#define PRISM_NUMBER_H +#ifndef PRISM_INTEGER_H +#define PRISM_INTEGER_H #include "prism/defines.h" #include "prism/internal/buffer.h" diff --git a/prism.gemspec b/prism.gemspec index 43bb030c98..ac0811a180 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -52,6 +52,7 @@ Gem::Specification.new do |spec| "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", + "include/prism/integer.h", "include/prism/node.h", "include/prism/node_new.h", "include/prism/options.h", @@ -65,7 +66,6 @@ Gem::Specification.new do |spec| "include/prism/util/pm_arena.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", - "include/prism/util/pm_integer.h", "include/prism/util/pm_list.h", "include/prism/util/pm_line_offset_list.h", "include/prism/util/pm_string.h", @@ -162,6 +162,7 @@ Gem::Specification.new do |spec| "src/buffer.c", "src/diagnostic.c", "src/encoding.c", + "src/integer.c", "src/memchr.c", "src/node.c", "src/options.c", @@ -175,7 +176,6 @@ Gem::Specification.new do |spec| "src/util/pm_arena.c", "src/util/pm_char.c", "src/util/pm_constant_pool.c", - "src/util/pm_integer.c", "src/util/pm_list.c", "src/util/pm_line_offset_list.c", "src/util/pm_string.c", diff --git a/src/util/pm_integer.c b/src/integer.c similarity index 99% rename from src/util/pm_integer.c rename to src/integer.c index 8e3404d03b..fd27188109 100644 --- a/src/util/pm_integer.c +++ b/src/integer.c @@ -1,4 +1,4 @@ -#include "prism/util/pm_integer.h" +#include "prism/integer.h" /** * Pull out the length and values from the integer, regardless of the form in diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 0612341772..2026d3a6c6 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -10,8 +10,8 @@ #include "prism/defines.h" #include "prism/util/pm_constant_pool.h" -#include "prism/util/pm_integer.h" #include "prism/util/pm_string.h" +#include "prism/integer.h" #include #include From 16fd2bf08adb3ce85bbba09e005db0ab93221d03 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 09:58:18 -0400 Subject: [PATCH 155/289] Split up integer between public and private headers --- include/prism.h | 1 - include/prism/integer.h | 91 +------------------------------- include/prism/internal/integer.h | 87 ++++++++++++++++++++++++++++++ include/prism/static_literals.h | 1 + prism.gemspec | 4 ++ src/integer.c | 33 +++++++----- src/prism.c | 2 + src/static_literals.c | 2 + templates/src/node.c.erb | 1 + templates/src/prettyprint.c.erb | 2 + 10 files changed, 121 insertions(+), 103 deletions(-) create mode 100644 include/prism/internal/integer.h diff --git a/include/prism.h b/include/prism.h index f9e410bab7..cb4439e77a 100644 --- a/include/prism.h +++ b/include/prism.h @@ -19,7 +19,6 @@ extern "C" { #include "prism/internal/strncasecmp.h" #include "prism/ast.h" #include "prism/diagnostic.h" -#include "prism/integer.h" #include "prism/node.h" #include "prism/options.h" #include "prism/parser.h" diff --git a/include/prism/integer.h b/include/prism/integer.h index dddf29ce10..9285986885 100644 --- a/include/prism/integer.h +++ b/include/prism/integer.h @@ -6,13 +6,9 @@ #ifndef PRISM_INTEGER_H #define PRISM_INTEGER_H -#include "prism/defines.h" -#include "prism/internal/buffer.h" - -#include #include +#include #include -#include /** * A structure represents an arbitrary-sized integer. @@ -42,89 +38,4 @@ typedef struct { bool negative; } pm_integer_t; -/** - * An enum controlling the base of an integer. It is expected that the base is - * already known before parsing the integer, even though it could be derived - * from the string itself. - */ -typedef enum { - /** The default decimal base, with no prefix. Leading 0s will be ignored. */ - PM_INTEGER_BASE_DEFAULT, - - /** The binary base, indicated by a 0b or 0B prefix. */ - PM_INTEGER_BASE_BINARY, - - /** The octal base, indicated by a 0, 0o, or 0O prefix. */ - PM_INTEGER_BASE_OCTAL, - - /** The decimal base, indicated by a 0d, 0D, or empty prefix. */ - PM_INTEGER_BASE_DECIMAL, - - /** The hexadecimal base, indicated by a 0x or 0X prefix. */ - PM_INTEGER_BASE_HEXADECIMAL, - - /** - * An unknown base, in which case pm_integer_parse will derive it based on - * the content of the string. This is less efficient and does more - * comparisons, so if callers know the base ahead of time, they should use - * that instead. - */ - PM_INTEGER_BASE_UNKNOWN -} pm_integer_base_t; - -/** - * Parse an integer from a string. This assumes that the format of the integer - * has already been validated, as internal validation checks are not performed - * here. - * - * @param integer The integer to parse into. - * @param base The base of the integer. - * @param start The start of the string. - * @param end The end of the string. - */ -void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end); - -/** - * Compare two integers. This function returns -1 if the left integer is less - * than the right integer, 0 if they are equal, and 1 if the left integer is - * greater than the right integer. - * - * @param left The left integer to compare. - * @param right The right integer to compare. - * @return The result of the comparison. - */ -int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right); - -/** - * Reduce a ratio of integers to its simplest form. - * - * If either the numerator or denominator do not fit into a 32-bit integer, then - * this function is a no-op. In the future, we may consider reducing even the - * larger numbers, but for now we're going to keep it simple. - * - * @param numerator The numerator of the ratio. - * @param denominator The denominator of the ratio. - */ -void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator); - -/** - * Convert an integer to a decimal string. - * - * @param buffer The buffer to append the string to. - * @param integer The integer to convert to a string. - * - * \public \memberof pm_integer_t - */ -PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer); - -/** - * Free the internal memory of an integer. This memory will only be allocated if - * the integer exceeds the size of a single node in the linked list. - * - * @param integer The integer to free. - * - * \public \memberof pm_integer_t - */ -PRISM_EXPORTED_FUNCTION void pm_integer_free(pm_integer_t *integer); - #endif diff --git a/include/prism/internal/integer.h b/include/prism/internal/integer.h new file mode 100644 index 0000000000..8bf21ae69d --- /dev/null +++ b/include/prism/internal/integer.h @@ -0,0 +1,87 @@ +/** + * @file internal/integer.h + * + * This module provides functions for working with arbitrary-sized integers. + */ +#ifndef PRISM_INTERNAL_INTEGER_H +#define PRISM_INTERNAL_INTEGER_H + +#include "prism/buffer.h" +#include "prism/integer.h" + +#include + +/** + * An enum controlling the base of an integer. It is expected that the base is + * already known before parsing the integer, even though it could be derived + * from the string itself. + */ +typedef enum { + /** The default decimal base, with no prefix. Leading 0s will be ignored. */ + PM_INTEGER_BASE_DEFAULT, + + /** The binary base, indicated by a 0b or 0B prefix. */ + PM_INTEGER_BASE_BINARY, + + /** The octal base, indicated by a 0, 0o, or 0O prefix. */ + PM_INTEGER_BASE_OCTAL, + + /** The decimal base, indicated by a 0d, 0D, or empty prefix. */ + PM_INTEGER_BASE_DECIMAL, + + /** The hexadecimal base, indicated by a 0x or 0X prefix. */ + PM_INTEGER_BASE_HEXADECIMAL, + + /** + * An unknown base, in which case pm_integer_parse will derive it based on + * the content of the string. This is less efficient and does more + * comparisons, so if callers know the base ahead of time, they should use + * that instead. + */ + PM_INTEGER_BASE_UNKNOWN +} pm_integer_base_t; + +/** + * Parse an integer from a string. This assumes that the format of the integer + * has already been validated, as internal validation checks are not performed + * here. + * + * @param integer The integer to parse into. + * @param base The base of the integer. + * @param start The start of the string. + * @param end The end of the string. + */ +void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end); + +/** + * Compare two integers. This function returns -1 if the left integer is less + * than the right integer, 0 if they are equal, and 1 if the left integer is + * greater than the right integer. + * + * @param left The left integer to compare. + * @param right The right integer to compare. + * @return The result of the comparison. + */ +int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right); + +/** + * Reduce a ratio of integers to its simplest form. + * + * If either the numerator or denominator do not fit into a 32-bit integer, then + * this function is a no-op. In the future, we may consider reducing even the + * larger numbers, but for now we're going to keep it simple. + * + * @param numerator The numerator of the ratio. + * @param denominator The denominator of the ratio. + */ +void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator); + +/** + * Convert an integer to a decimal string. + * + * @param buffer The buffer to append the string to. + * @param integer The integer to convert to a string. + */ +void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer); + +#endif diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index 6d73e5d04f..0e8ddbcfc6 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -8,6 +8,7 @@ #include "prism/defines.h" #include "prism/ast.h" +#include "prism/buffer.h" #include "prism/util/pm_line_offset_list.h" #include diff --git a/prism.gemspec b/prism.gemspec index ac0811a180..f3923eeda4 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -46,12 +46,15 @@ Gem::Specification.new do |spec| "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", + "include/prism/allocator.h", "include/prism/ast.h", "include/prism/buffer.h", "include/prism/debug_allocator.h", "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", + "include/prism/exported.h", + "include/prism/format.h", "include/prism/integer.h", "include/prism/node.h", "include/prism/node_new.h", @@ -61,6 +64,7 @@ Gem::Specification.new do |spec| "include/prism/regexp.h", "include/prism/static_literals.h", "include/prism/internal/buffer.h", + "include/prism/internal/integer.h", "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", "include/prism/util/pm_arena.h", diff --git a/src/integer.c b/src/integer.c index fd27188109..35dd5e0eea 100644 --- a/src/integer.c +++ b/src/integer.c @@ -1,4 +1,24 @@ -#include "prism/integer.h" +#include "prism/allocator.h" +#include "prism/internal/buffer.h" +#include "prism/internal/integer.h" + +#include +#include +#include +#include +#include +#include + +/** + * Free the internal memory of an integer. This memory will only be allocated if + * the integer exceeds the size of a single uint32_t. + */ +static void +pm_integer_free(pm_integer_t *integer) { + if (integer->values) { + xfree(integer->values); + } +} /** * Pull out the length and values from the integer, regardless of the form in @@ -658,14 +678,3 @@ pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { xfree_sized(digits, sizeof(char) * digits_length); pm_integer_free(&converted); } - -/** - * Free the internal memory of an integer. This memory will only be allocated if - * the integer exceeds the size of a single uint32_t. - */ -void -pm_integer_free(pm_integer_t *integer) { - if (integer->values) { - xfree(integer->values); - } -} diff --git a/src/prism.c b/src/prism.c index 8dfaf085eb..fdf3bacb42 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,3 +1,5 @@ +#include "prism/internal/integer.h" + #include "prism.h" #include "prism/node_new.h" diff --git a/src/static_literals.c b/src/static_literals.c index f3a5650d31..e6d66cd691 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -1,3 +1,5 @@ +#include "prism/internal/buffer.h" +#include "prism/internal/integer.h" #include "prism/static_literals.h" /** diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index f7a2089d30..30e2d6fc58 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -1,4 +1,5 @@ #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" +#include "prism/internal/integer.h" #include "prism/node.h" /** diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 05386336ab..aefb092df2 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -1,4 +1,6 @@ <%# encoding: ASCII -%> +#include "prism/internal/buffer.h" +#include "prism/internal/integer.h" #include "prism/prettyprint.h" // We optionally support pretty printing nodes. For systems that don't want or From 5966ab67f3057f9ffd3c4133845a154d9ceed7a7 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 10:04:11 -0400 Subject: [PATCH 156/289] Move line offset list out of util --- .../prism/{util/pm_line_offset_list.h => line_offset_list.h} | 2 +- include/prism/parser.h | 2 +- include/prism/static_literals.h | 2 +- include/prism/util/pm_char.h | 2 +- prism.gemspec | 4 ++-- src/{util/pm_line_offset_list.c => line_offset_list.c} | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) rename include/prism/{util/pm_line_offset_list.h => line_offset_list.h} (99%) rename src/{util/pm_line_offset_list.c => line_offset_list.c} (98%) diff --git a/include/prism/util/pm_line_offset_list.h b/include/prism/line_offset_list.h similarity index 99% rename from include/prism/util/pm_line_offset_list.h rename to include/prism/line_offset_list.h index 62a52da4ec..53e697ed86 100644 --- a/include/prism/util/pm_line_offset_list.h +++ b/include/prism/line_offset_list.h @@ -1,5 +1,5 @@ /** - * @file pm_line_offset_list.h + * @file line_offset_list.h * * A list of byte offsets of newlines in a string. * diff --git a/include/prism/parser.h b/include/prism/parser.h index 66df791244..1d8f28fff6 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -9,12 +9,12 @@ #include "prism/defines.h" #include "prism/ast.h" #include "prism/encoding.h" +#include "prism/line_offset_list.h" #include "prism/options.h" #include "prism/static_literals.h" #include "prism/util/pm_arena.h" #include "prism/util/pm_constant_pool.h" #include "prism/util/pm_list.h" -#include "prism/util/pm_line_offset_list.h" #include "prism/util/pm_string.h" #include diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index 0e8ddbcfc6..cdb00e6a83 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -9,7 +9,7 @@ #include "prism/defines.h" #include "prism/ast.h" #include "prism/buffer.h" -#include "prism/util/pm_line_offset_list.h" +#include "prism/line_offset_list.h" #include #include diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index 516390b21c..0be57d5a52 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -7,7 +7,7 @@ #define PRISM_CHAR_H #include "prism/defines.h" -#include "prism/util/pm_line_offset_list.h" +#include "prism/line_offset_list.h" #include #include diff --git a/prism.gemspec b/prism.gemspec index f3923eeda4..302fe17aca 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -56,6 +56,7 @@ Gem::Specification.new do |spec| "include/prism/exported.h", "include/prism/format.h", "include/prism/integer.h", + "include/prism/line_offset_list.h", "include/prism/node.h", "include/prism/node_new.h", "include/prism/options.h", @@ -71,7 +72,6 @@ Gem::Specification.new do |spec| "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_list.h", - "include/prism/util/pm_line_offset_list.h", "include/prism/util/pm_string.h", "include/prism/util/pm_strpbrk.h", "include/prism/version.h", @@ -167,6 +167,7 @@ Gem::Specification.new do |spec| "src/diagnostic.c", "src/encoding.c", "src/integer.c", + "src/line_offset_list.c", "src/memchr.c", "src/node.c", "src/options.c", @@ -181,7 +182,6 @@ Gem::Specification.new do |spec| "src/util/pm_char.c", "src/util/pm_constant_pool.c", "src/util/pm_list.c", - "src/util/pm_line_offset_list.c", "src/util/pm_string.c", "src/util/pm_strpbrk.c" ] diff --git a/src/util/pm_line_offset_list.c b/src/line_offset_list.c similarity index 98% rename from src/util/pm_line_offset_list.c rename to src/line_offset_list.c index 0648901e29..8513fdb46e 100644 --- a/src/util/pm_line_offset_list.c +++ b/src/line_offset_list.c @@ -1,4 +1,4 @@ -#include "prism/util/pm_line_offset_list.h" +#include "prism/line_offset_list.h" /** * Initialize a new line offset list with the given capacity. From 58586902b19d358ee104cc76c753738beaa29bae Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 10:14:08 -0400 Subject: [PATCH 157/289] Split up line offset list into public and internal --- include/prism/align.h | 38 ++++++++++++ include/prism/defines.h | 45 +------------- include/prism/force_inline.h | 21 +++++++ include/prism/internal/line_offset_list.h | 73 +++++++++++++++++++++++ include/prism/line_offset_list.h | 59 +----------------- include/prism/util/pm_char.h | 1 + prism.gemspec | 3 + src/buffer.c | 1 + src/line_offset_list.c | 6 +- src/prism.c | 1 + src/util/pm_char.c | 1 + 11 files changed, 148 insertions(+), 101 deletions(-) create mode 100644 include/prism/align.h create mode 100644 include/prism/force_inline.h create mode 100644 include/prism/internal/line_offset_list.h diff --git a/include/prism/align.h b/include/prism/align.h new file mode 100644 index 0000000000..bb120d488e --- /dev/null +++ b/include/prism/align.h @@ -0,0 +1,38 @@ +/** + * @file align.h + * + * Alignment macros used throughout the prism library. + */ +#ifndef PRISM_ALIGN_H +#define PRISM_ALIGN_H + +/** + * Compiler-agnostic macros for specifying alignment of types and variables. + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L /* C11 or later */ + /** Specify alignment for a type or variable. */ + #define PRISM_ALIGNAS _Alignas + + /** Get the alignment requirement of a type. */ + #define PRISM_ALIGNOF _Alignof +#elif defined(__GNUC__) || defined(__clang__) + /** Specify alignment for a type or variable. */ + #define PRISM_ALIGNAS(size) __attribute__((aligned(size))) + + /** Get the alignment requirement of a type. */ + #define PRISM_ALIGNOF(type) __alignof__(type) +#elif defined(_MSC_VER) + /** Specify alignment for a type or variable. */ + #define PRISM_ALIGNAS(size) __declspec(align(size)) + + /** Get the alignment requirement of a type. */ + #define PRISM_ALIGNOF(type) __alignof(type) +#else + /** Void because this platform does not support specifying alignment. */ + #define PRISM_ALIGNAS(size) + + /** Fallback to sizeof as alignment requirement of a type. */ + #define PRISM_ALIGNOF(type) sizeof(type) +#endif + +#endif diff --git a/include/prism/defines.h b/include/prism/defines.h index c533ba4ffe..fcfc8b84a1 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -9,8 +9,10 @@ #ifndef PRISM_DEFINES_H #define PRISM_DEFINES_H +#include "prism/align.h" #include "prism/allocator.h" #include "prism/exported.h" +#include "prism/force_inline.h" #include "prism/format.h" #include @@ -60,18 +62,6 @@ # define inline __inline #endif -/** - * Force a function to be inlined at every call site. Use sparingly — only for - * small, hot functions where the compiler's heuristics fail to inline. - */ -#if defined(_MSC_VER) -# define PRISM_FORCE_INLINE __forceinline -#elif defined(__GNUC__) || defined(__clang__) -# define PRISM_FORCE_INLINE inline __attribute__((always_inline)) -#else -# define PRISM_FORCE_INLINE inline -#endif - /** * Old Visual Studio versions before 2015 do not implement sprintf, but instead * implement _snprintf. We standard that here. @@ -314,35 +304,4 @@ #define PM_FLEX_ARY_LEN 1 /* data[1] */ #endif -/** - * We need to align nodes in the AST to a pointer boundary so that it can be - * safely cast to different node types. Use PRISM_ALIGNAS/PRISM_ALIGNOF to - * specify alignment in a compiler-agnostic way. - */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L /* C11 or later */ - /** Specify alignment for a type or variable. */ - #define PRISM_ALIGNAS _Alignas - - /** Get the alignment requirement of a type. */ - #define PRISM_ALIGNOF _Alignof -#elif defined(__GNUC__) || defined(__clang__) - /** Specify alignment for a type or variable. */ - #define PRISM_ALIGNAS(size) __attribute__((aligned(size))) - - /** Get the alignment requirement of a type. */ - #define PRISM_ALIGNOF(type) __alignof__(type) -#elif defined(_MSC_VER) - /** Specify alignment for a type or variable. */ - #define PRISM_ALIGNAS(size) __declspec(align(size)) - - /** Get the alignment requirement of a type. */ - #define PRISM_ALIGNOF(type) __alignof(type) -#else - /** Void because this platform does not support specifying alignment. */ - #define PRISM_ALIGNAS(size) - - /** Fallback to sizeof as alignment requirement of a type. */ - #define PRISM_ALIGNOF(type) sizeof(type) -#endif - #endif diff --git a/include/prism/force_inline.h b/include/prism/force_inline.h new file mode 100644 index 0000000000..c205e5ddf6 --- /dev/null +++ b/include/prism/force_inline.h @@ -0,0 +1,21 @@ +/** + * @file force_inline.h + * + * Macro definitions for forcing a function to be inlined at every call site. + */ +#ifndef PRISM_FORCE_INLINE_H +#define PRISM_FORCE_INLINE_H + +/** + * Force a function to be inlined at every call site. Use sparingly — only for + * small, hot functions where the compiler's heuristics fail to inline. + */ +#if defined(_MSC_VER) +# define PRISM_FORCE_INLINE __forceinline +#elif defined(__GNUC__) || defined(__clang__) +# define PRISM_FORCE_INLINE inline __attribute__((always_inline)) +#else +# define PRISM_FORCE_INLINE inline +#endif + +#endif diff --git a/include/prism/internal/line_offset_list.h b/include/prism/internal/line_offset_list.h new file mode 100644 index 0000000000..4b7d9fc1a6 --- /dev/null +++ b/include/prism/internal/line_offset_list.h @@ -0,0 +1,73 @@ +/** + * @file internal/line_offset_list.h + * + * A list of byte offsets of newlines in a string. + * + * When compiling the syntax tree, it's necessary to know the line and column + * of many nodes. This is necessary to support things like error messages, + * tracepoints, etc. + * + * It's possible that we could store the start line, start column, end line, and + * end column on every node in addition to the offsets that we already store, + * but that would be quite a lot of memory overhead. + */ +#ifndef PRISM_INTERNAL_LINE_OFFSET_LIST_H +#define PRISM_INTERNAL_LINE_OFFSET_LIST_H + +#include "prism/line_offset_list.h" +#include "prism/force_inline.h" +#include "prism/util/pm_arena.h" + +/** + * Initialize a new line offset list with the given capacity. + * + * @param arena The arena to allocate from. + * @param list The list to initialize. + * @param capacity The initial capacity of the list. + */ +void pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity); + +/** + * Clear out the offsets that have been appended to the list. + * + * @param list The list to clear. + */ +void pm_line_offset_list_clear(pm_line_offset_list_t *list); + +/** + * Append a new offset to the list (slow path with resize). + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param cursor The offset to append. + */ +void pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor); + +/** + * Append a new offset to the list. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param cursor The offset to append. + */ +static PRISM_FORCE_INLINE void +pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) { + if (list->size < list->capacity) { + list->offsets[list->size++] = cursor; + } else { + pm_line_offset_list_append_slow(arena, list, cursor); + } +} + +/** + * Returns the line of the given offset. If the offset is not in the list, the + * line of the closest offset less than the given offset is returned. + * + * @param list The list to search. + * @param cursor The offset to search for. + * @param start_line The line to start counting from. + * @return The line of the given offset. + */ +int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); + +#endif diff --git a/include/prism/line_offset_list.h b/include/prism/line_offset_list.h index 53e697ed86..33bdd03aaa 100644 --- a/include/prism/line_offset_list.h +++ b/include/prism/line_offset_list.h @@ -14,13 +14,10 @@ #ifndef PRISM_LINE_OFFSET_LIST_H #define PRISM_LINE_OFFSET_LIST_H -#include "prism/defines.h" -#include "prism/util/pm_arena.h" +#include "prism/exported.h" -#include -#include #include -#include +#include /** * A list of offsets of the start of lines in a string. The offsets are assumed @@ -48,58 +45,6 @@ typedef struct { uint32_t column; } pm_line_column_t; -/** - * Initialize a new line offset list with the given capacity. - * - * @param arena The arena to allocate from. - * @param list The list to initialize. - * @param capacity The initial capacity of the list. - */ -void pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity); - -/** - * Clear out the offsets that have been appended to the list. - * - * @param list The list to clear. - */ -void pm_line_offset_list_clear(pm_line_offset_list_t *list); - -/** - * Append a new offset to the list (slow path with resize). - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param cursor The offset to append. - */ -void pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor); - -/** - * Append a new offset to the list. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param cursor The offset to append. - */ -static PRISM_FORCE_INLINE void -pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) { - if (list->size < list->capacity) { - list->offsets[list->size++] = cursor; - } else { - pm_line_offset_list_append_slow(arena, list, cursor); - } -} - -/** - * Returns the line of the given offset. If the offset is not in the list, the - * line of the closest offset less than the given offset is returned. - * - * @param list The list to search. - * @param cursor The offset to search for. - * @param start_line The line to start counting from. - * @return The line of the given offset. - */ -int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); - /** * Returns the line and column of the given offset. If the offset is not in the * list, the line and column of the closest offset less than the given offset diff --git a/include/prism/util/pm_char.h b/include/prism/util/pm_char.h index 0be57d5a52..a6ffd1b107 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/util/pm_char.h @@ -7,6 +7,7 @@ #define PRISM_CHAR_H #include "prism/defines.h" +#include "prism/util/pm_arena.h" #include "prism/line_offset_list.h" #include diff --git a/prism.gemspec b/prism.gemspec index 302fe17aca..e3c0b34d20 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -46,6 +46,7 @@ Gem::Specification.new do |spec| "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", + "include/prism/align.h", "include/prism/allocator.h", "include/prism/ast.h", "include/prism/buffer.h", @@ -54,6 +55,7 @@ Gem::Specification.new do |spec| "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/exported.h", + "include/prism/force_inline.h", "include/prism/format.h", "include/prism/integer.h", "include/prism/line_offset_list.h", @@ -66,6 +68,7 @@ Gem::Specification.new do |spec| "include/prism/static_literals.h", "include/prism/internal/buffer.h", "include/prism/internal/integer.h", + "include/prism/internal/line_offset_list.h", "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", "include/prism/util/pm_arena.h", diff --git a/src/buffer.c b/src/buffer.c index dbbb05c7ef..865212bb80 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2,6 +2,7 @@ #include "prism/allocator.h" #include "prism/util/pm_char.h" +#include #include #include #include diff --git a/src/line_offset_list.c b/src/line_offset_list.c index 8513fdb46e..81976aacb3 100644 --- a/src/line_offset_list.c +++ b/src/line_offset_list.c @@ -1,4 +1,8 @@ -#include "prism/line_offset_list.h" +#include "prism/internal/line_offset_list.h" +#include "prism/align.h" + +#include +#include /** * Initialize a new line offset list with the given capacity. diff --git a/src/prism.c b/src/prism.c index fdf3bacb42..a4a7faafbf 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,4 +1,5 @@ #include "prism/internal/integer.h" +#include "prism/internal/line_offset_list.h" #include "prism.h" #include "prism/node_new.h" diff --git a/src/util/pm_char.c b/src/util/pm_char.c index ac283af356..346f15feb8 100644 --- a/src/util/pm_char.c +++ b/src/util/pm_char.c @@ -1,4 +1,5 @@ #include "prism/util/pm_char.h" +#include "prism/internal/line_offset_list.h" #define PRISM_CHAR_BIT_REGEXP_OPTION (1 << 2) From 895b395b99bdace27f2cdcf7883963ca21a3b6d2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 10:19:54 -0400 Subject: [PATCH 158/289] Move char to internal headers --- include/prism.h | 1 - .../prism/{util/pm_char.h => internal/char.h} | 20 +++++++++++++------ include/prism/options.h | 1 - prism.gemspec | 4 ++-- rakelib/char.rake | 2 +- src/buffer.c | 2 +- src/{util/pm_char.c => char.c} | 15 +------------- src/options.c | 1 + src/prism.c | 4 +++- src/regexp.c | 3 ++- 10 files changed, 25 insertions(+), 28 deletions(-) rename include/prism/{util/pm_char.h => internal/char.h} (96%) rename src/{util/pm_char.c => char.c} (95%) diff --git a/include/prism.h b/include/prism.h index cb4439e77a..46a6a6fa6c 100644 --- a/include/prism.h +++ b/include/prism.h @@ -12,7 +12,6 @@ extern "C" { #include "prism/defines.h" #include "prism/util/pm_arena.h" -#include "prism/util/pm_char.h" #include "prism/util/pm_strpbrk.h" #include "prism/internal/buffer.h" #include "prism/internal/memchr.h" diff --git a/include/prism/util/pm_char.h b/include/prism/internal/char.h similarity index 96% rename from include/prism/util/pm_char.h rename to include/prism/internal/char.h index a6ffd1b107..17e696142d 100644 --- a/include/prism/util/pm_char.h +++ b/include/prism/internal/char.h @@ -1,17 +1,25 @@ /** - * @file pm_char.h + * @file internal/char.h * * Functions for working with characters and strings. */ -#ifndef PRISM_CHAR_H -#define PRISM_CHAR_H +#ifndef PRISM_INTERNAL_CHAR_H +#define PRISM_INTERNAL_CHAR_H -#include "prism/defines.h" -#include "prism/util/pm_arena.h" +// #include "prism/defines.h" +// #include "prism/util/pm_arena.h" +// #include "prism/line_offset_list.h" + +// #include +// #include + +#include "prism/force_inline.h" #include "prism/line_offset_list.h" +#include "prism/util/pm_arena.h" #include #include +#include /** Bit flag for whitespace characters in pm_byte_table. */ #define PRISM_CHAR_BIT_WHITESPACE (1 << 0) @@ -21,7 +29,7 @@ /** * A lookup table for classifying bytes. Each entry is a bitfield of - * PRISM_CHAR_BIT_* flags. Defined in pm_char.c. + * PRISM_CHAR_BIT_* flags. Defined in char.c. */ extern const uint8_t pm_byte_table[256]; diff --git a/include/prism/options.h b/include/prism/options.h index 9a19a2aead..41f3bc7f42 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -7,7 +7,6 @@ #define PRISM_OPTIONS_H #include "prism/defines.h" -#include "prism/util/pm_char.h" #include "prism/util/pm_string.h" #include diff --git a/prism.gemspec b/prism.gemspec index e3c0b34d20..4666d975f5 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -67,12 +67,12 @@ Gem::Specification.new do |spec| "include/prism/regexp.h", "include/prism/static_literals.h", "include/prism/internal/buffer.h", + "include/prism/internal/char.h", "include/prism/internal/integer.h", "include/prism/internal/line_offset_list.h", "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", "include/prism/util/pm_arena.h", - "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_list.h", "include/prism/util/pm_string.h", @@ -167,6 +167,7 @@ Gem::Specification.new do |spec| "sig/generated/prism/parse_result/errors.rbs", "sig/generated/prism/parse_result/newlines.rbs", "src/buffer.c", + "src/char.c", "src/diagnostic.c", "src/encoding.c", "src/integer.c", @@ -182,7 +183,6 @@ Gem::Specification.new do |spec| "src/strncasecmp.c", "src/token_type.c", "src/util/pm_arena.c", - "src/util/pm_char.c", "src/util/pm_constant_pool.c", "src/util/pm_list.c", "src/util/pm_string.c", diff --git a/rakelib/char.rake b/rakelib/char.rake index 112e20b50d..d1486a440e 100644 --- a/rakelib/char.rake +++ b/rakelib/char.rake @@ -1,6 +1,6 @@ # frozen_string_literal: true -desc "Generate the lookup tables for pm_char.c" +desc "Generate the lookup tables for char.c" namespace :generate do task :char do puts "static const uint8_t pm_char_table[256] = {" diff --git a/src/buffer.c b/src/buffer.c index 865212bb80..b416519795 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,6 +1,6 @@ #include "prism/internal/buffer.h" +#include "prism/internal/char.h" #include "prism/allocator.h" -#include "prism/util/pm_char.h" #include #include diff --git a/src/util/pm_char.c b/src/char.c similarity index 95% rename from src/util/pm_char.c rename to src/char.c index 346f15feb8..c119ee8a19 100644 --- a/src/util/pm_char.c +++ b/src/char.c @@ -1,4 +1,4 @@ -#include "prism/util/pm_char.h" +#include "prism/internal/char.h" #include "prism/internal/line_offset_list.h" #define PRISM_CHAR_BIT_REGEXP_OPTION (1 << 2) @@ -270,16 +270,3 @@ bool pm_char_is_hexadecimal_digit(const uint8_t b) { return pm_char_is_number_kind(b, PRISM_NUMBER_BIT_HEXADECIMAL_DIGIT); } - -#undef PRISM_CHAR_BIT_WHITESPACE -#undef PRISM_CHAR_BIT_INLINE_WHITESPACE -#undef PRISM_CHAR_BIT_REGEXP_OPTION - -#undef PRISM_NUMBER_BIT_BINARY_DIGIT -#undef PRISM_NUMBER_BIT_BINARY_NUMBER -#undef PRISM_NUMBER_BIT_OCTAL_DIGIT -#undef PRISM_NUMBER_BIT_OCTAL_NUMBER -#undef PRISM_NUMBER_BIT_DECIMAL_DIGIT -#undef PRISM_NUMBER_BIT_DECIMAL_NUMBER -#undef PRISM_NUMBER_BIT_HEXADECIMAL_NUMBER -#undef PRISM_NUMBER_BIT_HEXADECIMAL_DIGIT diff --git a/src/options.c b/src/options.c index ecd88a8021..c89515964c 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,5 @@ #include "prism/options.h" +#include "prism/internal/char.h" /** * Set the shebang callback option on the given options struct. diff --git a/src/prism.c b/src/prism.c index a4a7faafbf..64c2680ee3 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,7 +1,9 @@ +#include "prism.h" + +#include "prism/internal/char.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" -#include "prism.h" #include "prism/node_new.h" /** diff --git a/src/regexp.c b/src/regexp.c index 33a546dde8..60ebcd86ee 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,6 +1,7 @@ +#include "prism/regexp.h" #include "prism/internal/buffer.h" +#include "prism/internal/char.h" #include "prism/internal/strncasecmp.h" -#include "prism/regexp.h" #include "prism/diagnostic.h" /** The maximum depth of nested groups allowed in a regular expression. */ From c74b7c3f5287aadeb136497ddf575cc350449bb8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 10:23:11 -0400 Subject: [PATCH 159/289] Move arena out of utils --- include/prism.h | 2 +- include/prism/{util/pm_arena.h => arena.h} | 2 +- include/prism/internal/char.h | 9 +-------- include/prism/internal/line_offset_list.h | 2 +- include/prism/parser.h | 2 +- include/prism/util/pm_constant_pool.h | 2 +- prism.gemspec | 4 ++-- src/{util/pm_arena.c => arena.c} | 2 +- src/util/pm_constant_pool.c | 2 +- templates/include/prism/diagnostic.h.erb | 4 ++-- templates/src/diagnostic.c.erb | 2 +- 11 files changed, 13 insertions(+), 20 deletions(-) rename include/prism/{util/pm_arena.h => arena.h} (99%) rename src/{util/pm_arena.c => arena.c} (98%) diff --git a/include/prism.h b/include/prism.h index 46a6a6fa6c..e4310ff395 100644 --- a/include/prism.h +++ b/include/prism.h @@ -11,11 +11,11 @@ extern "C" { #endif #include "prism/defines.h" -#include "prism/util/pm_arena.h" #include "prism/util/pm_strpbrk.h" #include "prism/internal/buffer.h" #include "prism/internal/memchr.h" #include "prism/internal/strncasecmp.h" +#include "prism/arena.h" #include "prism/ast.h" #include "prism/diagnostic.h" #include "prism/node.h" diff --git a/include/prism/util/pm_arena.h b/include/prism/arena.h similarity index 99% rename from include/prism/util/pm_arena.h rename to include/prism/arena.h index 175b39c6df..deeaba19a9 100644 --- a/include/prism/util/pm_arena.h +++ b/include/prism/arena.h @@ -1,5 +1,5 @@ /** - * @file pm_arena.h + * @file arena.h * * A bump allocator for the prism parser. */ diff --git a/include/prism/internal/char.h b/include/prism/internal/char.h index 17e696142d..7b394e43dc 100644 --- a/include/prism/internal/char.h +++ b/include/prism/internal/char.h @@ -6,16 +6,9 @@ #ifndef PRISM_INTERNAL_CHAR_H #define PRISM_INTERNAL_CHAR_H -// #include "prism/defines.h" -// #include "prism/util/pm_arena.h" -// #include "prism/line_offset_list.h" - -// #include -// #include - +#include "prism/arena.h" #include "prism/force_inline.h" #include "prism/line_offset_list.h" -#include "prism/util/pm_arena.h" #include #include diff --git a/include/prism/internal/line_offset_list.h b/include/prism/internal/line_offset_list.h index 4b7d9fc1a6..112603cdb9 100644 --- a/include/prism/internal/line_offset_list.h +++ b/include/prism/internal/line_offset_list.h @@ -15,8 +15,8 @@ #define PRISM_INTERNAL_LINE_OFFSET_LIST_H #include "prism/line_offset_list.h" +#include "prism/arena.h" #include "prism/force_inline.h" -#include "prism/util/pm_arena.h" /** * Initialize a new line offset list with the given capacity. diff --git a/include/prism/parser.h b/include/prism/parser.h index 1d8f28fff6..0922a2069a 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -7,12 +7,12 @@ #define PRISM_PARSER_H #include "prism/defines.h" +#include "prism/arena.h" #include "prism/ast.h" #include "prism/encoding.h" #include "prism/line_offset_list.h" #include "prism/options.h" #include "prism/static_literals.h" -#include "prism/util/pm_arena.h" #include "prism/util/pm_constant_pool.h" #include "prism/util/pm_list.h" #include "prism/util/pm_string.h" diff --git a/include/prism/util/pm_constant_pool.h b/include/prism/util/pm_constant_pool.h index c527343273..22599cdec1 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/util/pm_constant_pool.h @@ -11,7 +11,7 @@ #define PRISM_CONSTANT_POOL_H #include "prism/defines.h" -#include "prism/util/pm_arena.h" +#include "prism/arena.h" #include #include diff --git a/prism.gemspec b/prism.gemspec index 4666d975f5..3cbd0dc958 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -48,6 +48,7 @@ Gem::Specification.new do |spec| "include/prism.h", "include/prism/align.h", "include/prism/allocator.h", + "include/prism/arena.h", "include/prism/ast.h", "include/prism/buffer.h", "include/prism/debug_allocator.h", @@ -72,7 +73,6 @@ Gem::Specification.new do |spec| "include/prism/internal/line_offset_list.h", "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", - "include/prism/util/pm_arena.h", "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_list.h", "include/prism/util/pm_string.h", @@ -166,6 +166,7 @@ Gem::Specification.new do |spec| "sig/generated/prism/parse_result/comments.rbs", "sig/generated/prism/parse_result/errors.rbs", "sig/generated/prism/parse_result/newlines.rbs", + "src/arena.c", "src/buffer.c", "src/char.c", "src/diagnostic.c", @@ -182,7 +183,6 @@ Gem::Specification.new do |spec| "src/static_literals.c", "src/strncasecmp.c", "src/token_type.c", - "src/util/pm_arena.c", "src/util/pm_constant_pool.c", "src/util/pm_list.c", "src/util/pm_string.c", diff --git a/src/util/pm_arena.c b/src/arena.c similarity index 98% rename from src/util/pm_arena.c rename to src/arena.c index 6b07e25210..aa12b1b836 100644 --- a/src/util/pm_arena.c +++ b/src/arena.c @@ -1,4 +1,4 @@ -#include "prism/util/pm_arena.h" +#include "prism/arena.h" #include diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index 74e2a12524..3694b95c82 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -1,5 +1,5 @@ #include "prism/util/pm_constant_pool.h" -#include "prism/util/pm_arena.h" +#include "prism/arena.h" /** * Initialize a list of constant ids. diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb index 935fb663ea..2982a46587 100644 --- a/templates/include/prism/diagnostic.h.erb +++ b/templates/include/prism/diagnostic.h.erb @@ -6,9 +6,9 @@ #ifndef PRISM_DIAGNOSTIC_H #define PRISM_DIAGNOSTIC_H -#include "prism/ast.h" #include "prism/defines.h" -#include "prism/util/pm_arena.h" +#include "prism/arena.h" +#include "prism/ast.h" #include "prism/util/pm_list.h" #include diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index b02714637d..8cb3eb7302 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -1,5 +1,5 @@ #include "prism/diagnostic.h" -#include "prism/util/pm_arena.h" +#include "prism/arena.h" #define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %> From c03b69b16e583d178a0c2ecb7bc1e0702439a288 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 10:35:09 -0400 Subject: [PATCH 160/289] Split up arena headers into public and internal --- include/prism/arena.h | 52 +++--------------------------- include/prism/defines.h | 13 +------- include/prism/flex_array.h | 21 ++++++++++++ include/prism/internal/arena.h | 58 ++++++++++++++++++++++++++++++++++ prism.gemspec | 2 ++ src/arena.c | 5 ++- src/line_offset_list.c | 1 + src/prism.c | 1 + src/util/pm_constant_pool.c | 2 +- templates/src/diagnostic.c.erb | 2 +- 10 files changed, 94 insertions(+), 63 deletions(-) create mode 100644 include/prism/flex_array.h create mode 100644 include/prism/internal/arena.h diff --git a/include/prism/arena.h b/include/prism/arena.h index deeaba19a9..752ca766ae 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -6,12 +6,11 @@ #ifndef PRISM_ARENA_H #define PRISM_ARENA_H -#include "prism/defines.h" +#include "prism/exported.h" +#include "prism/flex_array.h" +#include "prism/force_inline.h" #include -#include -#include -#include /** * A single block of memory in the arena. Blocks are linked via prev pointers so @@ -28,7 +27,7 @@ typedef struct pm_arena_block { size_t used; /** The block's data. */ - char data[PM_FLEX_ARY_LEN]; + char data[PM_FLEX_ARRAY_LENGTH]; } pm_arena_block_t; /** @@ -44,16 +43,6 @@ typedef struct { size_t block_count; } pm_arena_t; -/** - * Ensure the arena has at least `capacity` bytes available in its current - * block, allocating a new block if necessary. This allows callers to - * pre-size the arena to avoid repeated small block allocations. - * - * @param arena The arena to pre-size. - * @param capacity The minimum number of bytes to ensure are available. - */ -void pm_arena_reserve(pm_arena_t *arena, size_t capacity); - /** * Slow path for pm_arena_alloc: allocate a new block and return a pointer to * the first `size` bytes. Do not call directly — use pm_arena_alloc instead. @@ -91,39 +80,6 @@ pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { return pm_arena_alloc_slow(arena, size); } -/** - * Allocate zero-initialized memory from the arena. This function is infallible - * — it aborts on allocation failure. - * - * @param arena The arena to allocate from. - * @param size The number of bytes to allocate. - * @param alignment The required alignment (must be a power of 2). - * @returns A pointer to the allocated, zero-initialized memory. - */ -static inline void * -pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { - void *ptr = pm_arena_alloc(arena, size, alignment); - memset(ptr, 0, size); - return ptr; -} - -/** - * Allocate memory from the arena and copy the given data into it. This is a - * convenience wrapper around pm_arena_alloc + memcpy. - * - * @param arena The arena to allocate from. - * @param src The source data to copy. - * @param size The number of bytes to allocate and copy. - * @param alignment The required alignment (must be a power of 2). - * @returns A pointer to the allocated copy. - */ -static inline void * -pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { - void *dst = pm_arena_alloc(arena, size, alignment); - memcpy(dst, src, size); - return dst; -} - /** * Free all blocks in the arena. After this call, all pointers returned by * pm_arena_alloc and pm_arena_zalloc are invalid. diff --git a/include/prism/defines.h b/include/prism/defines.h index fcfc8b84a1..048e967b62 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -12,6 +12,7 @@ #include "prism/align.h" #include "prism/allocator.h" #include "prism/exported.h" +#include "prism/flex_array.h" #include "prism/force_inline.h" #include "prism/format.h" @@ -292,16 +293,4 @@ #define PRISM_FALLTHROUGH #endif -/** - * A macro for defining a flexible array member. C99 supports `data[]`, GCC - * supports `data[0]` as an extension, and older compilers require `data[1]`. - */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - #define PM_FLEX_ARY_LEN /* data[] */ -#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) - #define PM_FLEX_ARY_LEN 0 /* data[0] */ -#else - #define PM_FLEX_ARY_LEN 1 /* data[1] */ -#endif - #endif diff --git a/include/prism/flex_array.h b/include/prism/flex_array.h new file mode 100644 index 0000000000..d21e336311 --- /dev/null +++ b/include/prism/flex_array.h @@ -0,0 +1,21 @@ +/** + * @file flex_array.h + * + * Macro definitions for working with flexible array members. + */ +#ifndef PRISM_FLEX_ARRAY_H +#define PRISM_FLEX_ARRAY_H + +/** + * A macro for defining a flexible array member. C99 supports `data[]`, GCC + * supports `data[0]` as an extension, and older compilers require `data[1]`. + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + #define PM_FLEX_ARRAY_LENGTH /* data[] */ +#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) + #define PM_FLEX_ARRAY_LENGTH 0 /* data[0] */ +#else + #define PM_FLEX_ARRAY_LENGTH 1 /* data[1] */ +#endif + +#endif diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h new file mode 100644 index 0000000000..32a62735ab --- /dev/null +++ b/include/prism/internal/arena.h @@ -0,0 +1,58 @@ +/** + * @file internal/arena.h + * + * A bump allocator for the prism parser. + */ +#ifndef PRISM_INTERNAL_ARENA_H +#define PRISM_INTERNAL_ARENA_H + +#include "prism/arena.h" +#include "prism/exported.h" + +#include +#include + +/** + * Ensure the arena has at least `capacity` bytes available in its current + * block, allocating a new block if necessary. This allows callers to + * pre-size the arena to avoid repeated small block allocations. + * + * @param arena The arena to pre-size. + * @param capacity The minimum number of bytes to ensure are available. + */ +void pm_arena_reserve(pm_arena_t *arena, size_t capacity); + +/** + * Allocate zero-initialized memory from the arena. This function is infallible + * — it aborts on allocation failure. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated, zero-initialized memory. + */ +static inline void * +pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { + void *ptr = pm_arena_alloc(arena, size, alignment); + memset(ptr, 0, size); + return ptr; +} + +/** + * Allocate memory from the arena and copy the given data into it. This is a + * convenience wrapper around pm_arena_alloc + memcpy. + * + * @param arena The arena to allocate from. + * @param src The source data to copy. + * @param size The number of bytes to allocate and copy. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated copy. + */ +static inline void * +pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { + void *dst = pm_arena_alloc(arena, size, alignment); + memcpy(dst, src, size); + return dst; +} + +#endif diff --git a/prism.gemspec b/prism.gemspec index 3cbd0dc958..ef64750809 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -56,6 +56,7 @@ Gem::Specification.new do |spec| "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/exported.h", + "include/prism/flex_array.h", "include/prism/force_inline.h", "include/prism/format.h", "include/prism/integer.h", @@ -67,6 +68,7 @@ Gem::Specification.new do |spec| "include/prism/prettyprint.h", "include/prism/regexp.h", "include/prism/static_literals.h", + "include/prism/internal/arena.h", "include/prism/internal/buffer.h", "include/prism/internal/char.h", "include/prism/internal/integer.h", diff --git a/src/arena.c b/src/arena.c index aa12b1b836..d7ce9c043c 100644 --- a/src/arena.c +++ b/src/arena.c @@ -1,10 +1,13 @@ #include "prism/arena.h" +#include "prism/allocator.h" #include +#include +#include /** * Compute the block allocation size using offsetof so it is correct regardless - * of PM_FLEX_ARY_LEN. + * of PM_FLEX_ARRAY_LENGTH. */ #define PM_ARENA_BLOCK_SIZE(data_size) (offsetof(pm_arena_block_t, data) + (data_size)) diff --git a/src/line_offset_list.c b/src/line_offset_list.c index 81976aacb3..752ea934f5 100644 --- a/src/line_offset_list.c +++ b/src/line_offset_list.c @@ -1,4 +1,5 @@ #include "prism/internal/line_offset_list.h" +#include "prism/internal/arena.h" #include "prism/align.h" #include diff --git a/src/prism.c b/src/prism.c index 64c2680ee3..4633ec6fb4 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,5 +1,6 @@ #include "prism.h" +#include "prism/internal/arena.h" #include "prism/internal/char.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" diff --git a/src/util/pm_constant_pool.c b/src/util/pm_constant_pool.c index 3694b95c82..679d3a6b86 100644 --- a/src/util/pm_constant_pool.c +++ b/src/util/pm_constant_pool.c @@ -1,5 +1,5 @@ #include "prism/util/pm_constant_pool.h" -#include "prism/arena.h" +#include "prism/internal/arena.h" /** * Initialize a list of constant ids. diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 8cb3eb7302..0d696772d5 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -1,5 +1,5 @@ #include "prism/diagnostic.h" -#include "prism/arena.h" +#include "prism/internal/arena.h" #define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %> From a18e3ca1789985fdd9bcb9224cb0ed04a783a893 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 10:39:31 -0400 Subject: [PATCH 161/289] Move compiler macro definitions into include/prism/attribute --- include/prism/arena.h | 6 +++--- include/prism/{ => attribute}/align.h | 2 +- include/prism/{ => attribute}/exported.h | 2 +- include/prism/{ => attribute}/flex_array.h | 2 +- include/prism/{ => attribute}/force_inline.h | 2 +- include/prism/{ => attribute}/format.h | 2 +- include/prism/buffer.h | 2 +- include/prism/defines.h | 10 +++++----- include/prism/internal/arena.h | 2 +- include/prism/internal/buffer.h | 2 +- include/prism/internal/char.h | 2 +- include/prism/internal/line_offset_list.h | 2 +- include/prism/line_offset_list.h | 2 +- prism.gemspec | 10 +++++----- src/line_offset_list.c | 2 +- 15 files changed, 25 insertions(+), 25 deletions(-) rename include/prism/{ => attribute}/align.h (97%) rename include/prism/{ => attribute}/exported.h (95%) rename include/prism/{ => attribute}/flex_array.h (94%) rename include/prism/{ => attribute}/force_inline.h (94%) rename include/prism/{ => attribute}/format.h (97%) diff --git a/include/prism/arena.h b/include/prism/arena.h index 752ca766ae..dd8ee09ceb 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -6,9 +6,9 @@ #ifndef PRISM_ARENA_H #define PRISM_ARENA_H -#include "prism/exported.h" -#include "prism/flex_array.h" -#include "prism/force_inline.h" +#include "prism/attribute/exported.h" +#include "prism/attribute/flex_array.h" +#include "prism/attribute/force_inline.h" #include diff --git a/include/prism/align.h b/include/prism/attribute/align.h similarity index 97% rename from include/prism/align.h rename to include/prism/attribute/align.h index bb120d488e..9a21b8d6ec 100644 --- a/include/prism/align.h +++ b/include/prism/attribute/align.h @@ -1,5 +1,5 @@ /** - * @file align.h + * @file attribute/align.h * * Alignment macros used throughout the prism library. */ diff --git a/include/prism/exported.h b/include/prism/attribute/exported.h similarity index 95% rename from include/prism/exported.h rename to include/prism/attribute/exported.h index 74476b0efb..8cb24848d1 100644 --- a/include/prism/exported.h +++ b/include/prism/attribute/exported.h @@ -1,5 +1,5 @@ /** - * @file exported.h + * @file attribute/exported.h * * Macro definitions for make functions publically visible. */ diff --git a/include/prism/flex_array.h b/include/prism/attribute/flex_array.h similarity index 94% rename from include/prism/flex_array.h rename to include/prism/attribute/flex_array.h index d21e336311..8daefba32b 100644 --- a/include/prism/flex_array.h +++ b/include/prism/attribute/flex_array.h @@ -1,5 +1,5 @@ /** - * @file flex_array.h + * @file attribute/flex_array.h * * Macro definitions for working with flexible array members. */ diff --git a/include/prism/force_inline.h b/include/prism/attribute/force_inline.h similarity index 94% rename from include/prism/force_inline.h rename to include/prism/attribute/force_inline.h index c205e5ddf6..1d2c494d6e 100644 --- a/include/prism/force_inline.h +++ b/include/prism/attribute/force_inline.h @@ -1,5 +1,5 @@ /** - * @file force_inline.h + * @file attribute/force_inline.h * * Macro definitions for forcing a function to be inlined at every call site. */ diff --git a/include/prism/format.h b/include/prism/attribute/format.h similarity index 97% rename from include/prism/format.h rename to include/prism/attribute/format.h index 973fc3fe4e..4ad99fe125 100644 --- a/include/prism/format.h +++ b/include/prism/attribute/format.h @@ -1,5 +1,5 @@ /** - * @file format.h + * @file attribute/format.h * * Macro definition for specifying that a function accepts variadic parameters * that look like printf format strings. diff --git a/include/prism/buffer.h b/include/prism/buffer.h index ffc07461fc..90f7c9198e 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -6,7 +6,7 @@ #ifndef PRISM_BUFFER_H #define PRISM_BUFFER_H -#include "prism/exported.h" +#include "prism/attribute/exported.h" #include #include diff --git a/include/prism/defines.h b/include/prism/defines.h index 048e967b62..1c271a80c8 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -9,12 +9,12 @@ #ifndef PRISM_DEFINES_H #define PRISM_DEFINES_H -#include "prism/align.h" +#include "prism/attribute/align.h" +#include "prism/attribute/exported.h" +#include "prism/attribute/flex_array.h" +#include "prism/attribute/force_inline.h" +#include "prism/attribute/format.h" #include "prism/allocator.h" -#include "prism/exported.h" -#include "prism/flex_array.h" -#include "prism/force_inline.h" -#include "prism/format.h" #include #include diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h index 32a62735ab..e86b89903e 100644 --- a/include/prism/internal/arena.h +++ b/include/prism/internal/arena.h @@ -6,8 +6,8 @@ #ifndef PRISM_INTERNAL_ARENA_H #define PRISM_INTERNAL_ARENA_H +#include "prism/attribute/exported.h" #include "prism/arena.h" -#include "prism/exported.h" #include #include diff --git a/include/prism/internal/buffer.h b/include/prism/internal/buffer.h index a5c46ed530..b1d360c91e 100644 --- a/include/prism/internal/buffer.h +++ b/include/prism/internal/buffer.h @@ -7,7 +7,7 @@ #define PRISM_INTERNAL_BUFFER_H #include "prism/buffer.h" -#include "prism/format.h" +#include "prism/attribute/format.h" #include diff --git a/include/prism/internal/char.h b/include/prism/internal/char.h index 7b394e43dc..b3975862dd 100644 --- a/include/prism/internal/char.h +++ b/include/prism/internal/char.h @@ -6,8 +6,8 @@ #ifndef PRISM_INTERNAL_CHAR_H #define PRISM_INTERNAL_CHAR_H +#include "prism/attribute/force_inline.h" #include "prism/arena.h" -#include "prism/force_inline.h" #include "prism/line_offset_list.h" #include diff --git a/include/prism/internal/line_offset_list.h b/include/prism/internal/line_offset_list.h index 112603cdb9..87af0bb524 100644 --- a/include/prism/internal/line_offset_list.h +++ b/include/prism/internal/line_offset_list.h @@ -15,8 +15,8 @@ #define PRISM_INTERNAL_LINE_OFFSET_LIST_H #include "prism/line_offset_list.h" +#include "prism/attribute/force_inline.h" #include "prism/arena.h" -#include "prism/force_inline.h" /** * Initialize a new line offset list with the given capacity. diff --git a/include/prism/line_offset_list.h b/include/prism/line_offset_list.h index 33bdd03aaa..0211b990fe 100644 --- a/include/prism/line_offset_list.h +++ b/include/prism/line_offset_list.h @@ -14,7 +14,7 @@ #ifndef PRISM_LINE_OFFSET_LIST_H #define PRISM_LINE_OFFSET_LIST_H -#include "prism/exported.h" +#include "prism/attribute/exported.h" #include #include diff --git a/prism.gemspec b/prism.gemspec index ef64750809..d9a3d15e62 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -46,7 +46,11 @@ Gem::Specification.new do |spec| "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", - "include/prism/align.h", + "include/prism/attribute/align.h", + "include/prism/attribute/exported.h", + "include/prism/attribute/flex_array.h", + "include/prism/attribute/force_inline.h", + "include/prism/attribute/format.h", "include/prism/allocator.h", "include/prism/arena.h", "include/prism/ast.h", @@ -55,10 +59,6 @@ Gem::Specification.new do |spec| "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", - "include/prism/exported.h", - "include/prism/flex_array.h", - "include/prism/force_inline.h", - "include/prism/format.h", "include/prism/integer.h", "include/prism/line_offset_list.h", "include/prism/node.h", diff --git a/src/line_offset_list.c b/src/line_offset_list.c index 752ea934f5..17946a224a 100644 --- a/src/line_offset_list.c +++ b/src/line_offset_list.c @@ -1,6 +1,6 @@ +#include "prism/attribute/align.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/arena.h" -#include "prism/align.h" #include #include From 104b6abd10a749448eeb3c5ec7073d99a1334f2a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 10:54:29 -0400 Subject: [PATCH 162/289] Move strpbrk into internal --- include/prism.h | 1 - include/prism/attribute/unused.h | 21 +++ include/prism/defines.h | 135 +----------------- include/prism/internal/accel.h | 21 +++ include/prism/internal/bit.h | 40 ++++++ .../{util/pm_strpbrk.h => internal/strpbrk.h} | 10 +- prism.gemspec | 9 +- src/prism.c | 3 + src/{util/pm_strpbrk.c => strpbrk.c} | 11 +- 9 files changed, 109 insertions(+), 142 deletions(-) create mode 100644 include/prism/attribute/unused.h create mode 100644 include/prism/internal/accel.h create mode 100644 include/prism/internal/bit.h rename include/prism/{util/pm_strpbrk.h => internal/strpbrk.h} (92%) rename src/{util/pm_strpbrk.c => strpbrk.c} (98%) diff --git a/include/prism.h b/include/prism.h index e4310ff395..3627c459a8 100644 --- a/include/prism.h +++ b/include/prism.h @@ -11,7 +11,6 @@ extern "C" { #endif #include "prism/defines.h" -#include "prism/util/pm_strpbrk.h" #include "prism/internal/buffer.h" #include "prism/internal/memchr.h" #include "prism/internal/strncasecmp.h" diff --git a/include/prism/attribute/unused.h b/include/prism/attribute/unused.h new file mode 100644 index 0000000000..37a7b00f40 --- /dev/null +++ b/include/prism/attribute/unused.h @@ -0,0 +1,21 @@ +/** + * @file attribute/unused.h + * + * Macro definitions for marking functions and parameters as unused to suppress + * compiler warnings. + */ +#ifndef PRISM_ATTRIBUTE_UNUSED_H +#define PRISM_ATTRIBUTE_UNUSED_H + +/** + * GCC will warn if you specify a function or parameter that is unused at + * runtime. This macro allows you to mark a function or parameter as unused in a + * compiler-agnostic way. + */ +#if defined(__GNUC__) +# define PRISM_ATTRIBUTE_UNUSED __attribute__((unused)) +#else +# define PRISM_ATTRIBUTE_UNUSED +#endif + +#endif diff --git a/include/prism/defines.h b/include/prism/defines.h index 1c271a80c8..ad1cf2b75c 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -14,7 +14,11 @@ #include "prism/attribute/flex_array.h" #include "prism/attribute/force_inline.h" #include "prism/attribute/format.h" +#include "prism/attribute/unused.h" + #include "prism/allocator.h" +#include "prism/internal/accel.h" +#include "prism/internal/bit.h" #include #include @@ -44,17 +48,6 @@ #define PRISM_DEPTH_MAXIMUM 10000 #endif -/** - * GCC will warn if you specify a function or parameter that is unused at - * runtime. This macro allows you to mark a function or parameter as unused in a - * compiler-agnostic way. - */ -#if defined(__GNUC__) -# define PRISM_ATTRIBUTE_UNUSED __attribute__((unused)) -#else -# define PRISM_ATTRIBUTE_UNUSED -#endif - /** * Old Visual Studio versions do not support the inline keyword, so we need to * define it to be __inline. @@ -123,83 +116,6 @@ #define PRISM_ISINF(x) isinf(x) #endif -/** - * If you build prism with a custom allocator, configure it with - * "-D PRISM_XALLOCATOR" to use your own allocator that defines xmalloc, - * xrealloc, xcalloc, and xfree. - * - * For example, your `prism_xallocator.h` file could look like this: - * - * ``` - * #ifndef PRISM_XALLOCATOR_H - * #define PRISM_XALLOCATOR_H - * #define xmalloc my_malloc - * #define xrealloc my_realloc - * #define xcalloc my_calloc - * #define xfree my_free - * #define xrealloc_sized my_realloc_sized // (optional) - * #define xfree_sized my_free_sized // (optional) - * #endif - * ``` - */ -#ifdef PRISM_XALLOCATOR - #include "prism_xallocator.h" -#else - #ifndef xmalloc - /** - * The malloc function that should be used. This can be overridden with - * the PRISM_XALLOCATOR define. - */ - #define xmalloc malloc - #endif - - #ifndef xrealloc - /** - * The realloc function that should be used. This can be overridden with - * the PRISM_XALLOCATOR define. - */ - #define xrealloc realloc - #endif - - #ifndef xcalloc - /** - * The calloc function that should be used. This can be overridden with - * the PRISM_XALLOCATOR define. - */ - #define xcalloc calloc - #endif - - #ifndef xfree - /** - * The free function that should be used. This can be overridden with the - * PRISM_XALLOCATOR define. - */ - #define xfree free - #endif -#endif - -#ifndef xfree_sized -/** - * The free_sized function that should be used. This can be overridden with the - * PRISM_XALLOCATOR define. - * If not defined, defaults to calling xfree. - */ - #define xfree_sized(p, s) xfree(((void)(s), (p))) -#endif - -#ifndef xrealloc_sized -/** - * The xrealloc_sized function that should be used. This can be overridden with the - * PRISM_XALLOCATOR define. - * If not defined, defaults to calling xrealloc. - */ - #define xrealloc_sized(p, ns, os) xrealloc((p), ((void)(os), (ns))) -#endif - -#ifdef PRISM_BUILD_DEBUG - #include "prism/debug_allocator.h" -#endif - /** * If PRISM_BUILD_MINIMAL is defined, then we're going to define every possible * switch that will turn off certain features of prism. @@ -236,49 +152,6 @@ #define PRISM_UNLIKELY(x) (x) #endif -/** - * Platform detection for SIMD / fast-path implementations. At most one of - * these macros is defined, selecting the best available vectorization strategy. - */ -#if (defined(__aarch64__) && defined(__ARM_NEON)) || (defined(_MSC_VER) && defined(_M_ARM64)) - #define PRISM_HAS_NEON -#elif (defined(__x86_64__) && defined(__SSSE3__)) || (defined(_MSC_VER) && defined(_M_X64)) - #define PRISM_HAS_SSSE3 -#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define PRISM_HAS_SWAR -#endif - -/** - * Count trailing zero bits in a 64-bit value. Used by SWAR identifier scanning - * to find the first non-matching byte in a word. - * - * Precondition: v must be nonzero. The result is undefined when v == 0 - * (matching the behavior of __builtin_ctzll and _BitScanForward64). - */ -#if defined(__GNUC__) || defined(__clang__) - #define pm_ctzll(v) ((unsigned) __builtin_ctzll(v)) -#elif defined(_MSC_VER) - #include - static inline unsigned pm_ctzll(uint64_t v) { - unsigned long index; - _BitScanForward64(&index, v); - return (unsigned) index; - } -#else - static inline unsigned - pm_ctzll(uint64_t v) { - unsigned c = 0; - v &= (uint64_t) (-(int64_t) v); - if (v & 0x00000000FFFFFFFFULL) c += 0; else c += 32; - if (v & 0x0000FFFF0000FFFFULL) c += 0; else c += 16; - if (v & 0x00FF00FF00FF00FFULL) c += 0; else c += 8; - if (v & 0x0F0F0F0F0F0F0F0FULL) c += 0; else c += 4; - if (v & 0x3333333333333333ULL) c += 0; else c += 2; - if (v & 0x5555555555555555ULL) c += 0; else c += 1; - return c; - } -#endif - /** * We use -Wimplicit-fallthrough to guard potentially unintended fall-through between cases of a switch. * Use PRISM_FALLTHROUGH to explicitly annotate cases where the fallthrough is intentional. diff --git a/include/prism/internal/accel.h b/include/prism/internal/accel.h new file mode 100644 index 0000000000..971c9b2473 --- /dev/null +++ b/include/prism/internal/accel.h @@ -0,0 +1,21 @@ +/** + * @file internal/accel.h + * + * Platform detection for acceleration implementations. + */ +#ifndef PRISM_INTERNAL_ACCEL_H +#define PRISM_INTERNAL_ACCEL_H + +/** + * Platform detection for SIMD / fast-path implementations. At most one of + * these macros is defined, selecting the best available vectorization strategy. + */ +#if (defined(__aarch64__) && defined(__ARM_NEON)) || (defined(_MSC_VER) && defined(_M_ARM64)) + #define PRISM_HAS_NEON +#elif (defined(__x86_64__) && defined(__SSSE3__)) || (defined(_MSC_VER) && defined(_M_X64)) + #define PRISM_HAS_SSSE3 +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define PRISM_HAS_SWAR +#endif + +#endif diff --git a/include/prism/internal/bit.h b/include/prism/internal/bit.h new file mode 100644 index 0000000000..110d4d68cb --- /dev/null +++ b/include/prism/internal/bit.h @@ -0,0 +1,40 @@ +/** + * @file internal/bit.h + * + * Bit manipulation utilities used throughout the prism library. + */ +#ifndef PRISM_INTERNAL_BIT_H +#define PRISM_INTERNAL_BIT_H + +/** + * Count trailing zero bits in a 64-bit value. Used by SWAR identifier scanning + * to find the first non-matching byte in a word. + * + * Precondition: v must be nonzero. The result is undefined when v == 0 + * (matching the behavior of __builtin_ctzll and _BitScanForward64). + */ +#if defined(__GNUC__) || defined(__clang__) + #define pm_ctzll(v) ((unsigned) __builtin_ctzll(v)) +#elif defined(_MSC_VER) + #include + static inline unsigned pm_ctzll(uint64_t v) { + unsigned long index; + _BitScanForward64(&index, v); + return (unsigned) index; + } +#else + static inline unsigned + pm_ctzll(uint64_t v) { + unsigned c = 0; + v &= (uint64_t) (-(int64_t) v); + if (v & 0x00000000FFFFFFFFULL) c += 0; else c += 32; + if (v & 0x0000FFFF0000FFFFULL) c += 0; else c += 16; + if (v & 0x00FF00FF00FF00FFULL) c += 0; else c += 8; + if (v & 0x0F0F0F0F0F0F0F0FULL) c += 0; else c += 4; + if (v & 0x3333333333333333ULL) c += 0; else c += 2; + if (v & 0x5555555555555555ULL) c += 0; else c += 1; + return c; + } +#endif + +#endif diff --git a/include/prism/util/pm_strpbrk.h b/include/prism/internal/strpbrk.h similarity index 92% rename from include/prism/util/pm_strpbrk.h rename to include/prism/internal/strpbrk.h index f387bd5782..ca5692d25c 100644 --- a/include/prism/util/pm_strpbrk.h +++ b/include/prism/internal/strpbrk.h @@ -1,17 +1,15 @@ /** - * @file pm_strpbrk.h + * @file internal/strpbrk.h * * A custom strpbrk implementation. */ -#ifndef PRISM_STRPBRK_H -#define PRISM_STRPBRK_H +#ifndef PRISM_INTERNAL_STRPBRK_H +#define PRISM_INTERNAL_STRPBRK_H -#include "prism/defines.h" -#include "prism/diagnostic.h" #include "prism/parser.h" #include -#include +#include /** * Here we have rolled our own version of strpbrk. The standard library strpbrk diff --git a/prism.gemspec b/prism.gemspec index d9a3d15e62..5ba050cf5d 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -51,6 +51,7 @@ Gem::Specification.new do |spec| "include/prism/attribute/flex_array.h", "include/prism/attribute/force_inline.h", "include/prism/attribute/format.h", + "include/prism/attribute/unused.h", "include/prism/allocator.h", "include/prism/arena.h", "include/prism/ast.h", @@ -68,17 +69,19 @@ Gem::Specification.new do |spec| "include/prism/prettyprint.h", "include/prism/regexp.h", "include/prism/static_literals.h", + "include/prism/internal/accel.h", "include/prism/internal/arena.h", + "include/prism/internal/bit.h", "include/prism/internal/buffer.h", "include/prism/internal/char.h", "include/prism/internal/integer.h", "include/prism/internal/line_offset_list.h", "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", + "include/prism/internal/strpbrk.h", "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_list.h", "include/prism/util/pm_string.h", - "include/prism/util/pm_strpbrk.h", "include/prism/version.h", "lib/prism.rb", "lib/prism/compiler.rb", @@ -184,11 +187,11 @@ Gem::Specification.new do |spec| "src/serialize.c", "src/static_literals.c", "src/strncasecmp.c", + "src/strpbrk.c", "src/token_type.c", "src/util/pm_constant_pool.c", "src/util/pm_list.c", - "src/util/pm_string.c", - "src/util/pm_strpbrk.c" + "src/util/pm_string.c" ] spec.extensions = ["ext/prism/extconf.rb"] diff --git a/src/prism.c b/src/prism.c index 4633ec6fb4..d7e7d661ff 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,9 +1,12 @@ #include "prism.h" +#include "prism/internal/accel.h" #include "prism/internal/arena.h" +#include "prism/internal/bit.h" #include "prism/internal/char.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" +#include "prism/internal/strpbrk.h" #include "prism/node_new.h" diff --git a/src/util/pm_strpbrk.c b/src/strpbrk.c similarity index 98% rename from src/util/pm_strpbrk.c rename to src/strpbrk.c index fdd2ab4567..b5a2089875 100644 --- a/src/util/pm_strpbrk.c +++ b/src/strpbrk.c @@ -1,4 +1,13 @@ -#include "prism/util/pm_strpbrk.h" +#include "prism/internal/strpbrk.h" + +#include "prism/attribute/unused.h" +#include "prism/internal/accel.h" +#include "prism/internal/bit.h" +#include "prism/diagnostic.h" + +#include +#include +#include /** * Add an invalid multibyte character error to the parser. From af683324eaa499a6a8793a0ef411c308fcf37d7a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:00:14 -0400 Subject: [PATCH 163/289] Split up diagnostic headers into public and internal --- include/prism/internal/diagnostic.h | 38 +++++++++++++++++++++++ prism.gemspec | 1 + src/prism.c | 1 + src/regexp.c | 3 +- src/strpbrk.c | 2 +- templates/include/prism/diagnostic.h.erb | 39 ------------------------ 6 files changed, 43 insertions(+), 41 deletions(-) create mode 100644 include/prism/internal/diagnostic.h diff --git a/include/prism/internal/diagnostic.h b/include/prism/internal/diagnostic.h new file mode 100644 index 0000000000..b06ab69124 --- /dev/null +++ b/include/prism/internal/diagnostic.h @@ -0,0 +1,38 @@ +/** + * @file internal/diagnostic.h + * + * A list of diagnostics generated during parsing. + */ +#ifndef PRISM_INTERNAL_DIAGNOSTIC_H +#define PRISM_INTERNAL_DIAGNOSTIC_H + +#include "prism/diagnostic.h" +#include "prism/arena.h" +#include "prism/util/pm_list.h" + +/** + * Append a diagnostic to the given list of diagnostics that is using shared + * memory for its message. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param start The source offset of the start of the diagnostic. + * @param length The length of the diagnostic. + * @param diag_id The diagnostic ID. + */ +void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id); + +/** + * Append a diagnostic to the given list of diagnostics that is using a format + * string for its message. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param start The source offset of the start of the diagnostic. + * @param length The length of the diagnostic. + * @param diag_id The diagnostic ID. + * @param ... The arguments to the format string for the message. + */ +void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); + +#endif diff --git a/prism.gemspec b/prism.gemspec index 5ba050cf5d..2bbce41c98 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -74,6 +74,7 @@ Gem::Specification.new do |spec| "include/prism/internal/bit.h", "include/prism/internal/buffer.h", "include/prism/internal/char.h", + "include/prism/internal/diagnostic.h", "include/prism/internal/integer.h", "include/prism/internal/line_offset_list.h", "include/prism/internal/memchr.h", diff --git a/src/prism.c b/src/prism.c index d7e7d661ff..8365b8bec2 100644 --- a/src/prism.c +++ b/src/prism.c @@ -4,6 +4,7 @@ #include "prism/internal/arena.h" #include "prism/internal/bit.h" #include "prism/internal/char.h" +#include "prism/internal/diagnostic.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/strpbrk.h" diff --git a/src/regexp.c b/src/regexp.c index 60ebcd86ee..9d8584ac17 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,8 +1,9 @@ #include "prism/regexp.h" + #include "prism/internal/buffer.h" #include "prism/internal/char.h" +#include "prism/internal/diagnostic.h" #include "prism/internal/strncasecmp.h" -#include "prism/diagnostic.h" /** The maximum depth of nested groups allowed in a regular expression. */ #define PM_REGEXP_PARSE_DEPTH_MAX 4096 diff --git a/src/strpbrk.c b/src/strpbrk.c index b5a2089875..fe7a1ab67b 100644 --- a/src/strpbrk.c +++ b/src/strpbrk.c @@ -3,7 +3,7 @@ #include "prism/attribute/unused.h" #include "prism/internal/accel.h" #include "prism/internal/bit.h" -#include "prism/diagnostic.h" +#include "prism/internal/diagnostic.h" #include #include diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb index 2982a46587..5560ea54e1 100644 --- a/templates/include/prism/diagnostic.h.erb +++ b/templates/include/prism/diagnostic.h.erb @@ -6,15 +6,9 @@ #ifndef PRISM_DIAGNOSTIC_H #define PRISM_DIAGNOSTIC_H -#include "prism/defines.h" -#include "prism/arena.h" #include "prism/ast.h" #include "prism/util/pm_list.h" -#include -#include -#include - /** * The diagnostic IDs of all of the diagnostics, used to communicate the types * of errors between the parser and the user. @@ -81,37 +75,4 @@ typedef enum { PM_WARNING_LEVEL_VERBOSE = 1 } pm_warning_level_t; -/** - * Get the human-readable name of the given diagnostic ID. - * - * @param diag_id The diagnostic ID. - * @return The human-readable name of the diagnostic ID. - */ -const char * pm_diagnostic_id_human(pm_diagnostic_id_t diag_id); - -/** - * Append a diagnostic to the given list of diagnostics that is using shared - * memory for its message. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param start The source offset of the start of the diagnostic. - * @param length The length of the diagnostic. - * @param diag_id The diagnostic ID. - */ -void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id); - -/** - * Append a diagnostic to the given list of diagnostics that is using a format - * string for its message. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param start The source offset of the start of the diagnostic. - * @param length The length of the diagnostic. - * @param diag_id The diagnostic ID. - * @param ... The arguments to the format string for the message. - */ -void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); - #endif From cc97110ba1b3fe85d6b4ac2359faec6f47be28a7 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:02:08 -0400 Subject: [PATCH 164/289] Move constant pool out of utils --- include/prism/{util/pm_constant_pool.h => constant_pool.h} | 2 +- include/prism/parser.h | 2 +- prism.gemspec | 4 ++-- src/{util/pm_constant_pool.c => constant_pool.c} | 3 ++- templates/include/prism/ast.h.erb | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) rename include/prism/{util/pm_constant_pool.h => constant_pool.h} (99%) rename src/{util/pm_constant_pool.c => constant_pool.c} (99%) diff --git a/include/prism/util/pm_constant_pool.h b/include/prism/constant_pool.h similarity index 99% rename from include/prism/util/pm_constant_pool.h rename to include/prism/constant_pool.h index 22599cdec1..7ffa2efec6 100644 --- a/include/prism/util/pm_constant_pool.h +++ b/include/prism/constant_pool.h @@ -1,5 +1,5 @@ /** - * @file pm_constant_pool.h + * @file constant_pool.h * * A data structure that stores a set of strings. * diff --git a/include/prism/parser.h b/include/prism/parser.h index 0922a2069a..312e8bd0cf 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -9,11 +9,11 @@ #include "prism/defines.h" #include "prism/arena.h" #include "prism/ast.h" +#include "prism/constant_pool.h" #include "prism/encoding.h" #include "prism/line_offset_list.h" #include "prism/options.h" #include "prism/static_literals.h" -#include "prism/util/pm_constant_pool.h" #include "prism/util/pm_list.h" #include "prism/util/pm_string.h" diff --git a/prism.gemspec b/prism.gemspec index 2bbce41c98..316d36ef22 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -56,6 +56,7 @@ Gem::Specification.new do |spec| "include/prism/arena.h", "include/prism/ast.h", "include/prism/buffer.h", + "include/prism/constant_pool.h", "include/prism/debug_allocator.h", "include/prism/defines.h", "include/prism/diagnostic.h", @@ -80,7 +81,6 @@ Gem::Specification.new do |spec| "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", "include/prism/internal/strpbrk.h", - "include/prism/util/pm_constant_pool.h", "include/prism/util/pm_list.h", "include/prism/util/pm_string.h", "include/prism/version.h", @@ -175,6 +175,7 @@ Gem::Specification.new do |spec| "src/arena.c", "src/buffer.c", "src/char.c", + "src/constant_pool.c", "src/diagnostic.c", "src/encoding.c", "src/integer.c", @@ -190,7 +191,6 @@ Gem::Specification.new do |spec| "src/strncasecmp.c", "src/strpbrk.c", "src/token_type.c", - "src/util/pm_constant_pool.c", "src/util/pm_list.c", "src/util/pm_string.c" ] diff --git a/src/util/pm_constant_pool.c b/src/constant_pool.c similarity index 99% rename from src/util/pm_constant_pool.c rename to src/constant_pool.c index 679d3a6b86..117b295d9b 100644 --- a/src/util/pm_constant_pool.c +++ b/src/constant_pool.c @@ -1,4 +1,5 @@ -#include "prism/util/pm_constant_pool.h" +#include "prism/constant_pool.h" + #include "prism/internal/arena.h" /** diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 2026d3a6c6..48c757a0e6 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -9,7 +9,7 @@ #define PRISM_AST_H #include "prism/defines.h" -#include "prism/util/pm_constant_pool.h" +#include "prism/constant_pool.h" #include "prism/util/pm_string.h" #include "prism/integer.h" From 281244ff57131d25b95582fadf560d17528aecee Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:06:28 -0400 Subject: [PATCH 165/289] Split up constant pool headers between public and internal --- include/prism/constant_pool.h | 117 +---------------------- include/prism/internal/constant_pool.h | 124 +++++++++++++++++++++++++ prism.gemspec | 1 + src/constant_pool.c | 4 + src/prism.c | 1 + templates/src/node.c.erb | 4 +- templates/src/prettyprint.c.erb | 4 +- 7 files changed, 137 insertions(+), 118 deletions(-) create mode 100644 include/prism/internal/constant_pool.h diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index 7ffa2efec6..cc426bb0ab 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -10,14 +10,8 @@ #ifndef PRISM_CONSTANT_POOL_H #define PRISM_CONSTANT_POOL_H -#include "prism/defines.h" -#include "prism/arena.h" - -#include -#include +#include #include -#include -#include /** * When we allocate constants into the pool, we reserve 0 to mean that the slot @@ -45,49 +39,6 @@ typedef struct { pm_constant_id_t *ids; } pm_constant_id_list_t; -/** - * Initialize a list of constant ids. - * - * @param list The list to initialize. - */ -void pm_constant_id_list_init(pm_constant_id_list_t *list); - -/** - * Initialize a list of constant ids with a given capacity. - * - * @param arena The arena to allocate from. - * @param list The list to initialize. - * @param capacity The initial capacity of the list. - */ -void pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity); - -/** - * Append a constant id to a list of constant ids. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param id The id to append. - */ -void pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id); - -/** - * Insert a constant id into a list of constant ids at the specified index. - * - * @param list The list to insert into. - * @param index The index at which to insert. - * @param id The id to insert. - */ -void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_constant_id_t id); - -/** - * Checks if the current constant id list includes the given constant id. - * - * @param list The list to check. - * @param id The id to check for. - * @return Whether the list includes the given id. - */ -bool pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id); - /** * The type of bucket in the constant pool hash map. This determines how the * bucket should be freed. @@ -148,70 +99,4 @@ typedef struct { uint32_t capacity; } pm_constant_pool_t; -/** - * Initialize a new constant pool with a given capacity. - * - * @param arena The arena to allocate from. - * @param pool The pool to initialize. - * @param capacity The initial capacity of the pool. - */ -void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity); - -/** - * Return a pointer to the constant indicated by the given constant id. - * - * @param pool The pool to get the constant from. - * @param constant_id The id of the constant to get. - * @return A pointer to the constant. - */ -pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id); - -/** - * Find a constant in a constant pool. Returns the id of the constant, or 0 if - * the constant is not found. - * - * @param pool The pool to find the constant in. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. - */ -pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length); - -/** - * Insert a constant into a constant pool that is a slice of a source string. - * Returns the id of the constant, or 0 if any potential calls to resize fail. - * - * @param arena The arena to allocate from. - * @param pool The pool to insert the constant into. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. - */ -pm_constant_id_t pm_constant_pool_insert_shared(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); - -/** - * Insert a constant into a constant pool from memory that is now owned by the - * constant pool. Returns the id of the constant, or 0 if any potential calls to - * resize fail. - * - * @param arena The arena to allocate from. - * @param pool The pool to insert the constant into. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. - */ -pm_constant_id_t pm_constant_pool_insert_owned(pm_arena_t *arena, pm_constant_pool_t *pool, uint8_t *start, size_t length); - -/** - * Insert a constant into a constant pool from memory that is constant. Returns - * the id of the constant, or 0 if any potential calls to resize fail. - * - * @param arena The arena to allocate from. - * @param pool The pool to insert the constant into. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. - */ -pm_constant_id_t pm_constant_pool_insert_constant(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); - #endif diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h new file mode 100644 index 0000000000..b204dfe39f --- /dev/null +++ b/include/prism/internal/constant_pool.h @@ -0,0 +1,124 @@ +/** + * @file internal/constant_pool.h + * + * A data structure that stores a set of strings. + * + * Each string is assigned a unique id, which can be used to compare strings for + * equality. This comparison ends up being much faster than strcmp, since it + * only requires a single integer comparison. + */ +#ifndef PRISM_INTERNAL_CONSTANT_POOL_H +#define PRISM_INTERNAL_CONSTANT_POOL_H + +#include "prism/constant_pool.h" + +/** + * Initialize a list of constant ids. + * + * @param list The list to initialize. + */ +void pm_constant_id_list_init(pm_constant_id_list_t *list); + +/** + * Initialize a list of constant ids with a given capacity. + * + * @param arena The arena to allocate from. + * @param list The list to initialize. + * @param capacity The initial capacity of the list. + */ +void pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity); + +/** + * Append a constant id to a list of constant ids. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param id The id to append. + */ +void pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id); + +/** + * Insert a constant id into a list of constant ids at the specified index. + * + * @param list The list to insert into. + * @param index The index at which to insert. + * @param id The id to insert. + */ +void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_constant_id_t id); + +/** + * Checks if the current constant id list includes the given constant id. + * + * @param list The list to check. + * @param id The id to check for. + * @return Whether the list includes the given id. + */ +bool pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id); + +/** + * Initialize a new constant pool with a given capacity. + * + * @param arena The arena to allocate from. + * @param pool The pool to initialize. + * @param capacity The initial capacity of the pool. + */ +void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity); + +/** + * Return a pointer to the constant indicated by the given constant id. + * + * @param pool The pool to get the constant from. + * @param constant_id The id of the constant to get. + * @return A pointer to the constant. + */ +pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id); + +/** + * Find a constant in a constant pool. Returns the id of the constant, or 0 if + * the constant is not found. + * + * @param pool The pool to find the constant in. + * @param start A pointer to the start of the constant. + * @param length The length of the constant. + * @return The id of the constant. + */ +pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length); + +/** + * Insert a constant into a constant pool that is a slice of a source string. + * Returns the id of the constant, or 0 if any potential calls to resize fail. + * + * @param arena The arena to allocate from. + * @param pool The pool to insert the constant into. + * @param start A pointer to the start of the constant. + * @param length The length of the constant. + * @return The id of the constant. + */ +pm_constant_id_t pm_constant_pool_insert_shared(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); + +/** + * Insert a constant into a constant pool from memory that is now owned by the + * constant pool. Returns the id of the constant, or 0 if any potential calls to + * resize fail. + * + * @param arena The arena to allocate from. + * @param pool The pool to insert the constant into. + * @param start A pointer to the start of the constant. + * @param length The length of the constant. + * @return The id of the constant. + */ +pm_constant_id_t pm_constant_pool_insert_owned(pm_arena_t *arena, pm_constant_pool_t *pool, uint8_t *start, size_t length); + +/** + * Insert a constant into a constant pool from memory that is constant. Returns + * the id of the constant, or 0 if any potential calls to resize fail. + * + * @param arena The arena to allocate from. + * @param pool The pool to insert the constant into. + * @param start A pointer to the start of the constant. + * @param length The length of the constant. + * @return The id of the constant. + */ +pm_constant_id_t pm_constant_pool_insert_constant(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); + +#endif diff --git a/prism.gemspec b/prism.gemspec index 316d36ef22..644bf14e0a 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -75,6 +75,7 @@ Gem::Specification.new do |spec| "include/prism/internal/bit.h", "include/prism/internal/buffer.h", "include/prism/internal/char.h", + "include/prism/internal/constant_pool.h", "include/prism/internal/diagnostic.h", "include/prism/internal/integer.h", "include/prism/internal/line_offset_list.h", diff --git a/src/constant_pool.c b/src/constant_pool.c index 117b295d9b..106566df90 100644 --- a/src/constant_pool.c +++ b/src/constant_pool.c @@ -1,7 +1,11 @@ #include "prism/constant_pool.h" +#include "prism/attribute/align.h" #include "prism/internal/arena.h" +#include +#include + /** * Initialize a list of constant ids. */ diff --git a/src/prism.c b/src/prism.c index 8365b8bec2..49d5ce018e 100644 --- a/src/prism.c +++ b/src/prism.c @@ -4,6 +4,7 @@ #include "prism/internal/arena.h" #include "prism/internal/bit.h" #include "prism/internal/char.h" +#include "prism/internal/constant_pool.h" #include "prism/internal/diagnostic.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 30e2d6fc58..8f89c500f8 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -1,7 +1,9 @@ #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" -#include "prism/internal/integer.h" #include "prism/node.h" +#include "prism/internal/constant_pool.h" +#include "prism/internal/integer.h" + /** * Attempts to grow the node list to the next size. If there is already * capacity in the list, this function does nothing. Otherwise it allocates a diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index aefb092df2..60665faba6 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -1,7 +1,9 @@ <%# encoding: ASCII -%> +#include "prism/prettyprint.h" + #include "prism/internal/buffer.h" +#include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" -#include "prism/prettyprint.h" // We optionally support pretty printing nodes. For systems that don't want or // need this functionality, it can be turned off with the From b27fd8276d448be62c8399cfec5c2c255e08db57 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:14:37 -0400 Subject: [PATCH 166/289] Move strings out of util --- include/prism/defines.h | 24 +------------- include/prism/internal/files.h | 32 +++++++++++++++++++ include/prism/options.h | 2 +- include/prism/parser.h | 2 +- include/prism/regexp.h | 2 +- include/prism/{util/pm_string.h => strings.h} | 6 ++-- lib/prism/ffi.rb | 2 +- prism.gemspec | 6 ++-- src/{util/pm_string.c => strings.c} | 2 +- templates/include/prism/ast.h.erb | 2 +- 10 files changed, 45 insertions(+), 35 deletions(-) create mode 100644 include/prism/internal/files.h rename include/prism/{util/pm_string.h => strings.h} (98%) rename src/{util/pm_string.c => strings.c} (99%) diff --git a/include/prism/defines.h b/include/prism/defines.h index ad1cf2b75c..1bb6c47e86 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -19,6 +19,7 @@ #include "prism/allocator.h" #include "prism/internal/accel.h" #include "prism/internal/bit.h" +#include "prism/internal/files.h" #include #include @@ -81,29 +82,6 @@ # define PM_STATIC_ASSERT(line, condition, message) typedef char PM_CONCATENATE(static_assert_, line)[(condition) ? 1 : -1] #endif -/** - * In general, libc for embedded systems does not support memory-mapped files. - * If the target platform is POSIX or Windows, we can map a file in memory and - * read it in a more efficient manner. - */ -#ifdef _WIN32 -# define PRISM_HAS_MMAP -#else -# include -# ifdef _POSIX_MAPPED_FILES -# define PRISM_HAS_MMAP -# endif -#endif - -/** - * If PRISM_HAS_NO_FILESYSTEM is defined, then we want to exclude all filesystem - * related code from the library. All filesystem related code should be guarded - * by PRISM_HAS_FILESYSTEM. - */ -#ifndef PRISM_HAS_NO_FILESYSTEM -# define PRISM_HAS_FILESYSTEM -#endif - /** * isinf on POSIX systems it accepts a float, a double, or a long double. * But mingw didn't provide an isinf macro, only an isinf function that only diff --git a/include/prism/internal/files.h b/include/prism/internal/files.h new file mode 100644 index 0000000000..bb00ae4232 --- /dev/null +++ b/include/prism/internal/files.h @@ -0,0 +1,32 @@ +/** + * @file internal/files.h + * + * Platform detection for mmap and filesystem support. + */ +#ifndef PRISM_INTERNAL_FILES_H +#define PRISM_INTERNAL_FILES_H + +/** + * In general, libc for embedded systems does not support memory-mapped files. + * If the target platform is POSIX or Windows, we can map a file in memory and + * read it in a more efficient manner. + */ +#ifdef _WIN32 +# define PRISM_HAS_MMAP +#else +# include +# ifdef _POSIX_MAPPED_FILES +# define PRISM_HAS_MMAP +# endif +#endif + +/** + * If PRISM_HAS_NO_FILESYSTEM is defined, then we want to exclude all filesystem + * related code from the library. All filesystem related code should be guarded + * by PRISM_HAS_FILESYSTEM. + */ +#ifndef PRISM_HAS_NO_FILESYSTEM +# define PRISM_HAS_FILESYSTEM +#endif + +#endif diff --git a/include/prism/options.h b/include/prism/options.h index 41f3bc7f42..cf144f649c 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -7,7 +7,7 @@ #define PRISM_OPTIONS_H #include "prism/defines.h" -#include "prism/util/pm_string.h" +#include "prism/strings.h" #include #include diff --git a/include/prism/parser.h b/include/prism/parser.h index 312e8bd0cf..f6037c384c 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -14,8 +14,8 @@ #include "prism/line_offset_list.h" #include "prism/options.h" #include "prism/static_literals.h" +#include "prism/strings.h" #include "prism/util/pm_list.h" -#include "prism/util/pm_string.h" #include diff --git a/include/prism/regexp.h b/include/prism/regexp.h index 60a84b9838..9baafe6d36 100644 --- a/include/prism/regexp.h +++ b/include/prism/regexp.h @@ -10,7 +10,7 @@ #include "prism/parser.h" #include "prism/encoding.h" #include "prism/internal/memchr.h" -#include "prism/util/pm_string.h" +#include "prism/strings.h" #include #include diff --git a/include/prism/util/pm_string.h b/include/prism/strings.h similarity index 98% rename from include/prism/util/pm_string.h rename to include/prism/strings.h index 76942180b6..d3fdcf6983 100644 --- a/include/prism/util/pm_string.h +++ b/include/prism/strings.h @@ -1,10 +1,10 @@ /** - * @file pm_string.h + * @file strings.h * * A generic string type that can have various ownership semantics. */ -#ifndef PRISM_STRING_H -#define PRISM_STRING_H +#ifndef PRISM_STRINGS_H +#define PRISM_STRINGS_H #include "prism/defines.h" diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 72187fa490..eb8cf3f4ca 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -116,7 +116,7 @@ def self.load_exported_functions_from(header, *functions, callbacks) ) load_exported_functions_from( - "prism/util/pm_string.h", + "prism/strings.h", "pm_string_mapped_init", "pm_string_free", "pm_string_source", diff --git a/prism.gemspec b/prism.gemspec index 644bf14e0a..2c6d4ad9da 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -70,6 +70,7 @@ Gem::Specification.new do |spec| "include/prism/prettyprint.h", "include/prism/regexp.h", "include/prism/static_literals.h", + "include/prism/strings.h", "include/prism/internal/accel.h", "include/prism/internal/arena.h", "include/prism/internal/bit.h", @@ -83,7 +84,6 @@ Gem::Specification.new do |spec| "include/prism/internal/strncasecmp.h", "include/prism/internal/strpbrk.h", "include/prism/util/pm_list.h", - "include/prism/util/pm_string.h", "include/prism/version.h", "lib/prism.rb", "lib/prism/compiler.rb", @@ -189,11 +189,11 @@ Gem::Specification.new do |spec| "src/regexp.c", "src/serialize.c", "src/static_literals.c", + "src/strings.c", "src/strncasecmp.c", "src/strpbrk.c", "src/token_type.c", - "src/util/pm_list.c", - "src/util/pm_string.c" + "src/util/pm_list.c" ] spec.extensions = ["ext/prism/extconf.rb"] diff --git a/src/util/pm_string.c b/src/strings.c similarity index 99% rename from src/util/pm_string.c rename to src/strings.c index c2c85e1614..1f5220a0a6 100644 --- a/src/util/pm_string.c +++ b/src/strings.c @@ -1,4 +1,4 @@ -#include "prism/util/pm_string.h" +#include "prism/strings.h" static const uint8_t empty_source[] = ""; diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 48c757a0e6..783eaca2dd 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -10,8 +10,8 @@ #include "prism/defines.h" #include "prism/constant_pool.h" -#include "prism/util/pm_string.h" #include "prism/integer.h" +#include "prism/strings.h" #include #include From 60e105fc0c566c71dbb39f8dc7e3b0cacc701a8c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:25:21 -0400 Subject: [PATCH 167/289] Split up public and internal strings headers --- include/prism/defines.h | 5 ++- include/prism/{internal => }/files.h | 6 +-- include/prism/internal/strings.h | 55 +++++++++++++++++++++++ include/prism/strings.h | 67 +++------------------------- prism.gemspec | 2 + src/options.c | 4 ++ src/prism.c | 1 + src/regexp.c | 1 + src/static_literals.c | 7 ++- src/strings.c | 20 ++++++++- 10 files changed, 99 insertions(+), 69 deletions(-) rename include/prism/{internal => }/files.h (88%) create mode 100644 include/prism/internal/strings.h diff --git a/include/prism/defines.h b/include/prism/defines.h index 1bb6c47e86..04082e9c29 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -16,10 +16,11 @@ #include "prism/attribute/format.h" #include "prism/attribute/unused.h" -#include "prism/allocator.h" #include "prism/internal/accel.h" #include "prism/internal/bit.h" -#include "prism/internal/files.h" + +#include "prism/allocator.h" +#include "prism/files.h" #include #include diff --git a/include/prism/internal/files.h b/include/prism/files.h similarity index 88% rename from include/prism/internal/files.h rename to include/prism/files.h index bb00ae4232..8a74e03be8 100644 --- a/include/prism/internal/files.h +++ b/include/prism/files.h @@ -1,10 +1,10 @@ /** - * @file internal/files.h + * @file files.h * * Platform detection for mmap and filesystem support. */ -#ifndef PRISM_INTERNAL_FILES_H -#define PRISM_INTERNAL_FILES_H +#ifndef PRISM_FILES_H +#define PRISM_FILES_H /** * In general, libc for embedded systems does not support memory-mapped files. diff --git a/include/prism/internal/strings.h b/include/prism/internal/strings.h new file mode 100644 index 0000000000..f46aa86a81 --- /dev/null +++ b/include/prism/internal/strings.h @@ -0,0 +1,55 @@ +/** + * @file internal/strings.h + * + * A generic string type that can have various ownership semantics. + */ +#ifndef PRISM_INTERNAL_STRINGS_H +#define PRISM_INTERNAL_STRINGS_H + +#include "prism/strings.h" + +/** + * Defines an empty string. This is useful for initializing a string that will + * be filled in later. + */ +#define PM_STRING_EMPTY ((pm_string_t) { .type = PM_STRING_CONSTANT, .source = NULL, .length = 0 }) + +/** + * Initialize a shared string that is based on initial input. + * + * @param string The string to initialize. + * @param start The start of the string. + * @param end The end of the string. + */ +void pm_string_shared_init(pm_string_t *string, const uint8_t *start, const uint8_t *end); + +/** + * Initialize an owned string that is responsible for freeing allocated memory. + * + * @param string The string to initialize. + * @param source The source of the string. + * @param length The length of the string. + */ +void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length); + +/** + * Ensure the string is owned. If it is not, then reinitialize it as owned and + * copy over the previous source. + * + * @param string The string to ensure is owned. + */ +void pm_string_ensure_owned(pm_string_t *string); + +/** + * Compare the underlying lengths and bytes of two strings. Returns 0 if the + * strings are equal, a negative number if the left string is less than the + * right string, and a positive number if the left string is greater than the + * right string. + * + * @param left The left string to compare. + * @param right The right string to compare. + * @return The comparison result. + */ +int pm_string_compare(const pm_string_t *left, const pm_string_t *right); + +#endif diff --git a/include/prism/strings.h b/include/prism/strings.h index d3fdcf6983..da28b76940 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -6,26 +6,11 @@ #ifndef PRISM_STRINGS_H #define PRISM_STRINGS_H -#include "prism/defines.h" +#include "prism/attribute/exported.h" +#include "prism/files.h" -#include -#include -#include #include -#include -#include - -// The following headers are necessary to read files using demand paging. -#ifdef _WIN32 -#include -#elif defined(_POSIX_MAPPED_FILES) -#include -#include -#include -#elif defined(PRISM_HAS_FILESYSTEM) -#include -#include -#endif +#include /** * A generic string type that can have various ownership semantics. @@ -63,30 +48,6 @@ typedef struct { */ PRISM_EXPORTED_FUNCTION size_t pm_string_sizeof(void); -/** - * Defines an empty string. This is useful for initializing a string that will - * be filled in later. - */ -#define PM_STRING_EMPTY ((pm_string_t) { .type = PM_STRING_CONSTANT, .source = NULL, .length = 0 }) - -/** - * Initialize a shared string that is based on initial input. - * - * @param string The string to initialize. - * @param start The start of the string. - * @param end The end of the string. - */ -void pm_string_shared_init(pm_string_t *string, const uint8_t *start, const uint8_t *end); - -/** - * Initialize an owned string that is responsible for freeing allocated memory. - * - * @param string The string to initialize. - * @param source The source of the string. - * @param length The length of the string. - */ -void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length); - /** * Initialize a constant string that doesn't own its memory source. * @@ -105,11 +66,13 @@ PRISM_EXPORTED_FUNCTION void pm_string_constant_init(pm_string_t *string, const typedef enum { /** Indicates that the string was successfully initialized. */ PM_STRING_INIT_SUCCESS = 0, + /** * Indicates a generic error from a string_*_init function, where the type * of error should be read from `errno` or `GetLastError()`. */ PM_STRING_INIT_ERROR_GENERIC = 1, + /** * Indicates that the file that was attempted to be opened was a directory. */ @@ -148,26 +111,6 @@ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_ */ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath); -/** - * Ensure the string is owned. If it is not, then reinitialize it as owned and - * copy over the previous source. - * - * @param string The string to ensure is owned. - */ -void pm_string_ensure_owned(pm_string_t *string); - -/** - * Compare the underlying lengths and bytes of two strings. Returns 0 if the - * strings are equal, a negative number if the left string is less than the - * right string, and a positive number if the left string is greater than the - * right string. - * - * @param left The left string to compare. - * @param right The right string to compare. - * @return The comparison result. - */ -int pm_string_compare(const pm_string_t *left, const pm_string_t *right); - /** * Returns the length associated with the string. * diff --git a/prism.gemspec b/prism.gemspec index 2c6d4ad9da..dd644ba2c9 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -61,6 +61,7 @@ Gem::Specification.new do |spec| "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", + "include/prism/files.h", "include/prism/integer.h", "include/prism/line_offset_list.h", "include/prism/node.h", @@ -82,6 +83,7 @@ Gem::Specification.new do |spec| "include/prism/internal/line_offset_list.h", "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", + "include/prism/internal/strings.h", "include/prism/internal/strpbrk.h", "include/prism/util/pm_list.h", "include/prism/version.h", diff --git a/src/options.c b/src/options.c index c89515964c..42ea38ba83 100644 --- a/src/options.c +++ b/src/options.c @@ -1,5 +1,9 @@ #include "prism/options.h" + #include "prism/internal/char.h" +#include "prism/allocator.h" + +#include /** * Set the shebang callback option on the given options struct. diff --git a/src/prism.c b/src/prism.c index 49d5ce018e..9f6bc2f380 100644 --- a/src/prism.c +++ b/src/prism.c @@ -8,6 +8,7 @@ #include "prism/internal/diagnostic.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" +#include "prism/internal/strings.h" #include "prism/internal/strpbrk.h" #include "prism/node_new.h" diff --git a/src/regexp.c b/src/regexp.c index 9d8584ac17..3dfe826104 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -3,6 +3,7 @@ #include "prism/internal/buffer.h" #include "prism/internal/char.h" #include "prism/internal/diagnostic.h" +#include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" /** The maximum depth of nested groups allowed in a regular expression. */ diff --git a/src/static_literals.c b/src/static_literals.c index e6d66cd691..3323ea9e1b 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -1,6 +1,11 @@ +#include "prism/static_literals.h" + #include "prism/internal/buffer.h" #include "prism/internal/integer.h" -#include "prism/static_literals.h" +#include "prism/internal/strings.h" +#include "prism/allocator.h" + +#include /** * A small struct used for passing around a subset of the information that is diff --git a/src/strings.c b/src/strings.c index 1f5220a0a6..da7548112b 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1,4 +1,22 @@ -#include "prism/strings.h" +#include "prism/internal/strings.h" + +#include "prism/allocator.h" + +#include +#include +#include + +/* The following headers are necessary to read files using demand paging. */ +#ifdef _WIN32 +#include +#elif defined(_POSIX_MAPPED_FILES) +#include +#include +#include +#elif defined(PRISM_HAS_FILESYSTEM) +#include +#include +#endif static const uint8_t empty_source[] = ""; From c6610459c7d282d1fc4d4e2b65ed94100b258356 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:38:29 -0400 Subject: [PATCH 168/289] Move list out of utils --- include/prism/internal/diagnostic.h | 1 - include/prism/{util/pm_list.h => list.h} | 30 +-------------- include/prism/parser.h | 2 +- prism.gemspec | 6 +-- rust/ruby-prism-sys/build/main.rs | 2 - rust/ruby-prism-sys/tests/utils_tests.rs | 20 +--------- src/list.c | 24 ++++++++++++ src/util/pm_list.c | 49 ------------------------ templates/include/prism/diagnostic.h.erb | 11 +++++- templates/src/node.c.erb | 2 + 10 files changed, 43 insertions(+), 104 deletions(-) rename include/prism/{util/pm_list.h => list.h} (75%) create mode 100644 src/list.c delete mode 100644 src/util/pm_list.c diff --git a/include/prism/internal/diagnostic.h b/include/prism/internal/diagnostic.h index b06ab69124..edaaa33a14 100644 --- a/include/prism/internal/diagnostic.h +++ b/include/prism/internal/diagnostic.h @@ -8,7 +8,6 @@ #include "prism/diagnostic.h" #include "prism/arena.h" -#include "prism/util/pm_list.h" /** * Append a diagnostic to the given list of diagnostics that is using shared diff --git a/include/prism/util/pm_list.h b/include/prism/list.h similarity index 75% rename from include/prism/util/pm_list.h rename to include/prism/list.h index f544bb2943..ba9adfba0f 100644 --- a/include/prism/util/pm_list.h +++ b/include/prism/list.h @@ -1,17 +1,12 @@ /** - * @file pm_list.h + * @file list.h * * An abstract linked list. */ #ifndef PRISM_LIST_H #define PRISM_LIST_H -#include "prism/defines.h" - -#include #include -#include -#include /** * This struct represents an abstract linked list that provides common @@ -63,25 +58,13 @@ typedef struct { pm_list_node_t *tail; } pm_list_t; -/** - * Returns true if the given list is empty. - * - * @param list The list to check. - * @return True if the given list is empty, otherwise false. - * - * \public \memberof pm_list_t - */ -PRISM_EXPORTED_FUNCTION bool pm_list_empty_p(pm_list_t *list); - /** * Returns the size of the list. * * @param list The list to check. * @return The size of the list. - * - * \public \memberof pm_list_t */ -PRISM_EXPORTED_FUNCTION size_t pm_list_size(pm_list_t *list); +size_t pm_list_size(pm_list_t *list); /** * Append a node to the given list. @@ -91,13 +74,4 @@ PRISM_EXPORTED_FUNCTION size_t pm_list_size(pm_list_t *list); */ void pm_list_append(pm_list_t *list, pm_list_node_t *node); -/** - * Deallocate the internal state of the given list. - * - * @param list The list to free. - * - * \public \memberof pm_list_t - */ -PRISM_EXPORTED_FUNCTION void pm_list_free(pm_list_t *list); - #endif diff --git a/include/prism/parser.h b/include/prism/parser.h index f6037c384c..6a4a7cade4 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -12,10 +12,10 @@ #include "prism/constant_pool.h" #include "prism/encoding.h" #include "prism/line_offset_list.h" +#include "prism/list.h" #include "prism/options.h" #include "prism/static_literals.h" #include "prism/strings.h" -#include "prism/util/pm_list.h" #include diff --git a/prism.gemspec b/prism.gemspec index dd644ba2c9..3394bb6ce7 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -64,6 +64,7 @@ Gem::Specification.new do |spec| "include/prism/files.h", "include/prism/integer.h", "include/prism/line_offset_list.h", + "include/prism/list.h", "include/prism/node.h", "include/prism/node_new.h", "include/prism/options.h", @@ -85,7 +86,6 @@ Gem::Specification.new do |spec| "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", "include/prism/internal/strpbrk.h", - "include/prism/util/pm_list.h", "include/prism/version.h", "lib/prism.rb", "lib/prism/compiler.rb", @@ -183,6 +183,7 @@ Gem::Specification.new do |spec| "src/encoding.c", "src/integer.c", "src/line_offset_list.c", + "src/list.c", "src/memchr.c", "src/node.c", "src/options.c", @@ -194,8 +195,7 @@ Gem::Specification.new do |spec| "src/strings.c", "src/strncasecmp.c", "src/strpbrk.c", - "src/token_type.c", - "src/util/pm_list.c" + "src/token_type.c" ] spec.extensions = ["ext/prism/extconf.rb"] diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 50a8f51d6c..0de2b3caba 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -149,8 +149,6 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { // Functions .allowlist_function("pm_arena_free") .allowlist_function("pm_line_offset_list_line_column") - .allowlist_function("pm_list_empty_p") - .allowlist_function("pm_list_free") .allowlist_function("pm_options_command_line_set") .allowlist_function("pm_options_encoding_locked_set") .allowlist_function("pm_options_encoding_set") diff --git a/rust/ruby-prism-sys/tests/utils_tests.rs b/rust/ruby-prism-sys/tests/utils_tests.rs index 13de5e8761..2c42750dd9 100644 --- a/rust/ruby-prism-sys/tests/utils_tests.rs +++ b/rust/ruby-prism-sys/tests/utils_tests.rs @@ -1,7 +1,4 @@ -use std::{ - ffi::{CStr, CString}, - mem::MaybeUninit, -}; +use std::ffi::{CStr, CString}; #[test] fn version_test() { @@ -15,21 +12,6 @@ fn version_test() { assert_eq!(&cstring.to_string_lossy(), "1.9.0"); } -#[test] -fn list_test() { - use ruby_prism_sys::{pm_list_empty_p, pm_list_free, pm_list_t}; - - let mut list = MaybeUninit::::zeroed(); - - unsafe { - let list = list.assume_init_mut(); - - assert!(pm_list_empty_p(list)); - - pm_list_free(list); - } -} - mod string { use ruby_prism_sys::{ pm_string_free, pm_string_length, pm_string_source, pm_string_t, pm_string_t__bindgen_ty_1, PM_STRING_CONSTANT, diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000000..419fd8952a --- /dev/null +++ b/src/list.c @@ -0,0 +1,24 @@ +#include "prism/list.h" + +/** + * Returns the size of the list. + */ +size_t +pm_list_size(pm_list_t *list) { + return list->size; +} + +/** + * Append a node to the given list. + */ +void +pm_list_append(pm_list_t *list, pm_list_node_t *node) { + if (list->head == NULL) { + list->head = node; + } else { + list->tail->next = node; + } + + list->tail = node; + list->size++; +} diff --git a/src/util/pm_list.c b/src/util/pm_list.c deleted file mode 100644 index 48486d6cf9..0000000000 --- a/src/util/pm_list.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "prism/util/pm_list.h" - -/** - * Returns true if the given list is empty. - */ -bool -pm_list_empty_p(pm_list_t *list) { - return list->head == NULL; -} - -/** - * Returns the size of the list. - */ -size_t -pm_list_size(pm_list_t *list) { - return list->size; -} - -/** - * Append a node to the given list. - */ -void -pm_list_append(pm_list_t *list, pm_list_node_t *node) { - if (list->head == NULL) { - list->head = node; - } else { - list->tail->next = node; - } - - list->tail = node; - list->size++; -} - -/** - * Deallocate the internal state of the given list. - */ -void -pm_list_free(pm_list_t *list) { - pm_list_node_t *node = list->head; - pm_list_node_t *next; - - while (node != NULL) { - next = node->next; - xfree_sized(node, sizeof(pm_list_node_t)); - node = next; - } - - list->size = 0; -} diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb index 5560ea54e1..a3964cc40c 100644 --- a/templates/include/prism/diagnostic.h.erb +++ b/templates/include/prism/diagnostic.h.erb @@ -6,8 +6,9 @@ #ifndef PRISM_DIAGNOSTIC_H #define PRISM_DIAGNOSTIC_H +#include "prism/attribute/exported.h" #include "prism/ast.h" -#include "prism/util/pm_list.h" +#include "prism/list.h" /** * The diagnostic IDs of all of the diagnostics, used to communicate the types @@ -75,4 +76,12 @@ typedef enum { PM_WARNING_LEVEL_VERBOSE = 1 } pm_warning_level_t; +/** + * Get the human-readable name of the given diagnostic ID. + * + * @param diag_id The diagnostic ID to get the name of. + * @returns The human-readable name of the given diagnostic ID. + */ +PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_id_human(pm_diagnostic_id_t diag_id); + #endif diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 8f89c500f8..4e1b1cdaae 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -4,6 +4,8 @@ #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" +#include + /** * Attempts to grow the node list to the next size. If there is already * capacity in the list, this function does nothing. Otherwise it allocates a From 4149565d77d4173e81081ece839259d72fbb4451 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:39:34 -0400 Subject: [PATCH 169/289] Fully remove util dir --- .github/workflows/cpp-bindings.yml | 2 +- Doxyfile | 2 +- README.md | 1 - ext/prism/extconf.rb | 5 +---- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cpp-bindings.yml b/.github/workflows/cpp-bindings.yml index 2a53272c4b..5b1bfba795 100644 --- a/.github/workflows/cpp-bindings.yml +++ b/.github/workflows/cpp-bindings.yml @@ -29,6 +29,6 @@ jobs: - name: Compile prism run: bundle exec rake compile - name: Compile C++ - run: g++ -o ./cpp_test cpp/test.cpp build/static/*.o build/static/util/*.o -Iinclude + run: g++ -o ./cpp_test cpp/test.cpp build/static/*.o -Iinclude - name: Run C++ run: ./cpp_test diff --git a/Doxyfile b/Doxyfile index 4ea648ed7a..fca1e8c314 100644 --- a/Doxyfile +++ b/Doxyfile @@ -23,7 +23,7 @@ PROJECT_NAME = "Prism Ruby parser" OUTPUT_DIRECTORY = doc JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES -INPUT = src src/util include include/prism include/prism/util +INPUT = src include include/prism EXCLUDE = include/prism/debug_allocator.h HTML_OUTPUT = c SORT_MEMBER_DOCS = NO diff --git a/README.md b/README.md index e92ef7bfb3..0805698d93 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,6 @@ The repository contains the infrastructure for both a shared library (libprism) │ └── prism Sample code that uses the Ruby API for documentation purposes ├── sig RBS type signatures for the Ruby library ├── src -│   ├── util various utility files │   └── prism.c main entrypoint for the shared library ├── templates contains ERB templates generated by templates/template.rb │   └── template.rb generates code from the nodes and tokens configured by config.yml diff --git a/ext/prism/extconf.rb b/ext/prism/extconf.rb index ea7cfe963e..9283d62b47 100644 --- a/ext/prism/extconf.rb +++ b/ext/prism/extconf.rb @@ -118,10 +118,7 @@ def add_libprism_source(path) src_list path end -$srcs = src_list("$(srcdir)") + - add_libprism_source("$(srcdir)/../../src") + - add_libprism_source("$(srcdir)/../../src/util") - +$srcs = src_list("$(srcdir)") + add_libprism_source("$(srcdir)/../../src") $headers += Dir["#{$srcdir}/../../include/**/*.h"] # Finally, we'll create the `Makefile` that is going to be used to configure and From 2cd264f1cdef42f5837053f5d4b65e8f5f3adc63 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:42:06 -0400 Subject: [PATCH 170/289] Split up list public and internal headers --- include/prism/internal/list.h | 27 +++++++++++++++++++++++++++ include/prism/list.h | 16 ---------------- src/list.c | 2 +- src/prism.c | 1 + templates/src/diagnostic.c.erb | 2 ++ templates/src/serialize.c.erb | 2 ++ 6 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 include/prism/internal/list.h diff --git a/include/prism/internal/list.h b/include/prism/internal/list.h new file mode 100644 index 0000000000..f770b1dd2d --- /dev/null +++ b/include/prism/internal/list.h @@ -0,0 +1,27 @@ +/** + * @file internal/list.h + * + * An abstract linked list. + */ +#ifndef PRISM_INTERNAL_LIST_H +#define PRISM_INTERNAL_LIST_H + +#include "prism/list.h" + +/** + * Returns the size of the list. + * + * @param list The list to check. + * @return The size of the list. + */ +size_t pm_list_size(pm_list_t *list); + +/** + * Append a node to the given list. + * + * @param list The list to append to. + * @param node The node to append. + */ +void pm_list_append(pm_list_t *list, pm_list_node_t *node); + +#endif diff --git a/include/prism/list.h b/include/prism/list.h index ba9adfba0f..c9fb18278c 100644 --- a/include/prism/list.h +++ b/include/prism/list.h @@ -58,20 +58,4 @@ typedef struct { pm_list_node_t *tail; } pm_list_t; -/** - * Returns the size of the list. - * - * @param list The list to check. - * @return The size of the list. - */ -size_t pm_list_size(pm_list_t *list); - -/** - * Append a node to the given list. - * - * @param list The list to append to. - * @param node The node to append. - */ -void pm_list_append(pm_list_t *list, pm_list_node_t *node); - #endif diff --git a/src/list.c b/src/list.c index 419fd8952a..8d4cd1be94 100644 --- a/src/list.c +++ b/src/list.c @@ -1,4 +1,4 @@ -#include "prism/list.h" +#include "prism/internal/list.h" /** * Returns the size of the list. diff --git a/src/prism.c b/src/prism.c index 9f6bc2f380..46a5960179 100644 --- a/src/prism.c +++ b/src/prism.c @@ -8,6 +8,7 @@ #include "prism/internal/diagnostic.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" +#include "prism/internal/list.h" #include "prism/internal/strings.h" #include "prism/internal/strpbrk.h" diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 0d696772d5..80d8b5b261 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -1,5 +1,7 @@ #include "prism/diagnostic.h" + #include "prism/internal/arena.h" +#include "prism/internal/list.h" #define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %> diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index f6da95f031..bf00abb69d 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,5 +1,7 @@ #include "prism.h" +#include "prism/internal/list.h" + // We optionally support serializing to a binary string. For systems that don't // want or need this functionality, it can be turned off with the // PRISM_EXCLUDE_SERIALIZATION define. From f9f9cd55d27e543623222c1c210e2f678fb06b0c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:49:20 -0400 Subject: [PATCH 171/289] Split up encoding public and internal headers --- include/prism/encoding.h | 276 +---------------------------- include/prism/internal/encoding.h | 281 ++++++++++++++++++++++++++++++ include/prism/internal/memchr.h | 2 +- include/prism/regexp.h | 2 +- prism.gemspec | 4 +- src/encoding.c | 7 +- src/strpbrk.c | 1 + 7 files changed, 296 insertions(+), 277 deletions(-) create mode 100644 include/prism/internal/encoding.h diff --git a/include/prism/encoding.h b/include/prism/encoding.h index 99c2397bdc..a2061b65b6 100644 --- a/include/prism/encoding.h +++ b/include/prism/encoding.h @@ -6,278 +6,8 @@ #ifndef PRISM_ENCODING_H #define PRISM_ENCODING_H -#include "prism/defines.h" -#include "prism/internal/strncasecmp.h" - -#include -#include -#include -#include - -/** - * This struct defines the functions necessary to implement the encoding - * interface so we can determine how many bytes the subsequent character takes. - * Each callback should return the number of bytes, or 0 if the next bytes are - * invalid for the encoding and type. - */ -typedef struct { - /** - * Return the number of bytes that the next character takes if it is valid - * in the encoding. Does not read more than n bytes. It is assumed that n is - * at least 1. - */ - size_t (*char_width)(const uint8_t *b, ptrdiff_t n); - - /** - * Return the number of bytes that the next character takes if it is valid - * in the encoding and is alphabetical. Does not read more than n bytes. It - * is assumed that n is at least 1. - */ - size_t (*alpha_char)(const uint8_t *b, ptrdiff_t n); - - /** - * Return the number of bytes that the next character takes if it is valid - * in the encoding and is alphanumeric. Does not read more than n bytes. It - * is assumed that n is at least 1. - */ - size_t (*alnum_char)(const uint8_t *b, ptrdiff_t n); - - /** - * Return true if the next character is valid in the encoding and is an - * uppercase character. Does not read more than n bytes. It is assumed that - * n is at least 1. - */ - bool (*isupper_char)(const uint8_t *b, ptrdiff_t n); - - /** - * The name of the encoding. This should correspond to a value that can be - * passed to Encoding.find in Ruby. - */ - const char *name; - - /** - * Return true if the encoding is a multibyte encoding. - */ - bool multibyte; -} pm_encoding_t; - -/** - * All of the lookup tables use the first bit of each embedded byte to indicate - * whether the codepoint is alphabetical. - */ -#define PRISM_ENCODING_ALPHABETIC_BIT 1 << 0 - -/** - * All of the lookup tables use the second bit of each embedded byte to indicate - * whether the codepoint is alphanumeric. - */ -#define PRISM_ENCODING_ALPHANUMERIC_BIT 1 << 1 - -/** - * All of the lookup tables use the third bit of each embedded byte to indicate - * whether the codepoint is uppercase. - */ -#define PRISM_ENCODING_UPPERCASE_BIT 1 << 2 - -/** - * Return the size of the next character in the UTF-8 encoding. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns The number of bytes that the next character takes if it is valid in - * the encoding, or 0 if it is not. - */ -size_t pm_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n); - -/** - * Return the size of the next character in the UTF-8 encoding if it is an - * alphabetical character. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns The number of bytes that the next character takes if it is valid in - * the encoding, or 0 if it is not. - */ -size_t pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n); - -/** - * Return the size of the next character in the UTF-8 encoding if it is an - * alphanumeric character. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns The number of bytes that the next character takes if it is valid in - * the encoding, or 0 if it is not. - */ -size_t pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n); - -/** - * Return true if the next character in the UTF-8 encoding if it is an uppercase - * character. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns True if the next character is valid in the encoding and is an - * uppercase character, or false if it is not. - */ -bool pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n); - -/** - * This lookup table is referenced in both the UTF-8 encoding file and the - * parser directly in order to speed up the default encoding processing. It is - * used to indicate whether a character is alphabetical, alphanumeric, or - * uppercase in unicode mappings. - */ -extern const uint8_t pm_encoding_unicode_table[256]; - -/** - * These are all of the encodings that prism supports. - */ -typedef enum { - PM_ENCODING_UTF_8 = 0, - PM_ENCODING_US_ASCII, - PM_ENCODING_ASCII_8BIT, - PM_ENCODING_EUC_JP, - PM_ENCODING_WINDOWS_31J, - -// We optionally support excluding the full set of encodings to only support the -// minimum necessary to process Ruby code without encoding comments. -#ifndef PRISM_ENCODING_EXCLUDE_FULL - PM_ENCODING_BIG5, - PM_ENCODING_BIG5_HKSCS, - PM_ENCODING_BIG5_UAO, - PM_ENCODING_CESU_8, - PM_ENCODING_CP51932, - PM_ENCODING_CP850, - PM_ENCODING_CP852, - PM_ENCODING_CP855, - PM_ENCODING_CP949, - PM_ENCODING_CP950, - PM_ENCODING_CP951, - PM_ENCODING_EMACS_MULE, - PM_ENCODING_EUC_JP_MS, - PM_ENCODING_EUC_JIS_2004, - PM_ENCODING_EUC_KR, - PM_ENCODING_EUC_TW, - PM_ENCODING_GB12345, - PM_ENCODING_GB18030, - PM_ENCODING_GB1988, - PM_ENCODING_GB2312, - PM_ENCODING_GBK, - PM_ENCODING_IBM437, - PM_ENCODING_IBM720, - PM_ENCODING_IBM737, - PM_ENCODING_IBM775, - PM_ENCODING_IBM852, - PM_ENCODING_IBM855, - PM_ENCODING_IBM857, - PM_ENCODING_IBM860, - PM_ENCODING_IBM861, - PM_ENCODING_IBM862, - PM_ENCODING_IBM863, - PM_ENCODING_IBM864, - PM_ENCODING_IBM865, - PM_ENCODING_IBM866, - PM_ENCODING_IBM869, - PM_ENCODING_ISO_8859_1, - PM_ENCODING_ISO_8859_2, - PM_ENCODING_ISO_8859_3, - PM_ENCODING_ISO_8859_4, - PM_ENCODING_ISO_8859_5, - PM_ENCODING_ISO_8859_6, - PM_ENCODING_ISO_8859_7, - PM_ENCODING_ISO_8859_8, - PM_ENCODING_ISO_8859_9, - PM_ENCODING_ISO_8859_10, - PM_ENCODING_ISO_8859_11, - PM_ENCODING_ISO_8859_13, - PM_ENCODING_ISO_8859_14, - PM_ENCODING_ISO_8859_15, - PM_ENCODING_ISO_8859_16, - PM_ENCODING_KOI8_R, - PM_ENCODING_KOI8_U, - PM_ENCODING_MAC_CENT_EURO, - PM_ENCODING_MAC_CROATIAN, - PM_ENCODING_MAC_CYRILLIC, - PM_ENCODING_MAC_GREEK, - PM_ENCODING_MAC_ICELAND, - PM_ENCODING_MAC_JAPANESE, - PM_ENCODING_MAC_ROMAN, - PM_ENCODING_MAC_ROMANIA, - PM_ENCODING_MAC_THAI, - PM_ENCODING_MAC_TURKISH, - PM_ENCODING_MAC_UKRAINE, - PM_ENCODING_SHIFT_JIS, - PM_ENCODING_SJIS_DOCOMO, - PM_ENCODING_SJIS_KDDI, - PM_ENCODING_SJIS_SOFTBANK, - PM_ENCODING_STATELESS_ISO_2022_JP, - PM_ENCODING_STATELESS_ISO_2022_JP_KDDI, - PM_ENCODING_TIS_620, - PM_ENCODING_UTF8_MAC, - PM_ENCODING_UTF8_DOCOMO, - PM_ENCODING_UTF8_KDDI, - PM_ENCODING_UTF8_SOFTBANK, - PM_ENCODING_WINDOWS_1250, - PM_ENCODING_WINDOWS_1251, - PM_ENCODING_WINDOWS_1252, - PM_ENCODING_WINDOWS_1253, - PM_ENCODING_WINDOWS_1254, - PM_ENCODING_WINDOWS_1255, - PM_ENCODING_WINDOWS_1256, - PM_ENCODING_WINDOWS_1257, - PM_ENCODING_WINDOWS_1258, - PM_ENCODING_WINDOWS_874, -#endif - - PM_ENCODING_MAXIMUM -} pm_encoding_type_t; - -/** - * This is the table of all of the encodings that prism supports. - */ -extern const pm_encoding_t pm_encodings[PM_ENCODING_MAXIMUM]; - -/** - * This is the default UTF-8 encoding. We need a reference to it to quickly - * create parsers. - */ -#define PM_ENCODING_UTF_8_ENTRY (&pm_encodings[PM_ENCODING_UTF_8]) - -/** - * This is the US-ASCII encoding. We need a reference to it to be able to - * compare against it when a string is being created because it could possibly - * need to fall back to ASCII-8BIT. - */ -#define PM_ENCODING_US_ASCII_ENTRY (&pm_encodings[PM_ENCODING_US_ASCII]) - -/** - * This is the ASCII-8BIT encoding. We need a reference to it so that pm_strpbrk - * can compare against it because invalid multibyte characters are not a thing - * in this encoding. It is also needed for handling Regexp encoding flags. - */ -#define PM_ENCODING_ASCII_8BIT_ENTRY (&pm_encodings[PM_ENCODING_ASCII_8BIT]) - -/** - * This is the EUC-JP encoding. We need a reference to it to quickly process - * regular expression modifiers. - */ -#define PM_ENCODING_EUC_JP_ENTRY (&pm_encodings[PM_ENCODING_EUC_JP]) - -/** - * This is the Windows-31J encoding. We need a reference to it to quickly - * process regular expression modifiers. - */ -#define PM_ENCODING_WINDOWS_31J_ENTRY (&pm_encodings[PM_ENCODING_WINDOWS_31J]) - -/** - * Parse the given name of an encoding and return a pointer to the corresponding - * encoding struct if one can be found, otherwise return NULL. - * - * @param start A pointer to the first byte of the name. - * @param end A pointer to the last byte of the name. - * @returns A pointer to the encoding struct if one is found, otherwise NULL. - */ -const pm_encoding_t * pm_encoding_find(const uint8_t *start, const uint8_t *end); +/* The encoding that the parser uses to process the source code. An opaque + * struct that is defined in the implementation file. */ +typedef struct pm_encoding_t pm_encoding_t; #endif diff --git a/include/prism/internal/encoding.h b/include/prism/internal/encoding.h new file mode 100644 index 0000000000..a62c1fd548 --- /dev/null +++ b/include/prism/internal/encoding.h @@ -0,0 +1,281 @@ +/** + * @file internal/encoding.h + * + * The encoding interface and implementations used by the parser. + */ +#ifndef PRISM_INTERNAL_ENCODING_H +#define PRISM_INTERNAL_ENCODING_H + +#include "prism/encoding.h" + +#include +#include +#include + +/** + * This struct defines the functions necessary to implement the encoding + * interface so we can determine how many bytes the subsequent character takes. + * Each callback should return the number of bytes, or 0 if the next bytes are + * invalid for the encoding and type. + */ +struct pm_encoding_t { + /** + * Return the number of bytes that the next character takes if it is valid + * in the encoding. Does not read more than n bytes. It is assumed that n is + * at least 1. + */ + size_t (*char_width)(const uint8_t *b, ptrdiff_t n); + + /** + * Return the number of bytes that the next character takes if it is valid + * in the encoding and is alphabetical. Does not read more than n bytes. It + * is assumed that n is at least 1. + */ + size_t (*alpha_char)(const uint8_t *b, ptrdiff_t n); + + /** + * Return the number of bytes that the next character takes if it is valid + * in the encoding and is alphanumeric. Does not read more than n bytes. It + * is assumed that n is at least 1. + */ + size_t (*alnum_char)(const uint8_t *b, ptrdiff_t n); + + /** + * Return true if the next character is valid in the encoding and is an + * uppercase character. Does not read more than n bytes. It is assumed that + * n is at least 1. + */ + bool (*isupper_char)(const uint8_t *b, ptrdiff_t n); + + /** + * The name of the encoding. This should correspond to a value that can be + * passed to Encoding.find in Ruby. + */ + const char *name; + + /** + * Return true if the encoding is a multibyte encoding. + */ + bool multibyte; +}; + +/** + * All of the lookup tables use the first bit of each embedded byte to indicate + * whether the codepoint is alphabetical. + */ +#define PRISM_ENCODING_ALPHABETIC_BIT 1 << 0 + +/** + * All of the lookup tables use the second bit of each embedded byte to indicate + * whether the codepoint is alphanumeric. + */ +#define PRISM_ENCODING_ALPHANUMERIC_BIT 1 << 1 + +/** + * All of the lookup tables use the third bit of each embedded byte to indicate + * whether the codepoint is uppercase. + */ +#define PRISM_ENCODING_UPPERCASE_BIT 1 << 2 + +/** + * Return the size of the next character in the UTF-8 encoding. + * + * @param b The bytes to read. + * @param n The number of bytes that can be read. + * @returns The number of bytes that the next character takes if it is valid in + * the encoding, or 0 if it is not. + */ +size_t pm_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n); + +/** + * Return the size of the next character in the UTF-8 encoding if it is an + * alphabetical character. + * + * @param b The bytes to read. + * @param n The number of bytes that can be read. + * @returns The number of bytes that the next character takes if it is valid in + * the encoding, or 0 if it is not. + */ +size_t pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n); + +/** + * Return the size of the next character in the UTF-8 encoding if it is an + * alphanumeric character. + * + * @param b The bytes to read. + * @param n The number of bytes that can be read. + * @returns The number of bytes that the next character takes if it is valid in + * the encoding, or 0 if it is not. + */ +size_t pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n); + +/** + * Return true if the next character in the UTF-8 encoding if it is an uppercase + * character. + * + * @param b The bytes to read. + * @param n The number of bytes that can be read. + * @returns True if the next character is valid in the encoding and is an + * uppercase character, or false if it is not. + */ +bool pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n); + +/** + * This lookup table is referenced in both the UTF-8 encoding file and the + * parser directly in order to speed up the default encoding processing. It is + * used to indicate whether a character is alphabetical, alphanumeric, or + * uppercase in unicode mappings. + */ +extern const uint8_t pm_encoding_unicode_table[256]; + +/** + * These are all of the encodings that prism supports. + */ +typedef enum { + PM_ENCODING_UTF_8 = 0, + PM_ENCODING_US_ASCII, + PM_ENCODING_ASCII_8BIT, + PM_ENCODING_EUC_JP, + PM_ENCODING_WINDOWS_31J, + +// We optionally support excluding the full set of encodings to only support the +// minimum necessary to process Ruby code without encoding comments. +#ifndef PRISM_ENCODING_EXCLUDE_FULL + PM_ENCODING_BIG5, + PM_ENCODING_BIG5_HKSCS, + PM_ENCODING_BIG5_UAO, + PM_ENCODING_CESU_8, + PM_ENCODING_CP51932, + PM_ENCODING_CP850, + PM_ENCODING_CP852, + PM_ENCODING_CP855, + PM_ENCODING_CP949, + PM_ENCODING_CP950, + PM_ENCODING_CP951, + PM_ENCODING_EMACS_MULE, + PM_ENCODING_EUC_JP_MS, + PM_ENCODING_EUC_JIS_2004, + PM_ENCODING_EUC_KR, + PM_ENCODING_EUC_TW, + PM_ENCODING_GB12345, + PM_ENCODING_GB18030, + PM_ENCODING_GB1988, + PM_ENCODING_GB2312, + PM_ENCODING_GBK, + PM_ENCODING_IBM437, + PM_ENCODING_IBM720, + PM_ENCODING_IBM737, + PM_ENCODING_IBM775, + PM_ENCODING_IBM852, + PM_ENCODING_IBM855, + PM_ENCODING_IBM857, + PM_ENCODING_IBM860, + PM_ENCODING_IBM861, + PM_ENCODING_IBM862, + PM_ENCODING_IBM863, + PM_ENCODING_IBM864, + PM_ENCODING_IBM865, + PM_ENCODING_IBM866, + PM_ENCODING_IBM869, + PM_ENCODING_ISO_8859_1, + PM_ENCODING_ISO_8859_2, + PM_ENCODING_ISO_8859_3, + PM_ENCODING_ISO_8859_4, + PM_ENCODING_ISO_8859_5, + PM_ENCODING_ISO_8859_6, + PM_ENCODING_ISO_8859_7, + PM_ENCODING_ISO_8859_8, + PM_ENCODING_ISO_8859_9, + PM_ENCODING_ISO_8859_10, + PM_ENCODING_ISO_8859_11, + PM_ENCODING_ISO_8859_13, + PM_ENCODING_ISO_8859_14, + PM_ENCODING_ISO_8859_15, + PM_ENCODING_ISO_8859_16, + PM_ENCODING_KOI8_R, + PM_ENCODING_KOI8_U, + PM_ENCODING_MAC_CENT_EURO, + PM_ENCODING_MAC_CROATIAN, + PM_ENCODING_MAC_CYRILLIC, + PM_ENCODING_MAC_GREEK, + PM_ENCODING_MAC_ICELAND, + PM_ENCODING_MAC_JAPANESE, + PM_ENCODING_MAC_ROMAN, + PM_ENCODING_MAC_ROMANIA, + PM_ENCODING_MAC_THAI, + PM_ENCODING_MAC_TURKISH, + PM_ENCODING_MAC_UKRAINE, + PM_ENCODING_SHIFT_JIS, + PM_ENCODING_SJIS_DOCOMO, + PM_ENCODING_SJIS_KDDI, + PM_ENCODING_SJIS_SOFTBANK, + PM_ENCODING_STATELESS_ISO_2022_JP, + PM_ENCODING_STATELESS_ISO_2022_JP_KDDI, + PM_ENCODING_TIS_620, + PM_ENCODING_UTF8_MAC, + PM_ENCODING_UTF8_DOCOMO, + PM_ENCODING_UTF8_KDDI, + PM_ENCODING_UTF8_SOFTBANK, + PM_ENCODING_WINDOWS_1250, + PM_ENCODING_WINDOWS_1251, + PM_ENCODING_WINDOWS_1252, + PM_ENCODING_WINDOWS_1253, + PM_ENCODING_WINDOWS_1254, + PM_ENCODING_WINDOWS_1255, + PM_ENCODING_WINDOWS_1256, + PM_ENCODING_WINDOWS_1257, + PM_ENCODING_WINDOWS_1258, + PM_ENCODING_WINDOWS_874, +#endif + + PM_ENCODING_MAXIMUM +} pm_encoding_type_t; + +/** + * This is the table of all of the encodings that prism supports. + */ +extern const pm_encoding_t pm_encodings[PM_ENCODING_MAXIMUM]; + +/** + * This is the default UTF-8 encoding. We need a reference to it to quickly + * create parsers. + */ +#define PM_ENCODING_UTF_8_ENTRY (&pm_encodings[PM_ENCODING_UTF_8]) + +/** + * This is the US-ASCII encoding. We need a reference to it to be able to + * compare against it when a string is being created because it could possibly + * need to fall back to ASCII-8BIT. + */ +#define PM_ENCODING_US_ASCII_ENTRY (&pm_encodings[PM_ENCODING_US_ASCII]) + +/** + * This is the ASCII-8BIT encoding. We need a reference to it so that pm_strpbrk + * can compare against it because invalid multibyte characters are not a thing + * in this encoding. It is also needed for handling Regexp encoding flags. + */ +#define PM_ENCODING_ASCII_8BIT_ENTRY (&pm_encodings[PM_ENCODING_ASCII_8BIT]) + +/** + * This is the EUC-JP encoding. We need a reference to it to quickly process + * regular expression modifiers. + */ +#define PM_ENCODING_EUC_JP_ENTRY (&pm_encodings[PM_ENCODING_EUC_JP]) + +/** + * This is the Windows-31J encoding. We need a reference to it to quickly + * process regular expression modifiers. + */ +#define PM_ENCODING_WINDOWS_31J_ENTRY (&pm_encodings[PM_ENCODING_WINDOWS_31J]) + +/** + * Parse the given name of an encoding and return a pointer to the corresponding + * encoding struct if one can be found, otherwise return NULL. + * + * @param start A pointer to the first byte of the name. + * @param end A pointer to the last byte of the name. + * @returns A pointer to the encoding struct if one is found, otherwise NULL. + */ +const pm_encoding_t * pm_encoding_find(const uint8_t *start, const uint8_t *end); + +#endif diff --git a/include/prism/internal/memchr.h b/include/prism/internal/memchr.h index 7277971681..905e3f33a1 100644 --- a/include/prism/internal/memchr.h +++ b/include/prism/internal/memchr.h @@ -6,7 +6,7 @@ #ifndef PRISM_INTERNAL_MEMCHR_H #define PRISM_INTERNAL_MEMCHR_H -#include "prism/encoding.h" +#include "prism/internal/encoding.h" #include diff --git a/include/prism/regexp.h b/include/prism/regexp.h index 9baafe6d36..17f0e03019 100644 --- a/include/prism/regexp.h +++ b/include/prism/regexp.h @@ -8,7 +8,7 @@ #include "prism/defines.h" #include "prism/parser.h" -#include "prism/encoding.h" +#include "prism/internal/encoding.h" #include "prism/internal/memchr.h" #include "prism/strings.h" diff --git a/prism.gemspec b/prism.gemspec index 3394bb6ce7..4712a86430 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -73,6 +73,7 @@ Gem::Specification.new do |spec| "include/prism/regexp.h", "include/prism/static_literals.h", "include/prism/strings.h", + "include/prism/version.h", "include/prism/internal/accel.h", "include/prism/internal/arena.h", "include/prism/internal/bit.h", @@ -80,13 +81,14 @@ Gem::Specification.new do |spec| "include/prism/internal/char.h", "include/prism/internal/constant_pool.h", "include/prism/internal/diagnostic.h", + "include/prism/internal/encoding.h", "include/prism/internal/integer.h", "include/prism/internal/line_offset_list.h", + "include/prism/internal/list.h", "include/prism/internal/memchr.h", "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", "include/prism/internal/strpbrk.h", - "include/prism/version.h", "lib/prism.rb", "lib/prism/compiler.rb", "lib/prism/desugar_compiler.rb", diff --git a/src/encoding.c b/src/encoding.c index d7e5616840..f43d0fd079 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -1,4 +1,9 @@ -#include "prism/encoding.h" +#include "prism/internal/encoding.h" + +#include "prism/attribute/unused.h" +#include "prism/internal/strncasecmp.h" + +#include typedef uint32_t pm_unicode_codepoint_t; diff --git a/src/strpbrk.c b/src/strpbrk.c index fe7a1ab67b..9b28a680c9 100644 --- a/src/strpbrk.c +++ b/src/strpbrk.c @@ -4,6 +4,7 @@ #include "prism/internal/accel.h" #include "prism/internal/bit.h" #include "prism/internal/diagnostic.h" +#include "prism/internal/encoding.h" #include #include From d2ec3620fa18cb662a9bc8dab9b45abacdae5a7d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 11:56:58 -0400 Subject: [PATCH 172/289] Split up static literals public and internal --- include/prism.h | 5 +- include/prism/internal/static_literals.h | 122 +++++++++++++++++++++++ include/prism/parser.h | 1 + include/prism/static_literals.h | 116 +-------------------- prism.gemspec | 1 + src/prism.c | 2 + src/static_literals.c | 2 +- 7 files changed, 130 insertions(+), 119 deletions(-) create mode 100644 include/prism/internal/static_literals.h diff --git a/include/prism.h b/include/prism.h index 3627c459a8..df7d49af29 100644 --- a/include/prism.h +++ b/include/prism.h @@ -11,9 +11,7 @@ extern "C" { #endif #include "prism/defines.h" -#include "prism/internal/buffer.h" -#include "prism/internal/memchr.h" -#include "prism/internal/strncasecmp.h" + #include "prism/arena.h" #include "prism/ast.h" #include "prism/diagnostic.h" @@ -22,7 +20,6 @@ extern "C" { #include "prism/parser.h" #include "prism/prettyprint.h" #include "prism/regexp.h" -#include "prism/static_literals.h" #include "prism/version.h" #include diff --git a/include/prism/internal/static_literals.h b/include/prism/internal/static_literals.h new file mode 100644 index 0000000000..0adde85780 --- /dev/null +++ b/include/prism/internal/static_literals.h @@ -0,0 +1,122 @@ +/** + * @file internal/static_literals.h + * + * A set of static literal nodes that can be checked for duplicates. + */ +#ifndef PRISM_INTERNAL_STATIC_LITERALS_H +#define PRISM_INTERNAL_STATIC_LITERALS_H + +#include "prism/static_literals.h" + +#include "prism/ast.h" +#include "prism/buffer.h" +#include "prism/line_offset_list.h" + +/** + * An internal hash table for a set of nodes. + */ +typedef struct { + /** The array of nodes in the hash table. */ + pm_node_t **nodes; + + /** The size of the hash table. */ + uint32_t size; + + /** The space that has been allocated in the hash table. */ + uint32_t capacity; +} pm_node_hash_t; + +/** + * Certain sets of nodes (hash keys and when clauses) check for duplicate nodes + * to alert the user of potential issues. To do this, we keep a set of the nodes + * that have been seen so far, and compare whenever we find a new node. + * + * We bucket the nodes based on their type to minimize the number of comparisons + * that need to be performed. + */ +struct pm_static_literals_t { + /** + * This is the set of IntegerNode and SourceLineNode instances. + */ + pm_node_hash_t integer_nodes; + + /** + * This is the set of FloatNode instances. + */ + pm_node_hash_t float_nodes; + + /** + * This is the set of RationalNode and ImaginaryNode instances. + */ + pm_node_hash_t number_nodes; + + /** + * This is the set of StringNode and SourceFileNode instances. + */ + pm_node_hash_t string_nodes; + + /** + * This is the set of RegularExpressionNode instances. + */ + pm_node_hash_t regexp_nodes; + + /** + * This is the set of SymbolNode instances. + */ + pm_node_hash_t symbol_nodes; + + /** + * A pointer to the last TrueNode instance that was inserted, or NULL. + */ + pm_node_t *true_node; + + /** + * A pointer to the last FalseNode instance that was inserted, or NULL. + */ + pm_node_t *false_node; + + /** + * A pointer to the last NilNode instance that was inserted, or NULL. + */ + pm_node_t *nil_node; + + /** + * A pointer to the last SourceEncodingNode instance that was inserted, or + * NULL. + */ + pm_node_t *source_encoding_node; +}; + +/** + * Add a node to the set of static literals. + * + * @param line_offsets The list of newline offsets to use to calculate lines. + * @param start The start of the source being parsed. + * @param start_line The line number that the parser starts on. + * @param literals The set of static literals to add the node to. + * @param node The node to add to the set. + * @param replace Whether to replace the previous node if one already exists. + * @return A pointer to the node that is being overwritten, if there is one. + */ +pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); + +/** + * Free the internal memory associated with the given static literals set. + * + * @param literals The set of static literals to free. + */ +void pm_static_literals_free(pm_static_literals_t *literals); + +/** + * Create a string-based representation of the given static literal. + * + * @param buffer The buffer to write the string to. + * @param line_offsets The list of newline offsets to use to calculate lines. + * @param start The start of the source being parsed. + * @param start_line The line number that the parser starts on. + * @param encoding_name The name of the encoding of the source being parsed. + * @param node The node to create a string representation of. + */ +void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); + +#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index 6a4a7cade4..0a0b142952 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -7,6 +7,7 @@ #define PRISM_PARSER_H #include "prism/defines.h" + #include "prism/arena.h" #include "prism/ast.h" #include "prism/constant_pool.h" diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h index cdb00e6a83..4519510280 100644 --- a/include/prism/static_literals.h +++ b/include/prism/static_literals.h @@ -6,119 +6,7 @@ #ifndef PRISM_STATIC_LITERALS_H #define PRISM_STATIC_LITERALS_H -#include "prism/defines.h" -#include "prism/ast.h" -#include "prism/buffer.h" -#include "prism/line_offset_list.h" - -#include -#include - -/** - * An internal hash table for a set of nodes. - */ -typedef struct { - /** The array of nodes in the hash table. */ - pm_node_t **nodes; - - /** The size of the hash table. */ - uint32_t size; - - /** The space that has been allocated in the hash table. */ - uint32_t capacity; -} pm_node_hash_t; - -/** - * Certain sets of nodes (hash keys and when clauses) check for duplicate nodes - * to alert the user of potential issues. To do this, we keep a set of the nodes - * that have been seen so far, and compare whenever we find a new node. - * - * We bucket the nodes based on their type to minimize the number of comparisons - * that need to be performed. - */ -typedef struct { - /** - * This is the set of IntegerNode and SourceLineNode instances. - */ - pm_node_hash_t integer_nodes; - - /** - * This is the set of FloatNode instances. - */ - pm_node_hash_t float_nodes; - - /** - * This is the set of RationalNode and ImaginaryNode instances. - */ - pm_node_hash_t number_nodes; - - /** - * This is the set of StringNode and SourceFileNode instances. - */ - pm_node_hash_t string_nodes; - - /** - * This is the set of RegularExpressionNode instances. - */ - pm_node_hash_t regexp_nodes; - - /** - * This is the set of SymbolNode instances. - */ - pm_node_hash_t symbol_nodes; - - /** - * A pointer to the last TrueNode instance that was inserted, or NULL. - */ - pm_node_t *true_node; - - /** - * A pointer to the last FalseNode instance that was inserted, or NULL. - */ - pm_node_t *false_node; - - /** - * A pointer to the last NilNode instance that was inserted, or NULL. - */ - pm_node_t *nil_node; - - /** - * A pointer to the last SourceEncodingNode instance that was inserted, or - * NULL. - */ - pm_node_t *source_encoding_node; -} pm_static_literals_t; - -/** - * Add a node to the set of static literals. - * - * @param line_offsets The list of newline offsets to use to calculate lines. - * @param start The start of the source being parsed. - * @param start_line The line number that the parser starts on. - * @param literals The set of static literals to add the node to. - * @param node The node to add to the set. - * @param replace Whether to replace the previous node if one already exists. - * @return A pointer to the node that is being overwritten, if there is one. - */ -pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); - -/** - * Free the internal memory associated with the given static literals set. - * - * @param literals The set of static literals to free. - */ -void pm_static_literals_free(pm_static_literals_t *literals); - -/** - * Create a string-based representation of the given static literal. - * - * @param buffer The buffer to write the string to. - * @param line_offsets The list of newline offsets to use to calculate lines. - * @param start The start of the source being parsed. - * @param start_line The line number that the parser starts on. - * @param encoding_name The name of the encoding of the source being parsed. - * @param node The node to create a string representation of. - */ -void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); +/** An opaque struct that holds the static literals. */ +typedef struct pm_static_literals_t pm_static_literals_t; #endif diff --git a/prism.gemspec b/prism.gemspec index 4712a86430..bd5d1ec1dd 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -86,6 +86,7 @@ Gem::Specification.new do |spec| "include/prism/internal/line_offset_list.h", "include/prism/internal/list.h", "include/prism/internal/memchr.h", + "include/prism/internal/static_literals.h", "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", "include/prism/internal/strpbrk.h", diff --git a/src/prism.c b/src/prism.c index 46a5960179..2162eea1de 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9,7 +9,9 @@ #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/list.h" +#include "prism/internal/static_literals.h" #include "prism/internal/strings.h" +#include "prism/internal/strncasecmp.h" #include "prism/internal/strpbrk.h" #include "prism/node_new.h" diff --git a/src/static_literals.c b/src/static_literals.c index 3323ea9e1b..9023f7fff9 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -1,4 +1,4 @@ -#include "prism/static_literals.h" +#include "prism/internal/static_literals.h" #include "prism/internal/buffer.h" #include "prism/internal/integer.h" From abd0a833be47af4a7a2237f3187d238c4dfd5f70 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 12:01:09 -0400 Subject: [PATCH 173/289] Split up public/internal options --- include/prism/internal/options.h | 83 ++++++++++++++++++++++++++++++++ include/prism/options.h | 76 +---------------------------- prism.gemspec | 1 + src/options.c | 1 + src/prism.c | 1 + templates/src/serialize.c.erb | 1 + 6 files changed, 88 insertions(+), 75 deletions(-) create mode 100644 include/prism/internal/options.h diff --git a/include/prism/internal/options.h b/include/prism/internal/options.h new file mode 100644 index 0000000000..e3fb0a9e5e --- /dev/null +++ b/include/prism/internal/options.h @@ -0,0 +1,83 @@ +/** + * @file internal/options.h + * + * The options that can be passed to parsing. + */ +#ifndef PRISM_INTERNAL_OPTIONS_H +#define PRISM_INTERNAL_OPTIONS_H + +#include "prism/options.h" + +/** + * Deserialize an options struct from the given binary string. This is used to + * pass options to the parser from an FFI call so that consumers of the library + * from an FFI perspective don't have to worry about the structure of our + * options structs. Since the source of these calls will be from Ruby + * implementation internals we assume it is from a trusted source. + * + * `data` is assumed to be a valid pointer pointing to well-formed data. The + * layout of this data should be the same every time, and is described below: + * + * | # bytes | field | + * | ------- | -------------------------- | + * | `4` | the length of the filepath | + * | ... | the filepath bytes | + * | `4` | the line number | + * | `4` | the length the encoding | + * | ... | the encoding bytes | + * | `1` | frozen string literal | + * | `1` | -p command line option | + * | `1` | -n command line option | + * | `1` | -l command line option | + * | `1` | -a command line option | + * | `1` | the version | + * | `1` | encoding locked | + * | `1` | main script | + * | `1` | partial script | + * | `1` | freeze | + * | `4` | the number of scopes | + * | ... | the scopes | + * + * The version field is an enum, so it should be one of the following values: + * + * | value | version | + * | ----- | ------------------------- | + * | `0` | use the latest version of prism | + * | `1` | use the version of prism that is vendored in CRuby 3.3.0 | + * | `2` | use the version of prism that is vendored in CRuby 3.4.0 | + * | `3` | use the version of prism that is vendored in CRuby 4.0.0 | + * | `4` | use the version of prism that is vendored in CRuby 4.1.0 | + * + * Each scope is laid out as follows: + * + * | # bytes | field | + * | ------- | -------------------------- | + * | `4` | the number of locals | + * | `1` | the forwarding flags | + * | ... | the locals | + * + * Each local is laid out as follows: + * + * | # bytes | field | + * | ------- | -------------------------- | + * | `4` | the length of the local | + * | ... | the local bytes | + * + * Some additional things to note about this layout: + * + * * The filepath can have a length of 0, in which case we'll consider it an + * empty string. + * * The line number should be 0-indexed. + * * The encoding can have a length of 0, in which case we'll use the default + * encoding (UTF-8). If it's not 0, it should correspond to a name of an + * encoding that can be passed to `Encoding.find` in Ruby. + * * The frozen string literal, encoding locked, main script, and partial script + * fields are booleans, so their values should be either 0 or 1. + * * The number of scopes can be 0. + * + * @param options The options struct to deserialize into. + * @param data The binary string to deserialize from. + */ +void pm_options_read(pm_options_t *options, const char *data); + +#endif diff --git a/include/prism/options.h b/include/prism/options.h index cf144f649c..4c8728c69a 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -6,12 +6,10 @@ #ifndef PRISM_OPTIONS_H #define PRISM_OPTIONS_H -#include "prism/defines.h" #include "prism/strings.h" #include #include -#include /** * String literals should be made frozen. @@ -58,7 +56,7 @@ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_BLOCK = 0x4; /** When the scope is fowarding with the ... parameter. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_ALL = 0x8; -// Forward declaration needed by the callback typedef. +/* Forward declaration needed by the callback typedef. */ struct pm_options; /** @@ -418,76 +416,4 @@ PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t */ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); -/** - * Deserialize an options struct from the given binary string. This is used to - * pass options to the parser from an FFI call so that consumers of the library - * from an FFI perspective don't have to worry about the structure of our - * options structs. Since the source of these calls will be from Ruby - * implementation internals we assume it is from a trusted source. - * - * `data` is assumed to be a valid pointer pointing to well-formed data. The - * layout of this data should be the same every time, and is described below: - * - * | # bytes | field | - * | ------- | -------------------------- | - * | `4` | the length of the filepath | - * | ... | the filepath bytes | - * | `4` | the line number | - * | `4` | the length the encoding | - * | ... | the encoding bytes | - * | `1` | frozen string literal | - * | `1` | -p command line option | - * | `1` | -n command line option | - * | `1` | -l command line option | - * | `1` | -a command line option | - * | `1` | the version | - * | `1` | encoding locked | - * | `1` | main script | - * | `1` | partial script | - * | `1` | freeze | - * | `4` | the number of scopes | - * | ... | the scopes | - * - * The version field is an enum, so it should be one of the following values: - * - * | value | version | - * | ----- | ------------------------- | - * | `0` | use the latest version of prism | - * | `1` | use the version of prism that is vendored in CRuby 3.3.0 | - * | `2` | use the version of prism that is vendored in CRuby 3.4.0 | - * | `3` | use the version of prism that is vendored in CRuby 4.0.0 | - * | `4` | use the version of prism that is vendored in CRuby 4.1.0 | - * - * Each scope is laid out as follows: - * - * | # bytes | field | - * | ------- | -------------------------- | - * | `4` | the number of locals | - * | `1` | the forwarding flags | - * | ... | the locals | - * - * Each local is laid out as follows: - * - * | # bytes | field | - * | ------- | -------------------------- | - * | `4` | the length of the local | - * | ... | the local bytes | - * - * Some additional things to note about this layout: - * - * * The filepath can have a length of 0, in which case we'll consider it an - * empty string. - * * The line number should be 0-indexed. - * * The encoding can have a length of 0, in which case we'll use the default - * encoding (UTF-8). If it's not 0, it should correspond to a name of an - * encoding that can be passed to `Encoding.find` in Ruby. - * * The frozen string literal, encoding locked, main script, and partial script - * fields are booleans, so their values should be either 0 or 1. - * * The number of scopes can be 0. - * - * @param options The options struct to deserialize into. - * @param data The binary string to deserialize from. - */ -void pm_options_read(pm_options_t *options, const char *data); - #endif diff --git a/prism.gemspec b/prism.gemspec index bd5d1ec1dd..3941e21077 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -86,6 +86,7 @@ Gem::Specification.new do |spec| "include/prism/internal/line_offset_list.h", "include/prism/internal/list.h", "include/prism/internal/memchr.h", + "include/prism/internal/options.h", "include/prism/internal/static_literals.h", "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", diff --git a/src/options.c b/src/options.c index 42ea38ba83..26df07fca3 100644 --- a/src/options.c +++ b/src/options.c @@ -4,6 +4,7 @@ #include "prism/allocator.h" #include +#include /** * Set the shebang callback option on the given options struct. diff --git a/src/prism.c b/src/prism.c index 2162eea1de..0e24aff7d6 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9,6 +9,7 @@ #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/list.h" +#include "prism/internal/options.h" #include "prism/internal/static_literals.h" #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index bf00abb69d..d2ef80b3c4 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,6 +1,7 @@ #include "prism.h" #include "prism/internal/list.h" +#include "prism/internal/options.h" // We optionally support serializing to a binary string. For systems that don't // want or need this functionality, it can be turned off with the From cc93903d080e538b33acb8628f97edbd6aa036ee Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 12:31:46 -0400 Subject: [PATCH 174/289] Put inline in its own header --- include/prism/attribute/force_inline.h | 4 +- include/prism/attribute/inline.h | 31 +++ include/prism/defines.h | 18 +- include/prism/internal/arena.h | 5 +- include/prism/internal/bit.h | 6 +- include/prism/internal/line_offset_list.h | 1 + prism.gemspec | 1 + src/buffer.c | 6 +- src/char.c | 10 +- src/constant_pool.c | 7 +- src/options.c | 3 +- src/prism.c | 288 +++++++++++----------- src/regexp.c | 15 +- src/static_literals.c | 5 +- src/strncasecmp.c | 4 +- src/strpbrk.c | 23 +- templates/include/prism/node_new.h.erb | 4 +- templates/src/diagnostic.c.erb | 5 +- templates/src/prettyprint.c.erb | 5 +- templates/src/serialize.c.erb | 5 +- 20 files changed, 242 insertions(+), 204 deletions(-) create mode 100644 include/prism/attribute/inline.h diff --git a/include/prism/attribute/force_inline.h b/include/prism/attribute/force_inline.h index 1d2c494d6e..7f1e8c57f8 100644 --- a/include/prism/attribute/force_inline.h +++ b/include/prism/attribute/force_inline.h @@ -6,6 +6,8 @@ #ifndef PRISM_FORCE_INLINE_H #define PRISM_FORCE_INLINE_H +#include "prism/attribute/inline.h" + /** * Force a function to be inlined at every call site. Use sparingly — only for * small, hot functions where the compiler's heuristics fail to inline. @@ -15,7 +17,7 @@ #elif defined(__GNUC__) || defined(__clang__) # define PRISM_FORCE_INLINE inline __attribute__((always_inline)) #else -# define PRISM_FORCE_INLINE inline +# define PRISM_FORCE_INLINE PRISM_INLINE #endif #endif diff --git a/include/prism/attribute/inline.h b/include/prism/attribute/inline.h new file mode 100644 index 0000000000..79a5dfcbee --- /dev/null +++ b/include/prism/attribute/inline.h @@ -0,0 +1,31 @@ +/** + * @file attribute/inline.h + * + * Macro definitions for forcing a function to be inlined at every call site. + */ +#ifndef PRISM_INLINE_H +#define PRISM_INLINE_H + +/** + * Old Visual Studio versions do not support the inline keyword, so we need to + * define it to be __inline. + */ +#if defined(_MSC_VER) && !defined(inline) +# define PRISM_INLINE __inline +#else +# define PRISM_INLINE inline +#endif + +/** + * Force a function to be inlined at every call site. Use sparingly — only for + * small, hot functions where the compiler's heuristics fail to inline. + */ +#if defined(_MSC_VER) +# define PRISM_FORCE_INLINE __forceinline +#elif defined(__GNUC__) || defined(__clang__) +# define PRISM_FORCE_INLINE inline __attribute__((always_inline)) +#else +# define PRISM_FORCE_INLINE PRISM_INLINE +#endif + +#endif diff --git a/include/prism/defines.h b/include/prism/defines.h index 04082e9c29..0d997f9c9b 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -12,8 +12,8 @@ #include "prism/attribute/align.h" #include "prism/attribute/exported.h" #include "prism/attribute/flex_array.h" -#include "prism/attribute/force_inline.h" #include "prism/attribute/format.h" +#include "prism/attribute/inline.h" #include "prism/attribute/unused.h" #include "prism/internal/accel.h" @@ -50,22 +50,6 @@ #define PRISM_DEPTH_MAXIMUM 10000 #endif -/** - * Old Visual Studio versions do not support the inline keyword, so we need to - * define it to be __inline. - */ -#if defined(_MSC_VER) && !defined(inline) -# define inline __inline -#endif - -/** - * Old Visual Studio versions before 2015 do not implement sprintf, but instead - * implement _snprintf. We standard that here. - */ -#if !defined(snprintf) && defined(_MSC_VER) && (_MSC_VER < 1900) -# define snprintf _snprintf -#endif - /** * A simple utility macro to concatenate two tokens together, necessary when one * of the tokens is itself a macro. diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h index e86b89903e..8d263d9e6e 100644 --- a/include/prism/internal/arena.h +++ b/include/prism/internal/arena.h @@ -7,6 +7,7 @@ #define PRISM_INTERNAL_ARENA_H #include "prism/attribute/exported.h" +#include "prism/attribute/inline.h" #include "prism/arena.h" #include @@ -31,7 +32,7 @@ void pm_arena_reserve(pm_arena_t *arena, size_t capacity); * @param alignment The required alignment (must be a power of 2). * @returns A pointer to the allocated, zero-initialized memory. */ -static inline void * +static PRISM_INLINE void * pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { void *ptr = pm_arena_alloc(arena, size, alignment); memset(ptr, 0, size); @@ -48,7 +49,7 @@ pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { * @param alignment The required alignment (must be a power of 2). * @returns A pointer to the allocated copy. */ -static inline void * +static PRISM_INLINE void * pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { void *dst = pm_arena_alloc(arena, size, alignment); memcpy(dst, src, size); diff --git a/include/prism/internal/bit.h b/include/prism/internal/bit.h index 110d4d68cb..06ac3be2ee 100644 --- a/include/prism/internal/bit.h +++ b/include/prism/internal/bit.h @@ -6,6 +6,8 @@ #ifndef PRISM_INTERNAL_BIT_H #define PRISM_INTERNAL_BIT_H +#include "prism/attribute/inline.h" + /** * Count trailing zero bits in a 64-bit value. Used by SWAR identifier scanning * to find the first non-matching byte in a word. @@ -17,13 +19,13 @@ #define pm_ctzll(v) ((unsigned) __builtin_ctzll(v)) #elif defined(_MSC_VER) #include - static inline unsigned pm_ctzll(uint64_t v) { + static PRISM_INLINE unsigned pm_ctzll(uint64_t v) { unsigned long index; _BitScanForward64(&index, v); return (unsigned) index; } #else - static inline unsigned + static PRISM_INLINE unsigned pm_ctzll(uint64_t v) { unsigned c = 0; v &= (uint64_t) (-(int64_t) v); diff --git a/include/prism/internal/line_offset_list.h b/include/prism/internal/line_offset_list.h index 87af0bb524..97fa050924 100644 --- a/include/prism/internal/line_offset_list.h +++ b/include/prism/internal/line_offset_list.h @@ -15,6 +15,7 @@ #define PRISM_INTERNAL_LINE_OFFSET_LIST_H #include "prism/line_offset_list.h" + #include "prism/attribute/force_inline.h" #include "prism/arena.h" diff --git a/prism.gemspec b/prism.gemspec index 3941e21077..6a4b7ba5a4 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -51,6 +51,7 @@ Gem::Specification.new do |spec| "include/prism/attribute/flex_array.h", "include/prism/attribute/force_inline.h", "include/prism/attribute/format.h", + "include/prism/attribute/inline.h", "include/prism/attribute/unused.h", "include/prism/allocator.h", "include/prism/arena.h", diff --git a/src/buffer.c b/src/buffer.c index b416519795..a54c55182b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,4 +1,6 @@ #include "prism/internal/buffer.h" + +#include "prism/attribute/inline.h" #include "prism/internal/char.h" #include "prism/allocator.h" @@ -55,7 +57,7 @@ pm_buffer_length(const pm_buffer_t *buffer) { /** * Append the given amount of space to the buffer. */ -static inline bool +static PRISM_INLINE bool pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { size_t next_length = buffer->length + length; const size_t original_capacity = buffer->capacity; @@ -80,7 +82,7 @@ pm_buffer_append_length(pm_buffer_t *buffer, size_t length) { /** * Append a generic pointer to memory to the buffer. */ -static inline void +static PRISM_INLINE void pm_buffer_append(pm_buffer_t *buffer, const void *source, size_t length) { size_t cursor = buffer->length; if (pm_buffer_append_length(buffer, length)) { diff --git a/src/char.c b/src/char.c index c119ee8a19..1b5438cd0c 100644 --- a/src/char.c +++ b/src/char.c @@ -1,4 +1,6 @@ #include "prism/internal/char.h" + +#include "prism/attribute/inline.h" #include "prism/internal/line_offset_list.h" #define PRISM_CHAR_BIT_REGEXP_OPTION (1 << 2) @@ -56,7 +58,7 @@ static const uint8_t pm_number_table[256] = { * Returns the number of characters at the start of the string that match the * given kind. Disallows searching past the given maximum number of characters. */ -static inline size_t +static PRISM_INLINE size_t pm_strspn_char_kind(const uint8_t *string, ptrdiff_t length, uint8_t kind) { if (length <= 0) return 0; @@ -114,7 +116,7 @@ pm_strspn_regexp_option(const uint8_t *string, ptrdiff_t length) { * the string that match the given kind. Disallows searching past the given * maximum number of characters. */ -static inline size_t +static PRISM_INLINE size_t pm_strspn_number_kind(const uint8_t *string, ptrdiff_t length, uint8_t kind) { if (length <= 0) return 0; @@ -133,7 +135,7 @@ pm_strspn_number_kind(const uint8_t *string, ptrdiff_t length, uint8_t kind) { * Additionally, report the location of the last invalid underscore character * found in the string through the out invalid parameter. */ -static inline size_t +static PRISM_INLINE size_t pm_strspn_number_kind_underscores(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid, uint8_t kind) { if (length <= 0) return 0; @@ -234,7 +236,7 @@ pm_strspn_hexadecimal_number(const uint8_t *string, ptrdiff_t length, const uint /** * Returns true if the given character matches the given kind. */ -static inline bool +static PRISM_INLINE bool pm_char_is_number_kind(const uint8_t b, uint8_t kind) { return (pm_number_table[b] & kind) != 0; } diff --git a/src/constant_pool.c b/src/constant_pool.c index 106566df90..7de70a47a4 100644 --- a/src/constant_pool.c +++ b/src/constant_pool.c @@ -1,6 +1,7 @@ #include "prism/constant_pool.h" #include "prism/attribute/align.h" +#include "prism/attribute/inline.h" #include "prism/internal/arena.h" #include @@ -81,7 +82,7 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) { * by XOR followed by multiplication by a large odd constant, which spreads * entropy across all bits. A final xorshift fold produces the 32-bit result. */ -static inline uint32_t +static PRISM_INLINE uint32_t pm_constant_pool_hash(const uint8_t *start, size_t length) { // This constant is borrowed from wyhash. It is a 64-bit odd integer with // roughly equal 0/1 bits, chosen for good avalanche behavior when used in @@ -167,7 +168,7 @@ is_power_of_two(uint32_t size) { /** * Resize a constant pool to a given capacity. */ -static inline void +static PRISM_INLINE void pm_constant_pool_resize(pm_arena_t *arena, pm_constant_pool_t *pool) { assert(is_power_of_two(pool->capacity)); @@ -257,7 +258,7 @@ pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size /** * Insert a constant into a constant pool and return its index in the pool. */ -static inline pm_constant_id_t +static PRISM_INLINE pm_constant_id_t pm_constant_pool_insert(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length, pm_constant_pool_bucket_type_t type) { if (pool->size >= (pool->capacity / 4 * 3)) { pm_constant_pool_resize(arena, pool); diff --git a/src/options.c b/src/options.c index 26df07fca3..e38bd92ca9 100644 --- a/src/options.c +++ b/src/options.c @@ -1,5 +1,6 @@ #include "prism/options.h" +#include "prism/attribute/inline.h" #include "prism/internal/char.h" #include "prism/allocator.h" @@ -66,7 +67,7 @@ pm_options_command_line_set(pm_options_t *options, uint8_t command_line) { /** * Checks if the given slice represents a number. */ -static inline bool +static PRISM_INLINE bool is_number(const char *string, size_t length) { return pm_strspn_decimal_digit((const uint8_t *) string, (ptrdiff_t) length) == length; } diff --git a/src/prism.c b/src/prism.c index 0e24aff7d6..fed7b069e6 100644 --- a/src/prism.c +++ b/src/prism.c @@ -88,7 +88,7 @@ pm_version(void) { * Returns the incrementor character that should be used to increment the * nesting count if one is possible. */ -static inline uint8_t +static PRISM_INLINE uint8_t lex_mode_incrementor(const uint8_t start) { switch (start) { case '(': @@ -105,7 +105,7 @@ lex_mode_incrementor(const uint8_t start) { * Returns the matching character that should be used to terminate a list * beginning with the given character. */ -static inline uint8_t +static PRISM_INLINE uint8_t lex_mode_terminator(const uint8_t start) { switch (start) { case '(': @@ -147,7 +147,7 @@ lex_mode_push(pm_parser_t *parser, pm_lex_mode_t lex_mode) { /** * Push on a new list lex mode. */ -static inline bool +static PRISM_INLINE bool lex_mode_push_list(pm_parser_t *parser, bool interpolation, uint8_t delimiter) { uint8_t incrementor = lex_mode_incrementor(delimiter); uint8_t terminator = lex_mode_terminator(delimiter); @@ -195,7 +195,7 @@ lex_mode_push_list(pm_parser_t *parser, bool interpolation, uint8_t delimiter) { * called when we're at the end of the file. We want the parser to be able to * perform its normal error tolerance. */ -static inline bool +static PRISM_INLINE bool lex_mode_push_list_eof(pm_parser_t *parser) { return lex_mode_push_list(parser, false, '\0'); } @@ -203,7 +203,7 @@ lex_mode_push_list_eof(pm_parser_t *parser) { /** * Push on a new regexp lex mode. */ -static inline bool +static PRISM_INLINE bool lex_mode_push_regexp(pm_parser_t *parser, uint8_t incrementor, uint8_t terminator) { pm_lex_mode_t lex_mode = { .mode = PM_LEX_REGEXP, @@ -239,7 +239,7 @@ lex_mode_push_regexp(pm_parser_t *parser, uint8_t incrementor, uint8_t terminato /** * Push on a new string lex mode. */ -static inline bool +static PRISM_INLINE bool lex_mode_push_string(pm_parser_t *parser, bool interpolation, bool label_allowed, uint8_t incrementor, uint8_t terminator) { pm_lex_mode_t lex_mode = { .mode = PM_LEX_STRING, @@ -286,7 +286,7 @@ lex_mode_push_string(pm_parser_t *parser, bool interpolation, bool label_allowed * called when we're at the end of the file. We want the parser to be able to * perform its normal error tolerance. */ -static inline bool +static PRISM_INLINE bool lex_mode_push_string_eof(pm_parser_t *parser) { return lex_mode_push_string(parser, false, false, '\0', '\0'); } @@ -314,7 +314,7 @@ lex_mode_pop(pm_parser_t *parser) { /** * This is the equivalent of IS_lex_state is CRuby. */ -static inline bool +static PRISM_INLINE bool lex_state_p(const pm_parser_t *parser, pm_lex_state_t state) { return parser->lex_state & state; } @@ -325,7 +325,7 @@ typedef enum { PM_IGNORED_NEWLINE_PATTERN } pm_ignored_newline_type_t; -static inline pm_ignored_newline_type_t +static PRISM_INLINE pm_ignored_newline_type_t lex_state_ignored_p(pm_parser_t *parser) { bool ignored = lex_state_p(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_CLASS | PM_LEX_STATE_FNAME | PM_LEX_STATE_DOT) && !lex_state_p(parser, PM_LEX_STATE_LABELED); @@ -338,17 +338,17 @@ lex_state_ignored_p(pm_parser_t *parser) { } } -static inline bool +static PRISM_INLINE bool lex_state_beg_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_BEG_ANY) || ((parser->lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)); } -static inline bool +static PRISM_INLINE bool lex_state_arg_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_ARG_ANY); } -static inline bool +static PRISM_INLINE bool lex_state_spcarg_p(pm_parser_t *parser, bool space_seen) { if (parser->current.end >= parser->end) { return false; @@ -356,7 +356,7 @@ lex_state_spcarg_p(pm_parser_t *parser, bool space_seen) { return lex_state_arg_p(parser) && space_seen && !pm_char_is_whitespace(*parser->current.end); } -static inline bool +static PRISM_INLINE bool lex_state_end_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_END_ANY); } @@ -364,7 +364,7 @@ lex_state_end_p(pm_parser_t *parser) { /** * This is the equivalent of IS_AFTER_OPERATOR in CRuby. */ -static inline bool +static PRISM_INLINE bool lex_state_operator_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_DOT); } @@ -373,7 +373,7 @@ lex_state_operator_p(pm_parser_t *parser) { * Set the state of the lexer. This is defined as a function to be able to put a * breakpoint in it. */ -static inline void +static PRISM_INLINE void lex_state_set(pm_parser_t *parser, pm_lex_state_t state) { parser->lex_state = state; } @@ -468,7 +468,7 @@ debug_lex_state_set(pm_parser_t *parser, pm_lex_state_t state, char const * call /** * Append an error to the list of errors on the parser. */ -static inline void +static PRISM_INLINE void pm_parser_err(pm_parser_t *parser, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) { pm_diagnostic_list_append(&parser->metadata_arena, &parser->error_list, start, length, diag_id); } @@ -477,7 +477,7 @@ pm_parser_err(pm_parser_t *parser, uint32_t start, uint32_t length, pm_diagnosti * Append an error to the list of errors on the parser using the location of the * given token. */ -static inline void +static PRISM_INLINE void pm_parser_err_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic_id_t diag_id) { pm_parser_err(parser, PM_TOKEN_START(parser, token), PM_TOKEN_LENGTH(token), diag_id); } @@ -486,7 +486,7 @@ pm_parser_err_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic_ * Append an error to the list of errors on the parser using the location of the * current token. */ -static inline void +static PRISM_INLINE void pm_parser_err_current(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { pm_parser_err_token(parser, &parser->current, diag_id); } @@ -495,7 +495,7 @@ pm_parser_err_current(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { * Append an error to the list of errors on the parser using the location of the * previous token. */ -static inline void +static PRISM_INLINE void pm_parser_err_previous(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { pm_parser_err_token(parser, &parser->previous, diag_id); } @@ -504,7 +504,7 @@ pm_parser_err_previous(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { * Append an error to the list of errors on the parser using the location of the * given node. */ -static inline void +static PRISM_INLINE void pm_parser_err_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_t diag_id) { pm_parser_err(parser, PM_NODE_START(node), PM_NODE_LENGTH(node), diag_id); } @@ -546,7 +546,7 @@ pm_parser_err_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_ /** * Append a warning to the list of warnings on the parser. */ -static inline void +static PRISM_INLINE void pm_parser_warn(pm_parser_t *parser, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) { pm_diagnostic_list_append(&parser->metadata_arena, &parser->warning_list, start, length, diag_id); } @@ -555,7 +555,7 @@ pm_parser_warn(pm_parser_t *parser, uint32_t start, uint32_t length, pm_diagnost * Append a warning to the list of warnings on the parser using the location of * the given token. */ -static inline void +static PRISM_INLINE void pm_parser_warn_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic_id_t diag_id) { pm_parser_warn(parser, PM_TOKEN_START(parser, token), PM_TOKEN_LENGTH(token), diag_id); } @@ -564,7 +564,7 @@ pm_parser_warn_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic * Append a warning to the list of warnings on the parser using the location of * the given node. */ -static inline void +static PRISM_INLINE void pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_t diag_id) { pm_parser_warn(parser, PM_NODE_START(node), PM_NODE_LENGTH(node), diag_id); } @@ -767,7 +767,7 @@ pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t /** * Get the current state of constant shareability. */ -static inline pm_shareable_constant_value_t +static PRISM_INLINE pm_shareable_constant_value_t pm_parser_scope_shareable_constant_get(pm_parser_t *parser) { return parser->current_scope->shareable_constant; } @@ -1049,7 +1049,7 @@ pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, /** * Retrieve the constant pool id for the given location. */ -static inline pm_constant_id_t +static PRISM_INLINE pm_constant_id_t pm_parser_constant_id_raw(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { return pm_constant_pool_insert_shared(&parser->metadata_arena, &parser->constant_pool, start, (size_t) (end - start)); } @@ -1057,7 +1057,7 @@ pm_parser_constant_id_raw(pm_parser_t *parser, const uint8_t *start, const uint8 /** * Retrieve the constant pool id for the given string. */ -static inline pm_constant_id_t +static PRISM_INLINE pm_constant_id_t pm_parser_constant_id_owned(pm_parser_t *parser, uint8_t *start, size_t length) { return pm_constant_pool_insert_owned(&parser->metadata_arena, &parser->constant_pool, start, length); } @@ -1065,7 +1065,7 @@ pm_parser_constant_id_owned(pm_parser_t *parser, uint8_t *start, size_t length) /** * Retrieve the constant pool id for the given static literal C string. */ -static inline pm_constant_id_t +static PRISM_INLINE pm_constant_id_t pm_parser_constant_id_constant(pm_parser_t *parser, const char *start, size_t length) { return pm_constant_pool_insert_constant(&parser->metadata_arena, &parser->constant_pool, (const uint8_t *) start, length); } @@ -1073,7 +1073,7 @@ pm_parser_constant_id_constant(pm_parser_t *parser, const char *start, size_t le /** * Retrieve the constant pool id for the given token. */ -static inline pm_constant_id_t +static PRISM_INLINE pm_constant_id_t pm_parser_constant_id_token(pm_parser_t *parser, const pm_token_t *token) { return pm_parser_constant_id_raw(parser, token->start, token->end); } @@ -1292,7 +1292,7 @@ pm_check_value_expression(pm_parser_t *parser, pm_node_t *node) { return NULL; } -static inline void +static PRISM_INLINE void pm_assert_value_expression(pm_parser_t *parser, pm_node_t *node) { pm_node_t *void_node = pm_check_value_expression(parser, node); if (void_node != NULL) { @@ -1533,7 +1533,7 @@ pm_conditional_predicate_warn_write_literal_p(const pm_node_t *node) { * Add a warning to the parser if the value that is being written inside of a * predicate to a conditional is a literal. */ -static inline void +static PRISM_INLINE void pm_conditional_predicate_warn_write_literal(pm_parser_t *parser, const pm_node_t *node) { if (pm_conditional_predicate_warn_write_literal_p(node)) { pm_parser_warn_node(parser, node, parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_WARN_EQUAL_IN_CONDITIONAL_3_3 : PM_WARN_EQUAL_IN_CONDITIONAL); @@ -1699,7 +1699,7 @@ typedef struct { /** * Retrieve the end location of a `pm_arguments_t` object. */ -static inline const pm_location_t * +static PRISM_INLINE const pm_location_t * pm_arguments_end(pm_arguments_t *arguments) { if (arguments->block != NULL) { uint32_t end = PM_NODE_END(arguments->block); @@ -1762,7 +1762,7 @@ pm_arguments_validate_block(pm_parser_t *parser, pm_arguments_t *arguments, pm_b * reason we have the encoding_changed boolean to check if we need to go through * the function pointer or can just directly use the UTF-8 functions. */ -static inline size_t +static PRISM_INLINE size_t char_is_identifier_start(const pm_parser_t *parser, const uint8_t *b, ptrdiff_t n) { if (n <= 0) return 0; @@ -1789,7 +1789,7 @@ char_is_identifier_start(const pm_parser_t *parser, const uint8_t *b, ptrdiff_t * Similar to char_is_identifier but this function assumes that the encoding * has not been changed. */ -static inline size_t +static PRISM_INLINE size_t char_is_identifier_utf8(const uint8_t *b, ptrdiff_t n) { if (n <= 0) { return 0; @@ -1816,7 +1816,7 @@ char_is_identifier_utf8(const uint8_t *b, ptrdiff_t n) { #if defined(PRISM_HAS_NEON) #include -static inline size_t +static PRISM_INLINE size_t scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { const uint8_t *cursor = start; @@ -1870,7 +1870,7 @@ scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { #elif defined(PRISM_HAS_SSSE3) #include -static inline size_t +static PRISM_INLINE size_t scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { const uint8_t *cursor = start; @@ -1924,7 +1924,7 @@ scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { * impossible. The result has bit 7 set if and only if byte >= lo. The same * reasoning applies to the upper-bound direction. */ -static inline size_t +static PRISM_INLINE size_t scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { static const uint64_t ones = 0x0101010101010101ULL; static const uint64_t highs = 0x8080808080808080ULL; @@ -1983,7 +1983,7 @@ scan_identifier_ascii(const uint8_t *start, const uint8_t *end) { * the identifiers in a source file once the first character has been found. So * it's important that it be as fast as possible. */ -static inline size_t +static PRISM_INLINE size_t char_is_identifier(const pm_parser_t *parser, const uint8_t *b, ptrdiff_t n) { if (n <= 0) { return 0; @@ -2021,7 +2021,7 @@ const unsigned int pm_global_name_punctuation_hash[(0x7e - 0x20 + 31) / 32] = { #undef BIT #undef PUNCT -static inline bool +static PRISM_INLINE bool char_is_global_name_punctuation(const uint8_t b) { const unsigned int i = (const unsigned int) b; if (i <= 0x20 || 0x7e < i) return false; @@ -2029,7 +2029,7 @@ char_is_global_name_punctuation(const uint8_t b) { return (pm_global_name_punctuation_hash[(i - 0x20) / 32] >> (i % 32)) & 1; } -static inline bool +static PRISM_INLINE bool token_is_setter_name(pm_token_t *token) { return ( (token->type == PM_TOKEN_BRACKET_LEFT_RIGHT_EQUAL) || @@ -2117,7 +2117,7 @@ pm_local_is_keyword(const char *source, size_t length) { /** * Set the given flag on the given node. */ -static inline void +static PRISM_INLINE void pm_node_flag_set(pm_node_t *node, pm_node_flags_t flag) { node->flags |= flag; } @@ -2125,7 +2125,7 @@ pm_node_flag_set(pm_node_t *node, pm_node_flags_t flag) { /** * Remove the given flag from the given node. */ -static inline void +static PRISM_INLINE void pm_node_flag_unset(pm_node_t *node, pm_node_flags_t flag) { node->flags &= (pm_node_flags_t) ~flag; } @@ -2133,7 +2133,7 @@ pm_node_flag_unset(pm_node_t *node, pm_node_flags_t flag) { /** * Set the repeated parameter flag on the given node. */ -static inline void +static PRISM_INLINE void pm_node_flag_set_repeated_parameter(pm_node_t *node) { assert(PM_NODE_TYPE(node) == PM_BLOCK_LOCAL_VARIABLE_NODE || PM_NODE_TYPE(node) == PM_BLOCK_PARAMETER_NODE || @@ -2161,7 +2161,7 @@ pm_node_flag_set_repeated_parameter(pm_node_t *node) { /** * Parse out the options for a regular expression. */ -static inline pm_node_flags_t +static PRISM_INLINE pm_node_flags_t pm_regular_expression_flags_create(pm_parser_t *parser, const pm_token_t *closing) { pm_node_flags_t flags = 0; @@ -2210,7 +2210,7 @@ pm_statements_node_body_length(pm_statements_node_t *node); * Move an integer's values array into the arena. If the integer has heap- * allocated values, copy them to the arena and free the original. */ -static inline void +static PRISM_INLINE void pm_integer_arena_move(pm_arena_t *arena, pm_integer_t *integer) { if (integer->values != NULL) { size_t byte_size = integer->length * sizeof(uint32_t); @@ -2380,7 +2380,7 @@ pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) { /** * Append an argument to an array node. */ -static inline void +static PRISM_INLINE void pm_array_node_elements_append(pm_arena_t *arena, pm_array_node_t *node, pm_node_t *element) { if (!node->elements.size && !node->opening_loc.length) { PM_NODE_START_SET_NODE(node, element); @@ -2507,7 +2507,7 @@ pm_array_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *openin ); } -static inline void +static PRISM_INLINE void pm_array_pattern_node_requireds_append(pm_arena_t *arena, pm_array_pattern_node_t *node, pm_node_t *inner) { pm_node_list_append(arena, &node->requireds, inner); } @@ -2836,7 +2836,7 @@ pm_call_node_create(pm_parser_t *parser, pm_node_flags_t flags) { * Returns the value that the ignore visibility flag should be set to for the * given receiver. */ -static inline pm_node_flags_t +static PRISM_INLINE pm_node_flags_t pm_call_node_ignore_visibility_flag(const pm_node_t *receiver) { return PM_NODE_TYPE_P(receiver, PM_SELF_NODE) ? PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY : 0; } @@ -3086,7 +3086,7 @@ pm_call_node_variable_call_create(pm_parser_t *parser, pm_token_t *message) { * Returns whether or not this call can be used on the left-hand side of an * operator assignment. */ -static inline bool +static PRISM_INLINE bool pm_call_node_writable_p(const pm_parser_t *parser, const pm_call_node_t *node) { return ( (node->message_loc.length > 0) && @@ -3594,7 +3594,7 @@ pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) * a = *b * a = 1, 2, 3 */ -static inline pm_node_flags_t +static PRISM_INLINE pm_node_flags_t pm_implicit_array_write_flags(const pm_node_t *node, pm_node_flags_t flags) { if (PM_NODE_TYPE_P(node, PM_ARRAY_NODE) && ((const pm_array_node_t *) node)->opening_loc.length == 0) { return flags; @@ -4517,7 +4517,7 @@ pm_hash_node_create(pm_parser_t *parser, const pm_token_t *opening) { /** * Append a new element to a hash node. */ -static inline void +static PRISM_INLINE void pm_hash_node_elements_append(pm_arena_t *arena, pm_hash_node_t *hash, pm_node_t *element) { pm_node_list_append(arena, &hash->elements, element); @@ -4534,7 +4534,7 @@ pm_hash_node_elements_append(pm_arena_t *arena, pm_hash_node_t *hash, pm_node_t } } -static inline void +static PRISM_INLINE void pm_hash_node_closing_loc_set(const pm_parser_t *parser, pm_hash_node_t *hash, pm_token_t *token) { PM_NODE_LENGTH_SET_TOKEN(parser, hash, token); hash->closing_loc = TOK2LOC(parser, token); @@ -4634,13 +4634,13 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to ); } -static inline void +static PRISM_INLINE void pm_if_node_end_keyword_loc_set(const pm_parser_t *parser, pm_if_node_t *node, const pm_token_t *keyword) { PM_NODE_LENGTH_SET_TOKEN(parser, node, keyword); node->end_keyword_loc = TOK2LOC(parser, keyword); } -static inline void +static PRISM_INLINE void pm_else_node_end_keyword_loc_set(const pm_parser_t *parser, pm_else_node_t *node, const pm_token_t *keyword) { PM_NODE_LENGTH_SET_TOKEN(parser, node, keyword); node->end_keyword_loc = TOK2LOC(parser, keyword); @@ -4963,7 +4963,7 @@ pm_interpolated_regular_expression_node_create(pm_parser_t *parser, const pm_tok ); } -static inline void +static PRISM_INLINE void pm_interpolated_regular_expression_node_append(pm_arena_t *arena, pm_interpolated_regular_expression_node_t *node, pm_node_t *part) { if (PM_NODE_START(node) > PM_NODE_START(part)) { PM_NODE_START_SET_NODE(node, part); @@ -4975,7 +4975,7 @@ pm_interpolated_regular_expression_node_append(pm_arena_t *arena, pm_interpolate pm_interpolated_node_append(arena, UP(node), &node->parts, part); } -static inline void +static PRISM_INLINE void pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_interpolated_regular_expression_node_t *node, const pm_token_t *closing) { node->closing_loc = TOK2LOC(parser, closing); PM_NODE_LENGTH_SET_TOKEN(parser, node, closing); @@ -5005,7 +5005,7 @@ pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_inte * is necessary to indicate that the string should be left up to the runtime, * which could potentially use a chilled string otherwise. */ -static inline void +static PRISM_INLINE void pm_interpolated_string_node_append(pm_arena_t *arena, pm_interpolated_string_node_t *node, pm_node_t *part) { #define CLEAR_FLAGS(node) \ node->base.flags = (pm_node_flags_t) (FL(node) & ~(PM_NODE_FLAG_STATIC_LITERAL | PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE)) @@ -5208,13 +5208,13 @@ pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *openi ); } -static inline void +static PRISM_INLINE void pm_interpolated_xstring_node_append(pm_arena_t *arena, pm_interpolated_x_string_node_t *node, pm_node_t *part) { pm_interpolated_node_append(arena, UP(node), &node->parts, part); PM_NODE_LENGTH_SET_NODE(node, part); } -static inline void +static PRISM_INLINE void pm_interpolated_xstring_node_closing_set(const pm_parser_t *parser, pm_interpolated_x_string_node_t *node, const pm_token_t *closing) { node->closing_loc = TOK2LOC(parser, closing); PM_NODE_LENGTH_SET_TOKEN(parser, node, closing); @@ -5470,7 +5470,7 @@ pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name, /** * Returns true if the given bounds comprise `it`. */ -static inline bool +static PRISM_INLINE bool pm_token_is_it(const uint8_t *start, const uint8_t *end) { return (end - start == 2) && (start[0] == 'i') && (start[1] == 't'); } @@ -5479,7 +5479,7 @@ pm_token_is_it(const uint8_t *start, const uint8_t *end) { * Returns true if the given bounds comprise a numbered parameter (i.e., they * are of the form /^_\d$/). */ -static inline bool +static PRISM_INLINE bool pm_token_is_numbered_parameter(const pm_parser_t *parser, uint32_t start, uint32_t length) { return ( (length == 2) && @@ -5493,7 +5493,7 @@ pm_token_is_numbered_parameter(const pm_parser_t *parser, uint32_t start, uint32 * Ensure the given bounds do not comprise a numbered parameter. If they do, add * an appropriate error message to the parser. */ -static inline void +static PRISM_INLINE void pm_refute_numbered_parameter(pm_parser_t *parser, uint32_t start, uint32_t length) { if (pm_token_is_numbered_parameter(parser, start, length)) { PM_PARSER_ERR_FORMAT(parser, start, length, PM_ERR_PARAMETER_NUMBERED_RESERVED, parser->start + start); @@ -6133,7 +6133,7 @@ pm_regular_expression_node_create_unescaped(pm_parser_t *parser, const pm_token_ /** * Allocate a new initialize a new RegularExpressionNode node. */ -static inline pm_regular_expression_node_t * +static PRISM_INLINE pm_regular_expression_node_t * pm_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing) { return pm_regular_expression_node_create_unescaped(parser, opening, content, closing, &PM_STRING_EMPTY); } @@ -6188,7 +6188,7 @@ pm_rescue_node_create(pm_parser_t *parser, const pm_token_t *keyword) { ); } -static inline void +static PRISM_INLINE void pm_rescue_node_operator_set(const pm_parser_t *parser, pm_rescue_node_t *node, const pm_token_t *operator) { node->operator_loc = TOK2LOC(parser, operator); } @@ -6423,7 +6423,7 @@ pm_statements_node_body_length(pm_statements_node_t *node) { * Update the location of the statements node based on the statement that is * being added to the list. */ -static inline void +static PRISM_INLINE void pm_statements_node_body_update(pm_statements_node_t *node, pm_node_t *statement) { if (pm_statements_node_body_length(node) == 0 || PM_NODE_START(statement) < PM_NODE_START(node)) { PM_NODE_START_SET_NODE(node, statement); @@ -6474,7 +6474,7 @@ pm_statements_node_body_prepend(pm_arena_t *arena, pm_statements_node_t *node, p /** * Allocate a new StringNode node with the current string on the parser. */ -static inline pm_string_node_t * +static PRISM_INLINE pm_string_node_t * pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *string) { pm_node_flags_t flags = 0; @@ -6606,7 +6606,7 @@ parse_symbol_encoding_validate_other(pm_parser_t *parser, const pm_token_t *loca * If the validate flag is set, then it will check the contents of the symbol * to ensure that all characters are valid in the encoding. */ -static inline pm_node_flags_t +static PRISM_INLINE pm_node_flags_t parse_symbol_encoding(pm_parser_t *parser, const pm_token_t *location, const pm_string_t *contents, bool validate) { if (parser->explicit_encoding != NULL) { // A Symbol may optionally have its encoding explicitly set. This will @@ -6655,7 +6655,7 @@ pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, /** * Allocate and initialize a new SymbolNode node. */ -static inline pm_symbol_node_t * +static PRISM_INLINE pm_symbol_node_t * pm_symbol_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing) { return pm_symbol_node_create_unescaped(parser, opening, value, closing, &PM_STRING_EMPTY, 0); } @@ -6896,7 +6896,7 @@ pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const ); } -static inline void +static PRISM_INLINE void pm_unless_node_end_keyword_loc_set(const pm_parser_t *parser, pm_unless_node_t *node, const pm_token_t *end_keyword) { node->end_keyword_loc = TOK2LOC(parser, end_keyword); PM_NODE_LENGTH_SET_TOKEN(parser, node, end_keyword); @@ -6995,7 +6995,7 @@ pm_when_node_conditions_append(pm_arena_t *arena, pm_when_node_t *node, pm_node_ /** * Set the location of the then keyword of a when node. */ -static inline void +static PRISM_INLINE void pm_when_node_then_keyword_loc_set(const pm_parser_t *parser, pm_when_node_t *node, const pm_token_t *then_keyword) { PM_NODE_LENGTH_SET_TOKEN(parser, node, then_keyword); node->then_keyword_loc = TOK2LOC(parser, then_keyword); @@ -7093,7 +7093,7 @@ pm_xstring_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, /** * Allocate and initialize a new XStringNode node. */ -static inline pm_x_string_node_t * +static PRISM_INLINE pm_x_string_node_t * pm_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing) { return pm_xstring_node_create_unescaped(parser, opening, content, closing, &PM_STRING_EMPTY); } @@ -7153,7 +7153,7 @@ pm_parser_local_depth_constant_id(pm_parser_t *parser, pm_constant_id_t constant * described by the given token. This function implicitly inserts a constant * into the constant pool. */ -static inline int +static PRISM_INLINE int pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) { return pm_parser_local_depth_constant_id(parser, pm_parser_constant_id_token(parser, token)); } @@ -7161,7 +7161,7 @@ pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) { /** * Add a constant id to the local table of the current scope. */ -static inline void +static PRISM_INLINE void pm_parser_local_add(pm_parser_t *parser, pm_constant_id_t constant_id, const uint8_t *start, const uint8_t *end, uint32_t reads) { pm_locals_write(&parser->current_scope->locals, constant_id, U32(start - parser->start), U32(end - start), reads); } @@ -7179,7 +7179,7 @@ pm_parser_local_add_raw(pm_parser_t *parser, const uint8_t *start, const uint8_t /** * Add a local variable from a location to the current scope. */ -static inline pm_constant_id_t +static PRISM_INLINE pm_constant_id_t pm_parser_local_add_location(pm_parser_t *parser, pm_location_t *location, uint32_t reads) { return pm_parser_local_add_raw(parser, parser->start + location->start, parser->start + location->start + location->length, reads); } @@ -7187,7 +7187,7 @@ pm_parser_local_add_location(pm_parser_t *parser, pm_location_t *location, uint3 /** * Add a local variable from a token to the current scope. */ -static inline pm_constant_id_t +static PRISM_INLINE pm_constant_id_t pm_parser_local_add_token(pm_parser_t *parser, pm_token_t *token, uint32_t reads) { return pm_parser_local_add_raw(parser, token->start, token->end, reads); } @@ -7257,7 +7257,7 @@ pm_parser_scope_pop(pm_parser_t *parser) { /** * Pushes a value onto the stack. */ -static inline void +static PRISM_INLINE void pm_state_stack_push(pm_state_stack_t *stack, bool value) { *stack = (*stack << 1) | (value & 1); } @@ -7265,7 +7265,7 @@ pm_state_stack_push(pm_state_stack_t *stack, bool value) { /** * Pops a value off the stack. */ -static inline void +static PRISM_INLINE void pm_state_stack_pop(pm_state_stack_t *stack) { *stack >>= 1; } @@ -7273,38 +7273,38 @@ pm_state_stack_pop(pm_state_stack_t *stack) { /** * Returns the value at the top of the stack. */ -static inline bool +static PRISM_INLINE bool pm_state_stack_p(const pm_state_stack_t *stack) { return *stack & 1; } -static inline void +static PRISM_INLINE void pm_accepts_block_stack_push(pm_parser_t *parser, bool value) { // Use the negation of the value to prevent stack overflow. pm_state_stack_push(&parser->accepts_block_stack, !value); } -static inline void +static PRISM_INLINE void pm_accepts_block_stack_pop(pm_parser_t *parser) { pm_state_stack_pop(&parser->accepts_block_stack); } -static inline bool +static PRISM_INLINE bool pm_accepts_block_stack_p(pm_parser_t *parser) { return !pm_state_stack_p(&parser->accepts_block_stack); } -static inline void +static PRISM_INLINE void pm_do_loop_stack_push(pm_parser_t *parser, bool value) { pm_state_stack_push(&parser->do_loop_stack, value); } -static inline void +static PRISM_INLINE void pm_do_loop_stack_pop(pm_parser_t *parser) { pm_state_stack_pop(&parser->do_loop_stack); } -static inline bool +static PRISM_INLINE bool pm_do_loop_stack_p(pm_parser_t *parser) { return pm_state_stack_p(&parser->do_loop_stack); } @@ -7317,7 +7317,7 @@ pm_do_loop_stack_p(pm_parser_t *parser) { * Get the next character in the source starting from +cursor+. If that position * is beyond the end of the source then return '\0'. */ -static inline uint8_t +static PRISM_INLINE uint8_t peek_at(const pm_parser_t *parser, const uint8_t *cursor) { if (cursor < parser->end) { return *cursor; @@ -7331,7 +7331,7 @@ peek_at(const pm_parser_t *parser, const uint8_t *cursor) { * adding the given offset. If that position is beyond the end of the source * then return '\0'. */ -static inline uint8_t +static PRISM_INLINE uint8_t peek_offset(pm_parser_t *parser, ptrdiff_t offset) { return peek_at(parser, parser->current.end + offset); } @@ -7340,7 +7340,7 @@ peek_offset(pm_parser_t *parser, ptrdiff_t offset) { * Get the next character in the source starting from parser->current.end. If * that position is beyond the end of the source then return '\0'. */ -static inline uint8_t +static PRISM_INLINE uint8_t peek(const pm_parser_t *parser) { return peek_at(parser, parser->current.end); } @@ -7349,7 +7349,7 @@ peek(const pm_parser_t *parser) { * If the character to be read matches the given value, then returns true and * advances the current pointer. */ -static inline bool +static PRISM_INLINE bool match(pm_parser_t *parser, uint8_t value) { if (peek(parser) == value) { parser->current.end++; @@ -7362,7 +7362,7 @@ match(pm_parser_t *parser, uint8_t value) { * Return the length of the line ending string starting at +cursor+, or 0 if it * is not a line ending. This function is intended to be CRLF/LF agnostic. */ -static inline size_t +static PRISM_INLINE size_t match_eol_at(pm_parser_t *parser, const uint8_t *cursor) { if (peek_at(parser, cursor) == '\n') { return 1; @@ -7378,7 +7378,7 @@ match_eol_at(pm_parser_t *parser, const uint8_t *cursor) { * `parser->current.end + offset`, or 0 if it is not a line ending. This * function is intended to be CRLF/LF agnostic. */ -static inline size_t +static PRISM_INLINE size_t match_eol_offset(pm_parser_t *parser, ptrdiff_t offset) { return match_eol_at(parser, parser->current.end + offset); } @@ -7388,7 +7388,7 @@ match_eol_offset(pm_parser_t *parser, ptrdiff_t offset) { * or 0 if it is not a line ending. This function is intended to be CRLF/LF * agnostic. */ -static inline size_t +static PRISM_INLINE size_t match_eol(pm_parser_t *parser) { return match_eol_at(parser, parser->current.end); } @@ -7396,7 +7396,7 @@ match_eol(pm_parser_t *parser) { /** * Skip to the next newline character or NUL byte. */ -static inline const uint8_t * +static PRISM_INLINE const uint8_t * next_newline(const uint8_t *cursor, ptrdiff_t length) { assert(length >= 0); @@ -7409,7 +7409,7 @@ next_newline(const uint8_t *cursor, ptrdiff_t length) { /** * This is equivalent to the predicate of warn_balanced in CRuby. */ -static inline bool +static PRISM_INLINE bool ambiguous_operator_p(const pm_parser_t *parser, bool space_seen) { return !lex_state_p(parser, PM_LEX_STATE_CLASS | PM_LEX_STATE_DOT | PM_LEX_STATE_FNAME | PM_LEX_STATE_ENDFN) && space_seen && !pm_char_is_whitespace(peek(parser)); } @@ -7512,7 +7512,7 @@ parser_lex_magic_comment_boolean_value(const uint8_t *value_start, uint32_t valu } } -static inline bool +static PRISM_INLINE bool pm_char_is_magic_comment_key_delimiter(const uint8_t b) { return b == '\'' || b == '"' || b == ':' || b == ';'; } @@ -7522,7 +7522,7 @@ pm_char_is_magic_comment_key_delimiter(const uint8_t b) { * found, it returns a pointer to the start of the marker. Otherwise it returns * NULL. */ -static inline const uint8_t * +static PRISM_INLINE const uint8_t * parser_lex_magic_comment_emacs_marker(pm_parser_t *parser, const uint8_t *cursor, const uint8_t *end) { // Scan for '*' as the middle character, since it is rarer than '-' in // typical comments and avoids repeated memchr calls for '-' that hit @@ -7545,7 +7545,7 @@ parser_lex_magic_comment_emacs_marker(pm_parser_t *parser, const uint8_t *cursor * It returns true if it consumes the entire comment. Otherwise it returns * false. */ -static inline bool +static PRISM_INLINE bool parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { bool result = true; @@ -7820,7 +7820,7 @@ static const uint32_t context_terminators[] = { [PM_CONTEXT_WHILE] = (1U << PM_TOKEN_KEYWORD_END), }; -static inline bool +static PRISM_INLINE bool context_terminator(pm_context_t context, pm_token_t *token) { return token->type < 32 && (context_terminators[context] & (1U << token->type)); } @@ -7984,7 +7984,7 @@ context_human(pm_context_t context) { /* Specific token lexers */ /******************************************************************************/ -static inline void +static PRISM_INLINE void pm_strspn_number_validate(pm_parser_t *parser, const uint8_t *string, size_t length, const uint8_t *invalid) { if (invalid != NULL) { pm_diagnostic_id_t diag_id = (invalid == (string + length - 1)) ? PM_ERR_INVALID_NUMBER_UNDERSCORE_TRAILING : PM_ERR_INVALID_NUMBER_UNDERSCORE_INNER; @@ -8383,7 +8383,7 @@ lex_global_variable(pm_parser_t *parser) { * * `type` - the expected token type * * `modifier_type` - the expected modifier token type */ -static inline pm_token_type_t +static PRISM_INLINE pm_token_type_t lex_keyword(pm_parser_t *parser, const uint8_t *current_start, const char *value, size_t vlen, pm_lex_state_t state, pm_token_type_t type, pm_token_type_t modifier_type) { if (memcmp(current_start, value, vlen) == 0) { pm_lex_state_t last_state = parser->lex_state; @@ -8724,7 +8724,7 @@ static const bool ascii_printable_chars[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }; -static inline bool +static PRISM_INLINE bool char_is_ascii_printable(const uint8_t b) { return (b < 0x80) && ascii_printable_chars[b]; } @@ -8733,7 +8733,7 @@ char_is_ascii_printable(const uint8_t b) { * Return the value that a hexadecimal digit character represents. For example, * transform 'a' into 10, 'b' into 11, etc. */ -static inline uint8_t +static PRISM_INLINE uint8_t escape_hexadecimal_digit(const uint8_t value) { return (uint8_t) ((value <= '9') ? (value - '0') : (value & 0x7) + 9); } @@ -8743,7 +8743,7 @@ escape_hexadecimal_digit(const uint8_t value) { * digits scanned. This function assumes that the characters have already been * validated. */ -static inline uint32_t +static PRISM_INLINE uint32_t escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const pm_location_t *error_location, const uint8_t flags) { uint32_t value = 0; for (size_t index = 0; index < length; index++) { @@ -8771,7 +8771,7 @@ escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const /** * Escape a single character value based on the given flags. */ -static inline uint8_t +static PRISM_INLINE uint8_t escape_byte(uint8_t value, const uint8_t flags) { if (flags & PM_ESCAPE_FLAG_CONTROL) value &= 0x9f; if (flags & PM_ESCAPE_FLAG_META) value |= 0x80; @@ -8781,7 +8781,7 @@ escape_byte(uint8_t value, const uint8_t flags) { /** * Write a unicode codepoint to the given buffer. */ -static inline void +static PRISM_INLINE void escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t flags, const uint8_t *start, const uint8_t *end, uint32_t value) { // \u escape sequences in string-like structures implicitly change the // encoding to UTF-8 if they are >= 0x80 or if they are used in a character @@ -8817,7 +8817,7 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t fla * When you're writing a byte to the unescape buffer, if the byte is non-ASCII * (i.e., the top bit is set) then it locks in the encoding. */ -static inline void +static PRISM_INLINE void escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t flags, uint8_t byte) { if (byte >= 0x80) { if (parser->explicit_encoding != NULL && parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY && parser->encoding != PM_ENCODING_UTF_8_ENTRY) { @@ -8850,7 +8850,7 @@ escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_ * Note that in this case there is a literal \ byte in the regular expression * source so that the regular expression engine will perform its own unescaping. */ -static inline void +static PRISM_INLINE void escape_write_byte(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expression_buffer, uint8_t flags, uint8_t byte) { if (flags & PM_ESCAPE_FLAG_REGEXP) { pm_buffer_append_format(regular_expression_buffer, "\\x%02X", byte); @@ -8862,7 +8862,7 @@ escape_write_byte(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular /** * Write each byte of the given escaped character into the buffer. */ -static inline void +static PRISM_INLINE void escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expression_buffer, uint8_t flags) { size_t width; if (parser->encoding_changed) { @@ -9455,7 +9455,7 @@ lex_at_variable(pm_parser_t *parser) { /** * Optionally call out to the lex callback if one is provided. */ -static inline void +static PRISM_INLINE void parser_lex_callback(pm_parser_t *parser) { if (parser->lex_callback) { parser->lex_callback->callback(parser->lex_callback->data, parser, &parser->current); @@ -9465,7 +9465,7 @@ parser_lex_callback(pm_parser_t *parser) { /** * Return a new comment node of the specified type. */ -static inline pm_comment_t * +static PRISM_INLINE pm_comment_t * parser_comment(pm_parser_t *parser, pm_comment_type_t type) { pm_comment_t *comment = (pm_comment_t *) pm_arena_alloc(&parser->metadata_arena, sizeof(pm_comment_t), PRISM_ALIGNOF(pm_comment_t)); @@ -9564,7 +9564,7 @@ lex_embdoc(pm_parser_t *parser) { * This happens in a couple places depending on whether or not we have already * lexed a comment. */ -static inline void +static PRISM_INLINE void parser_lex_ignored_newline(pm_parser_t *parser) { parser->current.type = PM_TOKEN_IGNORED_NEWLINE; parser_lex_callback(parser); @@ -9579,7 +9579,7 @@ parser_lex_ignored_newline(pm_parser_t *parser) { * If it is set, then we need to skip past the heredoc body and then clear the * heredoc_end field. */ -static inline void +static PRISM_INLINE void parser_flush_heredoc_end(pm_parser_t *parser) { assert(parser->heredoc_end <= parser->end); parser->next_start = parser->heredoc_end; @@ -9655,12 +9655,12 @@ typedef struct { /** * Push the given byte into the token buffer. */ -static inline void +static PRISM_INLINE void pm_token_buffer_push_byte(pm_token_buffer_t *token_buffer, uint8_t byte) { pm_buffer_append_byte(&token_buffer->buffer, byte); } -static inline void +static PRISM_INLINE void pm_regexp_token_buffer_push_byte(pm_regexp_token_buffer_t *token_buffer, uint8_t byte) { pm_buffer_append_byte(&token_buffer->regexp_buffer, byte); } @@ -9668,7 +9668,7 @@ pm_regexp_token_buffer_push_byte(pm_regexp_token_buffer_t *token_buffer, uint8_t /** * Return the width of the character at the end of the current token. */ -static inline size_t +static PRISM_INLINE size_t parser_char_width(const pm_parser_t *parser) { size_t width; if (parser->encoding_changed) { @@ -9707,7 +9707,7 @@ pm_regexp_token_buffer_push_escaped(pm_regexp_token_buffer_t *token_buffer, pm_p * contents of the token buffer into the current string on the parser so that it * can be attached to the correct node. */ -static inline void +static PRISM_INLINE void pm_token_buffer_copy(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { // Copy buffer data into the arena and free the heap buffer. size_t len = pm_buffer_length(&token_buffer->buffer); @@ -9716,7 +9716,7 @@ pm_token_buffer_copy(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { pm_buffer_free(&token_buffer->buffer); } -static inline void +static PRISM_INLINE void pm_regexp_token_buffer_copy(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { pm_token_buffer_copy(parser, &token_buffer->base); pm_buffer_free(&token_buffer->regexp_buffer); @@ -9805,7 +9805,7 @@ pm_regexp_token_buffer_escape(pm_parser_t *parser, pm_regexp_token_buffer_t *tok * Effectively the same thing as pm_strspn_inline_whitespace, but in the case of * a tilde heredoc expands out tab characters to the nearest tab boundaries. */ -static inline size_t +static PRISM_INLINE size_t pm_heredoc_strspn_inline_whitespace(pm_parser_t *parser, const uint8_t **cursor, pm_heredoc_indent_t indent) { size_t whitespace = 0; @@ -12491,7 +12491,7 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = { /** * Returns true if the current token is of the given type. */ -static inline bool +static PRISM_INLINE bool match1(const pm_parser_t *parser, pm_token_type_t type) { return parser->current.type == type; } @@ -12499,7 +12499,7 @@ match1(const pm_parser_t *parser, pm_token_type_t type) { /** * Returns true if the current token is of either of the given types. */ -static inline bool +static PRISM_INLINE bool match2(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2) { return match1(parser, type1) || match1(parser, type2); } @@ -12507,7 +12507,7 @@ match2(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2) /** * Returns true if the current token is any of the three given types. */ -static inline bool +static PRISM_INLINE bool match3(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3) { return match1(parser, type1) || match1(parser, type2) || match1(parser, type3); } @@ -12515,7 +12515,7 @@ match3(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, /** * Returns true if the current token is any of the four given types. */ -static inline bool +static PRISM_INLINE bool match4(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_token_type_t type4) { return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4); } @@ -12523,7 +12523,7 @@ match4(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, /** * Returns true if the current token is any of the seven given types. */ -static inline bool +static PRISM_INLINE bool match7(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_token_type_t type4, pm_token_type_t type5, pm_token_type_t type6, pm_token_type_t type7) { return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6) || match1(parser, type7); } @@ -12531,7 +12531,7 @@ match7(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, /** * Returns true if the current token is any of the eight given types. */ -static inline bool +static PRISM_INLINE bool match8(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_token_type_t type4, pm_token_type_t type5, pm_token_type_t type6, pm_token_type_t type7, pm_token_type_t type8) { return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6) || match1(parser, type7) || match1(parser, type8); } @@ -12555,7 +12555,7 @@ accept1(pm_parser_t *parser, pm_token_type_t type) { * If the current token is either of the two given types, lex forward by one * token and return true. Otherwise return false. */ -static inline bool +static PRISM_INLINE bool accept2(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2) { if (match2(parser, type1, type2)) { parser_lex(parser); @@ -12671,7 +12671,7 @@ parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, ui * work in all cases, it may need to be refactored later. But it appears to work * for now. */ -static inline bool +static PRISM_INLINE bool token_begins_expression_p(pm_token_type_t type) { switch (type) { case PM_TOKEN_EQUAL_GREATER: @@ -13611,7 +13611,7 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod return contains_keyword_splat; } -static inline bool +static PRISM_INLINE bool argument_allowed_for_bare_hash(pm_parser_t *parser, pm_node_t *argument) { if (pm_symbol_node_label_p(parser, argument)) { return true; @@ -13638,7 +13638,7 @@ argument_allowed_for_bare_hash(pm_parser_t *parser, pm_node_t *argument) { /** * Append an argument to a list of arguments. */ -static inline void +static PRISM_INLINE void parse_arguments_append(pm_parser_t *parser, pm_arguments_t *arguments, pm_node_t *argument) { if (arguments->arguments == NULL) { arguments->arguments = pm_arguments_node_create(parser); @@ -14024,7 +14024,7 @@ update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_ord return true; } -static inline void +static PRISM_INLINE void parse_parameters_handle_trailing_comma( pm_parser_t *parser, pm_parameters_node_t *params, @@ -14564,7 +14564,7 @@ typedef enum { * Parse any number of rescue clauses. This will form a linked list of if * nodes pointing to each other from the top. */ -static inline void +static PRISM_INLINE void parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_t *opening, pm_begin_node_t *parent_node, pm_rescues_type_t type, uint16_t depth) { pm_rescue_node_t *current = NULL; @@ -15337,7 +15337,7 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) { } } -static inline pm_node_t * +static PRISM_INLINE pm_node_t * parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword, uint16_t depth) { context_push(parser, PM_CONTEXT_PREDICATE); pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE; @@ -15359,7 +15359,7 @@ parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_contex return predicate; } -static inline pm_node_t * +static PRISM_INLINE pm_node_t * parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newline_index, bool if_after_else, uint16_t depth) { pm_node_list_t current_block_exits = { 0 }; pm_node_list_t *previous_block_exits = push_block_exits(parser, ¤t_block_exits); @@ -15558,7 +15558,7 @@ PM_STATIC_ASSERT(__LINE__, ((int) PM_STRING_FLAGS_FORCED_UTF8_ENCODING) == ((int * If the encoding was explicitly set through the lexing process, then we need * to potentially mark the string's flags to indicate how to encode it. */ -static inline pm_node_flags_t +static PRISM_INLINE pm_node_flags_t parse_unescaped_encoding(const pm_parser_t *parser) { if (parser->explicit_encoding != NULL) { if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { @@ -15875,7 +15875,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s * Parse an argument to undef which can either be a bare word, a symbol, a * constant, or an interpolated symbol. */ -static inline pm_node_t * +static PRISM_INLINE pm_node_t * parse_undef_argument(pm_parser_t *parser, uint16_t depth) { switch (parser->current.type) { case PM_CASE_OPERATOR: @@ -15910,7 +15910,7 @@ parse_undef_argument(pm_parser_t *parser, uint16_t depth) { * we need to set the lex state to PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM * between the first and second arguments. */ -static inline pm_node_t * +static PRISM_INLINE pm_node_t * parse_alias_argument(pm_parser_t *parser, bool first, uint16_t depth) { switch (parser->current.type) { case PM_CASE_OPERATOR: @@ -16018,7 +16018,7 @@ parse_variable_call(pm_parser_t *parser) { * parser. If it does not match a valid method definition name, then a missing * token is returned. */ -static inline pm_token_t +static PRISM_INLINE pm_token_t parse_method_definition_name(pm_parser_t *parser) { switch (parser->current.type) { case PM_CASE_KEYWORD: @@ -16091,7 +16091,7 @@ parse_heredoc_dedent_string(pm_arena_t *arena, pm_string_t *string, size_t commo * If we end up trimming all of the whitespace from a node and it isn't * part of a line continuation, then we'll drop it from the list entirely. */ -static inline bool +static PRISM_INLINE bool heredoc_dedent_discard_string_node(pm_parser_t *parser, pm_string_node_t *string_node) { if (string_node->unescaped.length == 0) { const uint8_t *cursor = parser->start + PM_LOCATION_START(&string_node->content_loc); @@ -16152,7 +16152,7 @@ parse_strings_empty_content(const uint8_t *location) { /** * Parse a set of strings that could be concatenated together. */ -static inline pm_node_t * +static PRISM_INLINE pm_node_t * parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint16_t depth) { assert(parser->current.type == PM_TOKEN_STRING_BEGIN); bool concating = false; @@ -17303,7 +17303,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag * from its start bounds. If it's a compound node, then we will recursively * apply this function to its value. */ -static inline void +static PRISM_INLINE void parse_negative_numeric(pm_node_t *node) { switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: { @@ -17563,7 +17563,7 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) { * Determine if a given call node looks like a "command", which means it has * arguments but does not have parentheses. */ -static inline bool +static PRISM_INLINE bool pm_call_node_command_p(const pm_call_node_t *node) { return ( (node->opening_loc.length == 0) && @@ -17655,7 +17655,7 @@ pm_block_call_p(const pm_node_t *node) { /** * Parse an expression that begins with the previous node that we just lexed. */ -static inline pm_node_t * +static PRISM_INLINE pm_node_t * parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) { switch (parser->current.type) { case PM_TOKEN_BRACKET_LEFT_ARRAY: { @@ -20567,7 +20567,7 @@ parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const } } -static inline const uint8_t * +static PRISM_INLINE const uint8_t * pm_named_capture_escape_hex(pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end) { cursor++; @@ -20588,7 +20588,7 @@ pm_named_capture_escape_hex(pm_buffer_t *unescaped, const uint8_t *cursor, const return cursor; } -static inline const uint8_t * +static PRISM_INLINE const uint8_t * pm_named_capture_escape_octal(pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end) { uint8_t value = (uint8_t) (*cursor - '0'); cursor++; @@ -20607,7 +20607,7 @@ pm_named_capture_escape_octal(pm_buffer_t *unescaped, const uint8_t *cursor, con return cursor; } -static inline const uint8_t * +static PRISM_INLINE const uint8_t * pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end, const pm_location_t *error_location) { const uint8_t *start = cursor - 1; cursor++; @@ -20799,7 +20799,7 @@ parse_interpolated_regular_expression_named_captures(pm_parser_t *parser, const } } -static inline pm_node_t * +static PRISM_INLINE pm_node_t * parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, uint8_t flags, uint16_t depth) { pm_token_t token = parser->current; @@ -22728,7 +22728,7 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { // PRISM_EXCLUDE_SERIALIZATION define. #ifndef PRISM_EXCLUDE_SERIALIZATION -static inline void +static PRISM_INLINE void pm_serialize_header(pm_buffer_t *buffer) { pm_buffer_append_string(buffer, "PRISM", 5); pm_buffer_append_byte(buffer, PRISM_VERSION_MAJOR); diff --git a/src/regexp.c b/src/regexp.c index 3dfe826104..2955abcfcb 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,5 +1,6 @@ #include "prism/regexp.h" +#include "prism/attribute/inline.h" #include "prism/internal/buffer.h" #include "prism/internal/char.h" #include "prism/internal/diagnostic.h" @@ -118,7 +119,7 @@ typedef struct { * (points into the original source), we can point to the exact error location. * Otherwise, we point to the whole regexp node. */ -static inline void +static PRISM_INLINE void pm_regexp_parse_error(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end, const char *message) { pm_parser_t *pm = parser->parser; uint32_t loc_start, loc_length; @@ -167,7 +168,7 @@ pm_regexp_parser_named_capture(pm_regexp_parser_t *parser, const uint8_t *start, /** * Returns true if the next character is the end of the source. */ -static inline bool +static PRISM_INLINE bool pm_regexp_char_is_eof(pm_regexp_parser_t *parser) { return parser->cursor >= parser->end; } @@ -175,7 +176,7 @@ pm_regexp_char_is_eof(pm_regexp_parser_t *parser) { /** * Optionally accept a char and consume it if it exists. */ -static inline bool +static PRISM_INLINE bool pm_regexp_char_accept(pm_regexp_parser_t *parser, uint8_t value) { if (!pm_regexp_char_is_eof(parser) && *parser->cursor == value) { parser->cursor++; @@ -187,7 +188,7 @@ pm_regexp_char_accept(pm_regexp_parser_t *parser, uint8_t value) { /** * Expect a character to be present and consume it. */ -static inline bool +static PRISM_INLINE bool pm_regexp_char_expect(pm_regexp_parser_t *parser, uint8_t value) { if (!pm_regexp_char_is_eof(parser) && *parser->cursor == value) { parser->cursor++; @@ -219,7 +220,7 @@ pm_regexp_char_find(pm_regexp_parser_t *parser, uint8_t value) { * escape bytes >= 0x80 are followed by a non-hex-escape, this appends a 0x00 * sentinel to separate the groups for later multibyte validation. */ -static inline void +static PRISM_INLINE void pm_regexp_hex_group_boundary(pm_regexp_parser_t *parser) { if (parser->hex_group_active) { pm_buffer_append_byte(&parser->hex_escape_buffer, 0x00); @@ -230,7 +231,7 @@ pm_regexp_hex_group_boundary(pm_regexp_parser_t *parser) { /** * Track a hex escape byte value >= 0x80 for multibyte validation. */ -static inline void +static PRISM_INLINE void pm_regexp_track_hex_escape(pm_regexp_parser_t *parser, uint8_t byte) { if (byte >= 0x80) { pm_buffer_append_byte(&parser->hex_escape_buffer, byte); @@ -247,7 +248,7 @@ pm_regexp_track_hex_escape(pm_regexp_parser_t *parser, uint8_t byte) { /** * Parse a hex digit character and return its value, or -1 if not a hex digit. */ -static inline int +static PRISM_INLINE int pm_regexp_hex_digit_value(uint8_t byte) { if (byte >= '0' && byte <= '9') return byte - '0'; if (byte >= 'a' && byte <= 'f') return byte - 'a' + 10; diff --git a/src/static_literals.c b/src/static_literals.c index 9023f7fff9..b59a0acd12 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -1,5 +1,6 @@ #include "prism/internal/static_literals.h" +#include "prism/attribute/inline.h" #include "prism/internal/buffer.h" #include "prism/internal/integer.h" #include "prism/internal/strings.h" @@ -26,7 +27,7 @@ typedef struct { const char *encoding_name; } pm_static_literals_metadata_t; -static inline uint32_t +static PRISM_INLINE uint32_t murmur_scramble(uint32_t value) { value *= 0xcc9e2d51; value = (value << 15) | (value >> 17); @@ -508,7 +509,7 @@ pm_static_literal_positive_p(const pm_node_t *node) { /** * Create a string-based representation of the given static literal. */ -static inline void +static PRISM_INLINE void pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_metadata_t *metadata, const pm_node_t *node) { switch (PM_NODE_TYPE(node)) { case PM_FALSE_NODE: diff --git a/src/strncasecmp.c b/src/strncasecmp.c index c4e2214ee1..80eb399d04 100644 --- a/src/strncasecmp.c +++ b/src/strncasecmp.c @@ -1,9 +1,11 @@ #include "prism/internal/strncasecmp.h" +#include "prism/attribute/inline.h" + /** * A locale-insensitive version of `tolower(3)` */ -static inline int +static PRISM_INLINE int pm_tolower(int c) { if ('A' <= c && c <= 'Z') { return c | 0x20; diff --git a/src/strpbrk.c b/src/strpbrk.c index 9b28a680c9..d66c0b5fd1 100644 --- a/src/strpbrk.c +++ b/src/strpbrk.c @@ -1,5 +1,6 @@ #include "prism/internal/strpbrk.h" +#include "prism/attribute/inline.h" #include "prism/attribute/unused.h" #include "prism/internal/accel.h" #include "prism/internal/bit.h" @@ -13,7 +14,7 @@ /** * Add an invalid multibyte character error to the parser. */ -static inline void +static PRISM_INLINE void pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, uint32_t start, uint32_t length) { pm_diagnostic_list_append_format(&parser->metadata_arena, &parser->error_list, start, length, PM_ERR_INVALID_MULTIBYTE_CHARACTER, parser->start[start]); } @@ -21,7 +22,7 @@ pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, uint32_t start, uint /** * Set the explicit encoding for the parser to the current encoding. */ -static inline void +static PRISM_INLINE void pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, uint32_t start, uint32_t length) { if (parser->explicit_encoding != NULL) { if (parser->explicit_encoding == parser->encoding) { @@ -67,7 +68,7 @@ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, uint32_t start, uint32_t l * - low_lut/high_lut: nibble-based lookup tables for SIMD matching (NEON/SSSE3) * - table: 256-bit bitmap for scalar fallback matching (all platforms) */ -static inline void +static PRISM_INLINE void pm_strpbrk_cache_update(pm_parser_t *parser, const uint8_t *charset) { // The cache key is the full charset buffer (PM_STRPBRK_CACHE_SIZE bytes). // Since it is always NUL-padded, a fixed-size comparison covers both @@ -104,7 +105,7 @@ pm_strpbrk_cache_update(pm_parser_t *parser, const uint8_t *charset) { #if defined(PRISM_HAS_NEON) #include -static inline bool +static PRISM_INLINE bool scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { pm_strpbrk_cache_update(parser, charset); @@ -159,7 +160,7 @@ scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, c #elif defined(PRISM_HAS_SSSE3) #include -static inline bool +static PRISM_INLINE bool scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { pm_strpbrk_cache_update(parser, charset); @@ -211,7 +212,7 @@ scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, c #elif defined(PRISM_HAS_SWAR) -static inline bool +static PRISM_INLINE bool scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, const uint8_t *charset, size_t *index) { pm_strpbrk_cache_update(parser, charset); @@ -253,7 +254,7 @@ scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, c #else -static inline bool +static PRISM_INLINE bool scan_strpbrk_ascii(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, PRISM_ATTRIBUTE_UNUSED const uint8_t *source, PRISM_ATTRIBUTE_UNUSED size_t maximum, PRISM_ATTRIBUTE_UNUSED const uint8_t *charset, size_t *index) { *index = 0; return false; @@ -264,7 +265,7 @@ scan_strpbrk_ascii(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, PRISM_ATTRIBUTE_U /** * This is the default path. */ -static inline const uint8_t * +static PRISM_INLINE const uint8_t * pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { @@ -302,7 +303,7 @@ pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *chars /** * This is the path when the encoding is ASCII-8BIT. */ -static inline const uint8_t * +static PRISM_INLINE const uint8_t * pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { @@ -319,7 +320,7 @@ pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t /** * This is the slow path that does care about the encoding. */ -static inline const uint8_t * +static PRISM_INLINE const uint8_t * pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { const pm_encoding_t *encoding = parser->encoding; @@ -361,7 +362,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t * This is the fast path that does not care about the encoding because we know * the encoding only supports single-byte characters. */ -static inline const uint8_t * +static PRISM_INLINE const uint8_t * pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t index, size_t maximum, bool validate) { const pm_encoding_t *encoding = parser->encoding; diff --git a/templates/include/prism/node_new.h.erb b/templates/include/prism/node_new.h.erb index 56c214e006..27a7ed22c6 100644 --- a/templates/include/prism/node_new.h.erb +++ b/templates/include/prism/node_new.h.erb @@ -10,6 +10,8 @@ #include "prism/node.h" +#include "prism/attribute/inline.h" + <%- nodes.each do |node| -%> <%- params = node.fields.map(&:c_param) -%> /** @@ -24,7 +26,7 @@ <%- end -%> * @return The newly allocated and initialized node. */ -static inline pm_<%= node.human %>_t * +static PRISM_INLINE pm_<%= node.human %>_t * pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 80d8b5b261..7eab88201f 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -1,5 +1,6 @@ #include "prism/diagnostic.h" +#include "prism/attribute/inline.h" #include "prism/internal/arena.h" #include "prism/internal/list.h" @@ -434,7 +435,7 @@ pm_diagnostic_id_human(pm_diagnostic_id_t diag_id) { return ""; } -static inline const char * +static PRISM_INLINE const char * pm_diagnostic_message(pm_diagnostic_id_t diag_id) { assert(diag_id < PM_DIAGNOSTIC_ID_MAX); @@ -444,7 +445,7 @@ pm_diagnostic_message(pm_diagnostic_id_t diag_id) { return message; } -static inline uint8_t +static PRISM_INLINE uint8_t pm_diagnostic_level(pm_diagnostic_id_t diag_id) { assert(diag_id < PM_DIAGNOSTIC_ID_MAX); diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 60665faba6..39fdcb6269 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -1,6 +1,7 @@ <%# encoding: ASCII -%> #include "prism/prettyprint.h" +#include "prism/attribute/inline.h" #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" @@ -14,14 +15,14 @@ void pm_prettyprint(void) {} #else -static inline void +static PRISM_INLINE void prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) { pm_line_column_t start = pm_line_offset_list_line_column(&parser->line_offsets, location->start, parser->start_line); pm_line_column_t end = pm_line_offset_list_line_column(&parser->line_offsets, location->start + location->length, parser->start_line); pm_buffer_append_format(output_buffer, "(%" PRIi32 ",%" PRIu32 ")-(%" PRIi32 ",%" PRIu32 ")", start.line, start.column, end.line, end.column); } -static inline void +static PRISM_INLINE void prettyprint_constant(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_constant_id_t constant_id) { pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id); pm_buffer_append_format(output_buffer, ":%.*s", (int) constant->length, constant->start); diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index d2ef80b3c4..588e1aac3c 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,5 +1,6 @@ #include "prism.h" +#include "prism/attribute/inline.h" #include "prism/internal/list.h" #include "prism/internal/options.h" @@ -10,13 +11,13 @@ #include -static inline uint32_t +static PRISM_INLINE uint32_t pm_ptrdifft_to_u32(ptrdiff_t value) { assert(value >= 0 && ((unsigned long) value) < UINT32_MAX); return (uint32_t) value; } -static inline uint32_t +static PRISM_INLINE uint32_t pm_sizet_to_u32(size_t value) { assert(value < UINT32_MAX); return (uint32_t) value; From 8d1df7815e498ae8d88985600f356302f081252b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 12:47:08 -0400 Subject: [PATCH 175/289] Move regexp to internal --- Makefile | 6 +++--- docs/fuzzing.md | 15 ++++----------- ext/prism/extension.c | 10 +++++----- fuzz/asan.ignore | 5 ----- fuzz/corpus/regexp/1 | 1 - fuzz/corpus/regexp/2 | 1 - fuzz/corpus/regexp/3 | 1 - fuzz/corpus/regexp/4 | 1 - fuzz/corpus/regexp/6 | 1 - fuzz/corpus/unescape/1 | 1 - fuzz/corpus/unescape/2 | 1 - fuzz/corpus/unescape/3 | 1 - fuzz/regexp.c | 23 ----------------------- fuzz/regexp.sh | 5 ----- include/prism.h | 1 - include/prism/{ => internal}/regexp.h | 15 ++++----------- include/prism/parser.h | 8 ++++++++ prism.gemspec | 3 ++- src/parser.c | 11 +++++++++++ src/prism.c | 3 +++ src/regexp.c | 4 +++- templates/src/serialize.c.erb | 1 + 22 files changed, 44 insertions(+), 74 deletions(-) delete mode 100644 fuzz/asan.ignore delete mode 100644 fuzz/corpus/regexp/1 delete mode 100644 fuzz/corpus/regexp/2 delete mode 100644 fuzz/corpus/regexp/3 delete mode 100644 fuzz/corpus/regexp/4 delete mode 100644 fuzz/corpus/regexp/6 delete mode 100644 fuzz/corpus/unescape/1 delete mode 100644 fuzz/corpus/unescape/2 delete mode 100644 fuzz/corpus/unescape/3 delete mode 100644 fuzz/regexp.c delete mode 100755 fuzz/regexp.sh rename include/prism/{ => internal}/regexp.h (91%) create mode 100644 src/parser.c diff --git a/Makefile b/Makefile index 7f61f753fa..1c56c0d358 100644 --- a/Makefile +++ b/Makefile @@ -70,12 +70,12 @@ build/fuzz.%: $(SOURCES) fuzz/%.c fuzz/fuzz.c $(ECHO) "building $* fuzzer" $(Q) $(MAKEDIRS) $(@D) $(ECHO) "building main fuzz binary" - $(Q) afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^ + $(Q) afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^ $(ECHO) "building cmplog binary" - $(Q) AFL_LLVM_CMPLOG=1 afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@.cmplog $^ + $(Q) AFL_LLVM_CMPLOG=1 afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@.cmplog $^ build/fuzz.heisenbug.%: $(SOURCES) fuzz/%.c fuzz/heisenbug.c - $(Q) afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^ + $(Q) afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^ fuzz-debug: $(ECHO) "entering debug shell" diff --git a/docs/fuzzing.md b/docs/fuzzing.md index b6ec6112a8..c142394b63 100644 --- a/docs/fuzzing.md +++ b/docs/fuzzing.md @@ -5,8 +5,7 @@ We use fuzzing to test the various entrypoints to the library. The fuzzer we use ``` fuzz ├── corpus -│   ├── parse fuzzing corpus for parsing (a symlink to our fixtures) -│   └── regexp fuzzing corpus for regexp +│   └── parse fuzzing corpus for parsing (a symlink to our fixtures) ├── dict a AFL++ dictionary containing various tokens ├── docker │   └── Dockerfile for building a container with the fuzzer toolchain @@ -14,8 +13,6 @@ fuzz ├── heisenbug.c entrypoint for reproducing a crash or hang ├── parse.c fuzz handler for parsing ├── parse.sh script to run parsing fuzzer -├── regexp.c fuzz handler for regular expression parsing -├── regexp.sh script to run regexp fuzzer └── tools    ├── backtrace.sh generates backtrace files for a crash directory    └── minimize.sh generates minimized crash or hang files @@ -23,16 +20,14 @@ fuzz ## Usage -There are currently three fuzzing targets +There is currently one fuzz target: - `pm_serialize_parse` (parse) -- `pm_regexp_parse` (regexp) -Respectively, fuzzing can be performed with +Fuzzing can be performed with ``` make fuzz-run-parse -make fuzz-run-regexp ``` To end a fuzzing job, interrupt with CTRL+C. To enter a container with the fuzzing toolchain and debug utilities, run @@ -43,8 +38,6 @@ make fuzz-debug # Out-of-bounds reads -Currently, encoding functionality implementing the `pm_encoding_t` interface can read outside of inputs. For the time being, ASAN instrumentation is disabled for functions from src/enc. See `fuzz/asan.ignore`. - To disable ASAN read instrumentation globally, use the `FUZZ_FLAGS` environment variable e.g. ``` @@ -55,7 +48,7 @@ Note, that this may make reproducing bugs difficult as they may depend on memory ``` make fuzz-debug # enter the docker container with build tools -make build/fuzz.heisenbug.parse # or .regexp +make build/fuzz.heisenbug.parse ./build/fuzz.heisenbug.parse path-to-problem-input ``` diff --git a/ext/prism/extension.c b/ext/prism/extension.c index c248b0c123..60f33f0cb1 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -692,7 +692,7 @@ parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) { static void parse_lex_encoding_changed_callback(pm_parser_t *parser) { parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data; - parse_lex_data->encoding = rb_enc_find(parser->encoding->name); + parse_lex_data->encoding = rb_enc_find(pm_parser_encoding_name(parser)); // Since the encoding changed, we need to go back and change the encoding of // the tokens that were already lexed. This is only going to end up being @@ -767,7 +767,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod // encoding for the source string and the correct newline offsets. // We do it here because we've already created the Source object and given // it over to all of the tokens, and both of these are only set after pm_parse(). - rb_encoding *encoding = rb_enc_find(parser.encoding->name); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); rb_enc_associate(source_string, encoding); for (size_t index = 0; index < parser.line_offsets.size; index++) { @@ -856,7 +856,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) { pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(&parser); - rb_encoding *encoding = rb_enc_find(parser.encoding->name); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); VALUE source = pm_source_new(&parser, encoding, options->freeze); VALUE value = pm_ast_new(&parser, node, encoding, source, options->freeze); @@ -1075,7 +1075,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_buffer_t buffer; pm_node_t *node = pm_parse_stream(&arena, &parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); - rb_encoding *encoding = rb_enc_find(parser.encoding->name); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); VALUE source = pm_source_new(&parser, encoding, options.freeze); VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze); @@ -1098,7 +1098,7 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_parse(&parser); - rb_encoding *encoding = rb_enc_find(parser.encoding->name); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); VALUE source = pm_source_new(&parser, encoding, options->freeze); VALUE comments = parser_comments(&parser, source, options->freeze); diff --git a/fuzz/asan.ignore b/fuzz/asan.ignore deleted file mode 100644 index 01a130893c..0000000000 --- a/fuzz/asan.ignore +++ /dev/null @@ -1,5 +0,0 @@ -# for now, we ignore the encoding functions as they -# can read out of bounds -[address] -src:src/enc/* - diff --git a/fuzz/corpus/regexp/1 b/fuzz/corpus/regexp/1 deleted file mode 100644 index 9e2c270196..0000000000 --- a/fuzz/corpus/regexp/1 +++ /dev/null @@ -1 +0,0 @@ -(?#comment) diff --git a/fuzz/corpus/regexp/2 b/fuzz/corpus/regexp/2 deleted file mode 100644 index f4119666b1..0000000000 --- a/fuzz/corpus/regexp/2 +++ /dev/null @@ -1 +0,0 @@ -(?:abcd) diff --git a/fuzz/corpus/regexp/3 b/fuzz/corpus/regexp/3 deleted file mode 100644 index 77ee883146..0000000000 --- a/fuzz/corpus/regexp/3 +++ /dev/null @@ -1 +0,0 @@ -(?:subexp) diff --git a/fuzz/corpus/regexp/4 b/fuzz/corpus/regexp/4 deleted file mode 100644 index 60396c3a43..0000000000 --- a/fuzz/corpus/regexp/4 +++ /dev/null @@ -1 +0,0 @@ -!"£$%^&*()/adfas" diff --git a/fuzz/corpus/regexp/6 b/fuzz/corpus/regexp/6 deleted file mode 100644 index 273d11e622..0000000000 --- a/fuzz/corpus/regexp/6 +++ /dev/null @@ -1 +0,0 @@ -word| ) diff --git a/fuzz/corpus/unescape/1 b/fuzz/corpus/unescape/1 deleted file mode 100644 index cd1ed7f860..0000000000 --- a/fuzz/corpus/unescape/1 +++ /dev/null @@ -1 +0,0 @@ -\r\n diff --git a/fuzz/corpus/unescape/2 b/fuzz/corpus/unescape/2 deleted file mode 100644 index dd3221c3a3..0000000000 --- a/fuzz/corpus/unescape/2 +++ /dev/null @@ -1 +0,0 @@ -\\\"\\' diff --git a/fuzz/corpus/unescape/3 b/fuzz/corpus/unescape/3 deleted file mode 100644 index 186bc5a9e0..0000000000 --- a/fuzz/corpus/unescape/3 +++ /dev/null @@ -1 +0,0 @@ -\b\0000 diff --git a/fuzz/regexp.c b/fuzz/regexp.c deleted file mode 100644 index f1a02dedc2..0000000000 --- a/fuzz/regexp.c +++ /dev/null @@ -1,23 +0,0 @@ -#include - -void -regexp_name_callback(const pm_string_t *name, void *data) { - // Do nothing -} - -void -regexp_error_callback(const uint8_t *start, const uint8_t *end, const char *message, void *data) { - // Do nothing -} - -void -harness(const uint8_t *input, size_t size) { - pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, input, size, NULL); - - pm_regexp_parse(&parser, input, size, false, regexp_name_callback, NULL, regexp_error_callback, NULL); - - pm_parser_free(&parser); - pm_arena_free(&arena); -} diff --git a/fuzz/regexp.sh b/fuzz/regexp.sh deleted file mode 100755 index 5cf615a095..0000000000 --- a/fuzz/regexp.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -OUTPUT_DIR=$1 - -afl-fuzz -G 100 -c ./build/fuzz.regexp.cmplog -i ./fuzz/corpus/regexp -o "$OUTPUT_DIR" ./build/fuzz.regexp diff --git a/include/prism.h b/include/prism.h index df7d49af29..b7ef0d126c 100644 --- a/include/prism.h +++ b/include/prism.h @@ -19,7 +19,6 @@ extern "C" { #include "prism/options.h" #include "prism/parser.h" #include "prism/prettyprint.h" -#include "prism/regexp.h" #include "prism/version.h" #include diff --git a/include/prism/regexp.h b/include/prism/internal/regexp.h similarity index 91% rename from include/prism/regexp.h rename to include/prism/internal/regexp.h index 17f0e03019..7f4731967c 100644 --- a/include/prism/regexp.h +++ b/include/prism/internal/regexp.h @@ -1,20 +1,13 @@ /** - * @file regexp.h + * @file internal/regexp.h * * A regular expression parser. */ -#ifndef PRISM_REGEXP_H -#define PRISM_REGEXP_H +#ifndef PRISM_INTERNAL_REGEXP_H +#define PRISM_INTERNAL_REGEXP_H -#include "prism/defines.h" +#include "prism/ast.h" #include "prism/parser.h" -#include "prism/internal/encoding.h" -#include "prism/internal/memchr.h" -#include "prism/strings.h" - -#include -#include -#include /** * Accumulation state for named capture groups found during regexp parsing. diff --git a/include/prism/parser.h b/include/prism/parser.h index 0a0b142952..ae3961899e 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -993,4 +993,12 @@ struct pm_parser { #endif }; +/** + * Returns the name of the encoding that is being used to parse the source. + * + * @param parser the parser whose encoding name we want to get + * @return the name of the encoding that is being used to parse the source + */ +PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser); + #endif diff --git a/prism.gemspec b/prism.gemspec index 6a4b7ba5a4..a18de24742 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -71,7 +71,6 @@ Gem::Specification.new do |spec| "include/prism/options.h", "include/prism/parser.h", "include/prism/prettyprint.h", - "include/prism/regexp.h", "include/prism/static_literals.h", "include/prism/strings.h", "include/prism/version.h", @@ -88,6 +87,7 @@ Gem::Specification.new do |spec| "include/prism/internal/list.h", "include/prism/internal/memchr.h", "include/prism/internal/options.h", + "include/prism/internal/regexp.h", "include/prism/internal/static_literals.h", "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", @@ -192,6 +192,7 @@ Gem::Specification.new do |spec| "src/memchr.c", "src/node.c", "src/options.c", + "src/parser.c", "src/prettyprint.c", "src/prism.c", "src/regexp.c", diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000000..356700796f --- /dev/null +++ b/src/parser.c @@ -0,0 +1,11 @@ +#include "prism/parser.h" + +#include "prism/internal/encoding.h" + +/** + * Returns the name of the encoding that is being used to parse the source. + */ +const char * +pm_parser_encoding_name(const pm_parser_t *parser) { + return parser->encoding->name; +} diff --git a/src/prism.c b/src/prism.c index fed7b069e6..b4bf6b8a14 100644 --- a/src/prism.c +++ b/src/prism.c @@ -6,10 +6,13 @@ #include "prism/internal/char.h" #include "prism/internal/constant_pool.h" #include "prism/internal/diagnostic.h" +#include "prism/internal/encoding.h" #include "prism/internal/integer.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/list.h" +#include "prism/internal/memchr.h" #include "prism/internal/options.h" +#include "prism/internal/regexp.h" #include "prism/internal/static_literals.h" #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" diff --git a/src/regexp.c b/src/regexp.c index 2955abcfcb..7fd80ca696 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,9 +1,11 @@ -#include "prism/regexp.h" +#include "prism/internal/regexp.h" #include "prism/attribute/inline.h" #include "prism/internal/buffer.h" #include "prism/internal/char.h" #include "prism/internal/diagnostic.h" +#include "prism/internal/encoding.h" +#include "prism/internal/memchr.h" #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 588e1aac3c..e1c6709212 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,6 +1,7 @@ #include "prism.h" #include "prism/attribute/inline.h" +#include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" From 2496b0105b1792d6453662d55f68fe4a389111e3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 12:53:18 -0400 Subject: [PATCH 176/289] Split out excludes into its own header --- include/prism/defines.h | 19 +------------------ include/prism/excludes.h | 29 +++++++++++++++++++++++++++++ include/prism/prettyprint.h | 6 ++---- prism.gemspec | 1 + 4 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 include/prism/excludes.h diff --git a/include/prism/defines.h b/include/prism/defines.h index 0d997f9c9b..2189c0cdc7 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -20,6 +20,7 @@ #include "prism/internal/bit.h" #include "prism/allocator.h" +#include "prism/excludes.h" #include "prism/files.h" #include @@ -79,24 +80,6 @@ #define PRISM_ISINF(x) isinf(x) #endif -/** - * If PRISM_BUILD_MINIMAL is defined, then we're going to define every possible - * switch that will turn off certain features of prism. - */ -#ifdef PRISM_BUILD_MINIMAL - /** Exclude the serialization API. */ - #define PRISM_EXCLUDE_SERIALIZATION - - /** Exclude the JSON serialization API. */ - #define PRISM_EXCLUDE_JSON - - /** Exclude the prettyprint API. */ - #define PRISM_EXCLUDE_PRETTYPRINT - - /** Exclude the full set of encodings, using the minimal only. */ - #define PRISM_ENCODING_EXCLUDE_FULL -#endif - /** * Support PRISM_LIKELY and PRISM_UNLIKELY to help the compiler optimize its * branch predication. diff --git a/include/prism/excludes.h b/include/prism/excludes.h new file mode 100644 index 0000000000..8600622f63 --- /dev/null +++ b/include/prism/excludes.h @@ -0,0 +1,29 @@ +/** + * @file excludes.h + * + * A header file that defines macros to exclude certain features of the prism + * library. This is useful for reducing the size of the library when certain + * features are not needed. + */ +#ifndef PRISM_EXCLUDES_H +#define PRISM_EXCLUDES_H + +/** + * If PRISM_BUILD_MINIMAL is defined, then we're going to define every possible + * switch that will turn off certain features of prism. + */ +#ifdef PRISM_BUILD_MINIMAL + /** Exclude the serialization API. */ + #define PRISM_EXCLUDE_SERIALIZATION + + /** Exclude the JSON serialization API. */ + #define PRISM_EXCLUDE_JSON + + /** Exclude the prettyprint API. */ + #define PRISM_EXCLUDE_PRETTYPRINT + + /** Exclude the full set of encodings, using the minimal only. */ + #define PRISM_ENCODING_EXCLUDE_FULL +#endif + +#endif diff --git a/include/prism/prettyprint.h b/include/prism/prettyprint.h index 55da182f53..65c4302644 100644 --- a/include/prism/prettyprint.h +++ b/include/prism/prettyprint.h @@ -6,16 +6,14 @@ #ifndef PRISM_PRETTYPRINT_H #define PRISM_PRETTYPRINT_H -#include "prism/defines.h" +#include "prism/excludes.h" #ifdef PRISM_EXCLUDE_PRETTYPRINT -void pm_prettyprint(void); +#define pm_prettyprint(output_buffer_, parser_, node_) #else -#include - #include "prism/ast.h" #include "prism/buffer.h" #include "prism/parser.h" diff --git a/prism.gemspec b/prism.gemspec index a18de24742..df4dd9dd22 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -62,6 +62,7 @@ Gem::Specification.new do |spec| "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", + "include/prism/excludes.h", "include/prism/files.h", "include/prism/integer.h", "include/prism/line_offset_list.h", From 4090539e4a582baec27a705ba301bdcf584f1e86 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 12:56:18 -0400 Subject: [PATCH 177/289] Trim down parser.h --- include/prism/parser.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index ae3961899e..bb358bb9a8 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -6,19 +6,17 @@ #ifndef PRISM_PARSER_H #define PRISM_PARSER_H -#include "prism/defines.h" - #include "prism/arena.h" #include "prism/ast.h" -#include "prism/constant_pool.h" #include "prism/encoding.h" #include "prism/line_offset_list.h" #include "prism/list.h" #include "prism/options.h" #include "prism/static_literals.h" -#include "prism/strings.h" #include +#include +#include /** * This enum provides various bits that represent different kinds of states that From 76904582b19aa5c7d40b7a8b7335b0759a6ea07c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 12:59:42 -0400 Subject: [PATCH 178/289] Trim down node.h --- include/prism/node.h | 6 +++--- src/prism.c | 1 + templates/src/node.c.erb | 2 ++ templates/src/serialize.c.erb | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/prism/node.h b/include/prism/node.h index 560936dc08..e59baedbd0 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -6,9 +6,9 @@ #ifndef PRISM_NODE_H #define PRISM_NODE_H -#include "prism/defines.h" -#include "prism/internal/buffer.h" -#include "prism/parser.h" +#include "prism/attribute/exported.h" +#include "prism/arena.h" +#include "prism/ast.h" /** * Loop through each node in the node list, writing each node to the given diff --git a/src/prism.c b/src/prism.c index b4bf6b8a14..31c8881fa0 100644 --- a/src/prism.c +++ b/src/prism.c @@ -3,6 +3,7 @@ #include "prism/internal/accel.h" #include "prism/internal/arena.h" #include "prism/internal/bit.h" +#include "prism/internal/buffer.h" #include "prism/internal/char.h" #include "prism/internal/constant_pool.h" #include "prism/internal/diagnostic.h" diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 4e1b1cdaae..35ef8d9be5 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -1,8 +1,10 @@ #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" #include "prism/node.h" +#include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" +#include "prism/parser.h" #include diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index e1c6709212..39eb2b521a 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,6 +1,7 @@ #include "prism.h" #include "prism/attribute/inline.h" +#include "prism/internal/buffer.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" From 8ad880255d47a3f43f4cb95dc0189a285d7ab8fa Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 13:33:59 -0400 Subject: [PATCH 179/289] More splitting of headers --- include/prism/{internal => }/accel.h | 2 +- include/prism/attribute/fallthrough.h | 25 +++++++++++++++++++++++++ include/prism/defines.h | 18 +++--------------- include/prism/internal/isinf.h | 19 +++++++++++++++++++ include/prism/parser.h | 1 + prism.gemspec | 4 +++- src/prism.c | 2 +- src/regexp.c | 4 ++++ src/static_literals.c | 5 +++++ src/strpbrk.c | 2 +- templates/include/prism/ast.h.erb | 3 +-- templates/src/diagnostic.c.erb | 5 +++++ templates/src/node.c.erb | 2 ++ templates/src/prettyprint.c.erb | 2 ++ templates/src/token_type.c.erb | 4 ++-- 15 files changed, 75 insertions(+), 23 deletions(-) rename include/prism/{internal => }/accel.h (96%) create mode 100644 include/prism/attribute/fallthrough.h create mode 100644 include/prism/internal/isinf.h diff --git a/include/prism/internal/accel.h b/include/prism/accel.h similarity index 96% rename from include/prism/internal/accel.h rename to include/prism/accel.h index 971c9b2473..c8fc1433c6 100644 --- a/include/prism/internal/accel.h +++ b/include/prism/accel.h @@ -1,5 +1,5 @@ /** - * @file internal/accel.h + * @file accel.h * * Platform detection for acceleration implementations. */ diff --git a/include/prism/attribute/fallthrough.h b/include/prism/attribute/fallthrough.h new file mode 100644 index 0000000000..aefe3e48d7 --- /dev/null +++ b/include/prism/attribute/fallthrough.h @@ -0,0 +1,25 @@ +/** + * @file attribute/fallthrough.h + * + * Define the PRISM_FALLTHROUGH macro, which is used to annotate intentional + * fallthroughs in switch statements. + */ +#ifndef PRISM_FALLTHROUGH_H +#define PRISM_FALLTHROUGH_H + +/** + * We use -Wimplicit-fallthrough to guard potentially unintended fall-through + * between cases of a switch. Use PRISM_FALLTHROUGH to explicitly annotate cases + * where the fallthrough is intentional. + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L /* C23 or later */ + #define PRISM_FALLTHROUGH [[fallthrough]]; +#elif defined(__GNUC__) || defined(__clang__) + #define PRISM_FALLTHROUGH __attribute__((fallthrough)); +#elif defined(_MSC_VER) + #define PRISM_FALLTHROUGH __fallthrough; +#else + #define PRISM_FALLTHROUGH +#endif + +#endif diff --git a/include/prism/defines.h b/include/prism/defines.h index 2189c0cdc7..fb88df62b1 100644 --- a/include/prism/defines.h +++ b/include/prism/defines.h @@ -11,14 +11,16 @@ #include "prism/attribute/align.h" #include "prism/attribute/exported.h" +#include "prism/attribute/fallthrough.h" #include "prism/attribute/flex_array.h" #include "prism/attribute/format.h" #include "prism/attribute/inline.h" #include "prism/attribute/unused.h" -#include "prism/internal/accel.h" #include "prism/internal/bit.h" +#include "prism/internal/isinf.h" +#include "prism/accel.h" #include "prism/allocator.h" #include "prism/excludes.h" #include "prism/files.h" @@ -98,18 +100,4 @@ #define PRISM_UNLIKELY(x) (x) #endif -/** - * We use -Wimplicit-fallthrough to guard potentially unintended fall-through between cases of a switch. - * Use PRISM_FALLTHROUGH to explicitly annotate cases where the fallthrough is intentional. - */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L // C23 or later - #define PRISM_FALLTHROUGH [[fallthrough]]; -#elif defined(__GNUC__) || defined(__clang__) - #define PRISM_FALLTHROUGH __attribute__((fallthrough)); -#elif defined(_MSC_VER) - #define PRISM_FALLTHROUGH __fallthrough; -#else - #define PRISM_FALLTHROUGH -#endif - #endif diff --git a/include/prism/internal/isinf.h b/include/prism/internal/isinf.h new file mode 100644 index 0000000000..569f4726e7 --- /dev/null +++ b/include/prism/internal/isinf.h @@ -0,0 +1,19 @@ +/** + * @file isinf.h + */ +#ifndef PRISM_ISINF_H +#define PRISM_ISINF_H + +/** + * isinf on POSIX systems accepts a float, a double, or a long double. But mingw + * didn't provide an isinf macro, only an isinf function that only accepts + * floats, so we need to use _finite instead. + */ +#ifdef __MINGW64__ + #include + #define PRISM_ISINF(x) (!_finite(x)) +#else + #define PRISM_ISINF(x) isinf(x) +#endif + +#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index bb358bb9a8..9dc666661b 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -6,6 +6,7 @@ #ifndef PRISM_PARSER_H #define PRISM_PARSER_H +#include "prism/accel.h" #include "prism/arena.h" #include "prism/ast.h" #include "prism/encoding.h" diff --git a/prism.gemspec b/prism.gemspec index df4dd9dd22..fd216e13a7 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -48,11 +48,13 @@ Gem::Specification.new do |spec| "include/prism.h", "include/prism/attribute/align.h", "include/prism/attribute/exported.h", + "include/prism/attribute/fallthrough.h", "include/prism/attribute/flex_array.h", "include/prism/attribute/force_inline.h", "include/prism/attribute/format.h", "include/prism/attribute/inline.h", "include/prism/attribute/unused.h", + "include/prism/accel.h", "include/prism/allocator.h", "include/prism/arena.h", "include/prism/ast.h", @@ -75,7 +77,6 @@ Gem::Specification.new do |spec| "include/prism/static_literals.h", "include/prism/strings.h", "include/prism/version.h", - "include/prism/internal/accel.h", "include/prism/internal/arena.h", "include/prism/internal/bit.h", "include/prism/internal/buffer.h", @@ -84,6 +85,7 @@ Gem::Specification.new do |spec| "include/prism/internal/diagnostic.h", "include/prism/internal/encoding.h", "include/prism/internal/integer.h", + "include/prism/internal/isinf.h", "include/prism/internal/line_offset_list.h", "include/prism/internal/list.h", "include/prism/internal/memchr.h", diff --git a/src/prism.c b/src/prism.c index 31c8881fa0..eefd24e711 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,6 +1,5 @@ #include "prism.h" -#include "prism/internal/accel.h" #include "prism/internal/arena.h" #include "prism/internal/bit.h" #include "prism/internal/buffer.h" @@ -19,6 +18,7 @@ #include "prism/internal/strncasecmp.h" #include "prism/internal/strpbrk.h" +#include "prism/accel.h" #include "prism/node_new.h" /** diff --git a/src/regexp.c b/src/regexp.c index 7fd80ca696..0ed501092b 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,6 +1,7 @@ #include "prism/internal/regexp.h" #include "prism/attribute/inline.h" +#include "prism/attribute/fallthrough.h" #include "prism/internal/buffer.h" #include "prism/internal/char.h" #include "prism/internal/diagnostic.h" @@ -9,6 +10,9 @@ #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" +#include +#include + /** The maximum depth of nested groups allowed in a regular expression. */ #define PM_REGEXP_PARSE_DEPTH_MAX 4096 diff --git a/src/static_literals.c b/src/static_literals.c index b59a0acd12..73e479f8d3 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -1,12 +1,17 @@ #include "prism/internal/static_literals.h" #include "prism/attribute/inline.h" +#include "prism/attribute/unused.h" #include "prism/internal/buffer.h" #include "prism/internal/integer.h" +#include "prism/internal/isinf.h" #include "prism/internal/strings.h" #include "prism/allocator.h" +#include +#include #include +#include /** * A small struct used for passing around a subset of the information that is diff --git a/src/strpbrk.c b/src/strpbrk.c index d66c0b5fd1..59330fc172 100644 --- a/src/strpbrk.c +++ b/src/strpbrk.c @@ -2,10 +2,10 @@ #include "prism/attribute/inline.h" #include "prism/attribute/unused.h" -#include "prism/internal/accel.h" #include "prism/internal/bit.h" #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" +#include "prism/accel.h" #include #include diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 783eaca2dd..af3403c293 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -8,12 +8,11 @@ #ifndef PRISM_AST_H #define PRISM_AST_H -#include "prism/defines.h" +#include "prism/attribute/align.h" #include "prism/constant_pool.h" #include "prism/integer.h" #include "prism/strings.h" -#include #include #include diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 7eab88201f..8a4abc14eb 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -4,6 +4,11 @@ #include "prism/internal/arena.h" #include "prism/internal/list.h" +#include +#include +#include +#include + #define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %> /** This struct holds the data for each diagnostic. */ diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 35ef8d9be5..c0016647a8 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -6,7 +6,9 @@ #include "prism/internal/integer.h" #include "prism/parser.h" +#include #include +#include /** * Attempts to grow the node list to the next size. If there is already diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 39fdcb6269..db2d52ddcf 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -6,6 +6,8 @@ #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" +#include + // We optionally support pretty printing nodes. For systems that don't want or // need this functionality, it can be turned off with the // PRISM_EXCLUDE_PRETTYPRINT define. diff --git a/templates/src/token_type.c.erb b/templates/src/token_type.c.erb index c08a0e7921..cdf4e73658 100644 --- a/templates/src/token_type.c.erb +++ b/templates/src/token_type.c.erb @@ -1,7 +1,7 @@ -#include - #include "prism/ast.h" +#include + /** * Returns a string representation of the given token type. */ From 400b21739347720655b8b9b3eacc4f1b0c27b3e1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 13:41:06 -0400 Subject: [PATCH 180/289] Remove defines --- docs/build_system.md | 2 +- include/prism.h | 2 - include/prism/defines.h | 103 ----------------------------- prism.gemspec | 1 - rust/ruby-prism-sys/build/main.rs | 1 - src/prism.c | 52 +++++++++++++++ templates/ext/prism/api_node.c.erb | 1 + 7 files changed, 54 insertions(+), 108 deletions(-) delete mode 100644 include/prism/defines.h diff --git a/docs/build_system.md b/docs/build_system.md index 096edb8ad0..2e2749e62c 100644 --- a/docs/build_system.md +++ b/docs/build_system.md @@ -87,7 +87,7 @@ If you need to use memory allocation functions implemented outside of the standa * Additionally, include `-I [path/to/custom_allocator]` where your `prism_xallocator.h` is located * Link the implementation of `prism_xallocator.c` that contains functions declared in `prism_xallocator.h` -For further clarity, refer to `include/prism/defines.h`. +For further clarity, refer to `include/prism/allocator.h`. ### Building prism from source as a C library diff --git a/include/prism.h b/include/prism.h index b7ef0d126c..55ce7e4745 100644 --- a/include/prism.h +++ b/include/prism.h @@ -10,8 +10,6 @@ extern "C" { #endif -#include "prism/defines.h" - #include "prism/arena.h" #include "prism/ast.h" #include "prism/diagnostic.h" diff --git a/include/prism/defines.h b/include/prism/defines.h deleted file mode 100644 index fb88df62b1..0000000000 --- a/include/prism/defines.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file defines.h - * - * Macro definitions used throughout the prism library. - * - * This file should be included first by any *.h or *.c in prism for consistency - * and to ensure that the macros are defined before they are used. - */ -#ifndef PRISM_DEFINES_H -#define PRISM_DEFINES_H - -#include "prism/attribute/align.h" -#include "prism/attribute/exported.h" -#include "prism/attribute/fallthrough.h" -#include "prism/attribute/flex_array.h" -#include "prism/attribute/format.h" -#include "prism/attribute/inline.h" -#include "prism/attribute/unused.h" - -#include "prism/internal/bit.h" -#include "prism/internal/isinf.h" - -#include "prism/accel.h" -#include "prism/allocator.h" -#include "prism/excludes.h" -#include "prism/files.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * We want to be able to use the PRI* macros for printing out integers, but on - * some platforms they aren't included unless this is already defined. - */ -#define __STDC_FORMAT_MACROS -// Include sys/types.h before inttypes.h to work around issue with -// certain versions of GCC and newlib which causes omission of PRIx64 -#include -#include - -/** - * When we are parsing using recursive descent, we want to protect against - * malicious payloads that could attempt to crash our parser. We do this by - * specifying a maximum depth to which we are allowed to recurse. - */ -#ifndef PRISM_DEPTH_MAXIMUM - #define PRISM_DEPTH_MAXIMUM 10000 -#endif - -/** - * A simple utility macro to concatenate two tokens together, necessary when one - * of the tokens is itself a macro. - */ -#define PM_CONCATENATE(left, right) left ## right - -/** - * We want to be able to use static assertions, but they weren't standardized - * until C11. As such, we polyfill it here by making a hacky typedef that will - * fail to compile due to a negative array size if the condition is false. - */ -#if defined(_Static_assert) -# define PM_STATIC_ASSERT(line, condition, message) _Static_assert(condition, message) -#else -# define PM_STATIC_ASSERT(line, condition, message) typedef char PM_CONCATENATE(static_assert_, line)[(condition) ? 1 : -1] -#endif - -/** - * isinf on POSIX systems it accepts a float, a double, or a long double. - * But mingw didn't provide an isinf macro, only an isinf function that only - * accepts floats, so we need to use _finite instead. - */ -#ifdef __MINGW64__ - #include - #define PRISM_ISINF(x) (!_finite(x)) -#else - #define PRISM_ISINF(x) isinf(x) -#endif - -/** - * Support PRISM_LIKELY and PRISM_UNLIKELY to help the compiler optimize its - * branch predication. - */ -#if defined(__GNUC__) || defined(__clang__) - /** The compiler should predicate that this branch will be taken. */ - #define PRISM_LIKELY(x) __builtin_expect(!!(x), 1) - - /** The compiler should predicate that this branch will not be taken. */ - #define PRISM_UNLIKELY(x) __builtin_expect(!!(x), 0) -#else - /** Void because this platform does not support branch prediction hints. */ - #define PRISM_LIKELY(x) (x) - - /** Void because this platform does not support branch prediction hints. */ - #define PRISM_UNLIKELY(x) (x) -#endif - -#endif diff --git a/prism.gemspec b/prism.gemspec index fd216e13a7..e2dc185e81 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -61,7 +61,6 @@ Gem::Specification.new do |spec| "include/prism/buffer.h", "include/prism/constant_pool.h", "include/prism/debug_allocator.h", - "include/prism/defines.h", "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/excludes.h", diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 0de2b3caba..18441ed623 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -115,7 +115,6 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .derive_default(true) .generate_block(true) .generate_comments(true) - .header(ruby_include_path.join("prism/defines.h").to_str().unwrap()) .header(ruby_include_path.join("prism.h").to_str().unwrap()) .clang_arg(format!("-I{}", ruby_include_path.to_str().unwrap())) .clang_arg("-fparse-all-comments") diff --git a/src/prism.c b/src/prism.c index eefd24e711..0e96ee7cff 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,5 +1,8 @@ #include "prism.h" +#include "prism/attribute/fallthrough.h" +#include "prism/attribute/unused.h" + #include "prism/internal/arena.h" #include "prism/internal/bit.h" #include "prism/internal/buffer.h" @@ -8,6 +11,7 @@ #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" #include "prism/internal/integer.h" +#include "prism/internal/isinf.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/list.h" #include "prism/internal/memchr.h" @@ -17,10 +21,58 @@ #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" #include "prism/internal/strpbrk.h" +#include "prism/allocator.h" #include "prism/accel.h" #include "prism/node_new.h" +#include +#include + +/** + * When we are parsing using recursive descent, we want to protect against + * malicious payloads that could attempt to crash our parser. We do this by + * specifying a maximum depth to which we are allowed to recurse. + */ +#ifndef PRISM_DEPTH_MAXIMUM + #define PRISM_DEPTH_MAXIMUM 10000 +#endif + +/** + * A simple utility macro to concatenate two tokens together, necessary when one + * of the tokens is itself a macro. + */ +#define PM_CONCATENATE(left, right) left ## right + +/** + * We want to be able to use static assertions, but they weren't standardized + * until C11. As such, we polyfill it here by making a hacky typedef that will + * fail to compile due to a negative array size if the condition is false. + */ +#if defined(_Static_assert) +# define PM_STATIC_ASSERT(line, condition, message) _Static_assert(condition, message) +#else +# define PM_STATIC_ASSERT(line, condition, message) typedef char PM_CONCATENATE(static_assert_, line)[(condition) ? 1 : -1] +#endif + +/** + * Support PRISM_LIKELY and PRISM_UNLIKELY to help the compiler optimize its + * branch predication. + */ +#if defined(__GNUC__) || defined(__clang__) + /** The compiler should predicate that this branch will be taken. */ + #define PRISM_LIKELY(x) __builtin_expect(!!(x), 1) + + /** The compiler should predicate that this branch will not be taken. */ + #define PRISM_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else + /** Void because this platform does not support branch prediction hints. */ + #define PRISM_LIKELY(x) (x) + + /** Void because this platform does not support branch prediction hints. */ + #define PRISM_UNLIKELY(x) (x) +#endif + /** * The prism version and the serialization format. */ diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index e3bcf116cc..ea9754bdfd 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -1,5 +1,6 @@ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" #include "prism/extension.h" +#include "prism/allocator.h" extern VALUE rb_cPrism; extern VALUE rb_cPrismNode; From 01d575aa2fc5faec7f567265654c9bf1295b69a4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 13:53:30 -0400 Subject: [PATCH 181/289] Move compiler detection stuff into include/prism/compiler --- include/prism/accel.h | 21 ------------- include/prism/arena.h | 6 ++-- include/prism/attribute/format.h | 28 ----------------- include/prism/attribute/inline.h | 31 ------------------- include/prism/buffer.h | 2 +- include/prism/compiler/accel.h | 19 ++++++++++++ include/prism/{attribute => compiler}/align.h | 8 ++--- .../prism/{attribute => compiler}/exported.h | 8 ++--- .../{attribute => compiler}/fallthrough.h | 9 ++---- .../{attribute => compiler}/flex_array.h | 10 +++--- .../{attribute => compiler}/force_inline.h | 12 +++---- include/prism/compiler/format.h | 25 +++++++++++++++ include/prism/compiler/inline.h | 17 ++++++++++ .../prism/{attribute => compiler}/unused.h | 9 ++---- include/prism/internal/arena.h | 4 +-- include/prism/internal/bit.h | 2 +- include/prism/internal/buffer.h | 2 +- include/prism/internal/char.h | 2 +- include/prism/internal/line_offset_list.h | 2 +- include/prism/line_offset_list.h | 2 +- include/prism/node.h | 2 +- include/prism/parser.h | 2 +- include/prism/strings.h | 2 +- prism.gemspec | 18 +++++------ src/buffer.c | 2 +- src/char.c | 2 +- src/constant_pool.c | 4 +-- src/encoding.c | 2 +- src/line_offset_list.c | 2 +- src/options.c | 2 +- src/prism.c | 6 ++-- src/regexp.c | 4 +-- src/static_literals.c | 4 +-- src/strncasecmp.c | 2 +- src/strpbrk.c | 7 +++-- templates/include/prism/ast.h.erb | 2 +- templates/include/prism/diagnostic.h.erb | 2 +- templates/include/prism/node_new.h.erb | 2 +- templates/src/diagnostic.c.erb | 2 +- templates/src/prettyprint.c.erb | 2 +- templates/src/serialize.c.erb | 2 +- 41 files changed, 130 insertions(+), 162 deletions(-) delete mode 100644 include/prism/accel.h delete mode 100644 include/prism/attribute/format.h delete mode 100644 include/prism/attribute/inline.h create mode 100644 include/prism/compiler/accel.h rename include/prism/{attribute => compiler}/align.h (89%) rename include/prism/{attribute => compiler}/exported.h (79%) rename include/prism/{attribute => compiler}/fallthrough.h (73%) rename include/prism/{attribute => compiler}/flex_array.h (62%) rename include/prism/{attribute => compiler}/force_inline.h (55%) create mode 100644 include/prism/compiler/format.h create mode 100644 include/prism/compiler/inline.h rename include/prism/{attribute => compiler}/unused.h (62%) diff --git a/include/prism/accel.h b/include/prism/accel.h deleted file mode 100644 index c8fc1433c6..0000000000 --- a/include/prism/accel.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @file accel.h - * - * Platform detection for acceleration implementations. - */ -#ifndef PRISM_INTERNAL_ACCEL_H -#define PRISM_INTERNAL_ACCEL_H - -/** - * Platform detection for SIMD / fast-path implementations. At most one of - * these macros is defined, selecting the best available vectorization strategy. - */ -#if (defined(__aarch64__) && defined(__ARM_NEON)) || (defined(_MSC_VER) && defined(_M_ARM64)) - #define PRISM_HAS_NEON -#elif (defined(__x86_64__) && defined(__SSSE3__)) || (defined(_MSC_VER) && defined(_M_X64)) - #define PRISM_HAS_SSSE3 -#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define PRISM_HAS_SWAR -#endif - -#endif diff --git a/include/prism/arena.h b/include/prism/arena.h index dd8ee09ceb..73f2fab900 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -6,9 +6,9 @@ #ifndef PRISM_ARENA_H #define PRISM_ARENA_H -#include "prism/attribute/exported.h" -#include "prism/attribute/flex_array.h" -#include "prism/attribute/force_inline.h" +#include "prism/compiler/exported.h" +#include "prism/compiler/flex_array.h" +#include "prism/compiler/force_inline.h" #include diff --git a/include/prism/attribute/format.h b/include/prism/attribute/format.h deleted file mode 100644 index 4ad99fe125..0000000000 --- a/include/prism/attribute/format.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file attribute/format.h - * - * Macro definition for specifying that a function accepts variadic parameters - * that look like printf format strings. - */ -#ifndef PRISM_FORMAT_H -#define PRISM_FORMAT_H - -/** - * Certain compilers support specifying that a function accepts variadic - * parameters that look like printf format strings to provide a better developer - * experience when someone is using the function. This macro does that in a - * compiler-agnostic way. - */ -#if defined(__GNUC__) -# if defined(__MINGW_PRINTF_FORMAT) -# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) __attribute__((format(__MINGW_PRINTF_FORMAT, string_index_, argument_index_))) -# else -# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) __attribute__((format(printf, string_index_, argument_index_))) -# endif -#elif defined(__clang__) -# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) __attribute__((__format__(__printf__, string_index_, argument_index_))) -#else -# define PRISM_ATTRIBUTE_FORMAT(string_index_, argument_index_) -#endif - -#endif diff --git a/include/prism/attribute/inline.h b/include/prism/attribute/inline.h deleted file mode 100644 index 79a5dfcbee..0000000000 --- a/include/prism/attribute/inline.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file attribute/inline.h - * - * Macro definitions for forcing a function to be inlined at every call site. - */ -#ifndef PRISM_INLINE_H -#define PRISM_INLINE_H - -/** - * Old Visual Studio versions do not support the inline keyword, so we need to - * define it to be __inline. - */ -#if defined(_MSC_VER) && !defined(inline) -# define PRISM_INLINE __inline -#else -# define PRISM_INLINE inline -#endif - -/** - * Force a function to be inlined at every call site. Use sparingly — only for - * small, hot functions where the compiler's heuristics fail to inline. - */ -#if defined(_MSC_VER) -# define PRISM_FORCE_INLINE __forceinline -#elif defined(__GNUC__) || defined(__clang__) -# define PRISM_FORCE_INLINE inline __attribute__((always_inline)) -#else -# define PRISM_FORCE_INLINE PRISM_INLINE -#endif - -#endif diff --git a/include/prism/buffer.h b/include/prism/buffer.h index 90f7c9198e..41b0fd8dc0 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -6,7 +6,7 @@ #ifndef PRISM_BUFFER_H #define PRISM_BUFFER_H -#include "prism/attribute/exported.h" +#include "prism/compiler/exported.h" #include #include diff --git a/include/prism/compiler/accel.h b/include/prism/compiler/accel.h new file mode 100644 index 0000000000..be23236d1d --- /dev/null +++ b/include/prism/compiler/accel.h @@ -0,0 +1,19 @@ +/** + * @file compiler/accel.h + */ +#ifndef PRISM_COMPILER_ACCEL_H +#define PRISM_COMPILER_ACCEL_H + +/** + * Platform detection for SIMD/fast-path implementations. At most one of these + * macros is defined, selecting the best available vectorization strategy. + */ +#if (defined(__aarch64__) && defined(__ARM_NEON)) || (defined(_MSC_VER) && defined(_M_ARM64)) +# define PRISM_HAS_NEON +#elif (defined(__x86_64__) && defined(__SSSE3__)) || (defined(_MSC_VER) && defined(_M_X64)) +# define PRISM_HAS_SSSE3 +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define PRISM_HAS_SWAR +#endif + +#endif diff --git a/include/prism/attribute/align.h b/include/prism/compiler/align.h similarity index 89% rename from include/prism/attribute/align.h rename to include/prism/compiler/align.h index 9a21b8d6ec..22cb49a48c 100644 --- a/include/prism/attribute/align.h +++ b/include/prism/compiler/align.h @@ -1,10 +1,8 @@ /** - * @file attribute/align.h - * - * Alignment macros used throughout the prism library. + * @file compiler/align.h */ -#ifndef PRISM_ALIGN_H -#define PRISM_ALIGN_H +#ifndef PRISM_COMPILER_ALIGN_H +#define PRISM_COMPILER_ALIGN_H /** * Compiler-agnostic macros for specifying alignment of types and variables. diff --git a/include/prism/attribute/exported.h b/include/prism/compiler/exported.h similarity index 79% rename from include/prism/attribute/exported.h rename to include/prism/compiler/exported.h index 8cb24848d1..823773ecbb 100644 --- a/include/prism/attribute/exported.h +++ b/include/prism/compiler/exported.h @@ -1,10 +1,8 @@ /** - * @file attribute/exported.h - * - * Macro definitions for make functions publically visible. + * @file compiler/exported.h */ -#ifndef PRISM_EXPORTED_H -#define PRISM_EXPORTED_H +#ifndef PRISM_COMPILER_EXPORTED_H +#define PRISM_COMPILER_EXPORTED_H /** * By default, we compile with -fvisibility=hidden. When this is enabled, we diff --git a/include/prism/attribute/fallthrough.h b/include/prism/compiler/fallthrough.h similarity index 73% rename from include/prism/attribute/fallthrough.h rename to include/prism/compiler/fallthrough.h index aefe3e48d7..ce1b450e8a 100644 --- a/include/prism/attribute/fallthrough.h +++ b/include/prism/compiler/fallthrough.h @@ -1,11 +1,8 @@ /** - * @file attribute/fallthrough.h - * - * Define the PRISM_FALLTHROUGH macro, which is used to annotate intentional - * fallthroughs in switch statements. + * @file compiler/fallthrough.h */ -#ifndef PRISM_FALLTHROUGH_H -#define PRISM_FALLTHROUGH_H +#ifndef PRISM_COMPILER_FALLTHROUGH_H +#define PRISM_COMPILER_FALLTHROUGH_H /** * We use -Wimplicit-fallthrough to guard potentially unintended fall-through diff --git a/include/prism/attribute/flex_array.h b/include/prism/compiler/flex_array.h similarity index 62% rename from include/prism/attribute/flex_array.h rename to include/prism/compiler/flex_array.h index 8daefba32b..7504b5fdd3 100644 --- a/include/prism/attribute/flex_array.h +++ b/include/prism/compiler/flex_array.h @@ -1,13 +1,11 @@ /** - * @file attribute/flex_array.h - * - * Macro definitions for working with flexible array members. + * @file compiler/flex_array.h */ -#ifndef PRISM_FLEX_ARRAY_H -#define PRISM_FLEX_ARRAY_H +#ifndef PRISM_COMPILER_FLEX_ARRAY_H +#define PRISM_COMPILER_FLEX_ARRAY_H /** - * A macro for defining a flexible array member. C99 supports `data[]`, GCC + * A macro for helper define a flexible array member. C99 supports `data[]`, GCC * supports `data[0]` as an extension, and older compilers require `data[1]`. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) diff --git a/include/prism/attribute/force_inline.h b/include/prism/compiler/force_inline.h similarity index 55% rename from include/prism/attribute/force_inline.h rename to include/prism/compiler/force_inline.h index 7f1e8c57f8..e189d592d6 100644 --- a/include/prism/attribute/force_inline.h +++ b/include/prism/compiler/force_inline.h @@ -1,12 +1,10 @@ /** - * @file attribute/force_inline.h - * - * Macro definitions for forcing a function to be inlined at every call site. + * @file compiler/force_inline.h */ -#ifndef PRISM_FORCE_INLINE_H -#define PRISM_FORCE_INLINE_H +#ifndef PRISM_COMPILER_FORCE_INLINE_H +#define PRISM_COMPILER_FORCE_INLINE_H -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" /** * Force a function to be inlined at every call site. Use sparingly — only for @@ -15,7 +13,7 @@ #if defined(_MSC_VER) # define PRISM_FORCE_INLINE __forceinline #elif defined(__GNUC__) || defined(__clang__) -# define PRISM_FORCE_INLINE inline __attribute__((always_inline)) +# define PRISM_FORCE_INLINE PRISM_INLINE __attribute__((always_inline)) #else # define PRISM_FORCE_INLINE PRISM_INLINE #endif diff --git a/include/prism/compiler/format.h b/include/prism/compiler/format.h new file mode 100644 index 0000000000..32f4c3c6d7 --- /dev/null +++ b/include/prism/compiler/format.h @@ -0,0 +1,25 @@ +/** + * @file compiler/format.h + */ +#ifndef PRISM_COMPILER_FORMAT_H +#define PRISM_COMPILER_FORMAT_H + +/** + * Certain compilers support specifying that a function accepts variadic + * parameters that look like printf format strings to provide a better developer + * experience when someone is using the function. This macro does that in a + * compiler-agnostic way. + */ +#if defined(__GNUC__) +# if defined(__MINGW_PRINTF_FORMAT) +# define PRISM_ATTRIBUTE_FORMAT(fmt_idx_, arg_idx_) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt_idx_, arg_idx_))) +# else +# define PRISM_ATTRIBUTE_FORMAT(fmt_idx_, arg_idx_) __attribute__((format(printf, fmt_idx_, arg_idx_))) +# endif +#elif defined(__clang__) +# define PRISM_ATTRIBUTE_FORMAT(fmt_idx_, arg_idx_) __attribute__((__format__(__printf__, fmt_idx_, arg_idx_))) +#else +# define PRISM_ATTRIBUTE_FORMAT(fmt_idx_, arg_idx_) +#endif + +#endif diff --git a/include/prism/compiler/inline.h b/include/prism/compiler/inline.h new file mode 100644 index 0000000000..856a375691 --- /dev/null +++ b/include/prism/compiler/inline.h @@ -0,0 +1,17 @@ +/** + * @file compiler/inline.h + */ +#ifndef PRISM_COMPILER_INLINE_H +#define PRISM_COMPILER_INLINE_H + +/** + * Old Visual Studio versions do not support the inline keyword, so we need to + * define it to be __inline. + */ +#if defined(_MSC_VER) && !defined(inline) +# define PRISM_INLINE __inline +#else +# define PRISM_INLINE inline +#endif + +#endif diff --git a/include/prism/attribute/unused.h b/include/prism/compiler/unused.h similarity index 62% rename from include/prism/attribute/unused.h rename to include/prism/compiler/unused.h index 37a7b00f40..fced007f9b 100644 --- a/include/prism/attribute/unused.h +++ b/include/prism/compiler/unused.h @@ -1,11 +1,8 @@ /** - * @file attribute/unused.h - * - * Macro definitions for marking functions and parameters as unused to suppress - * compiler warnings. + * @file compiler/unused.h */ -#ifndef PRISM_ATTRIBUTE_UNUSED_H -#define PRISM_ATTRIBUTE_UNUSED_H +#ifndef PRISM_COMPILER_UNUSED_H +#define PRISM_COMPILER_UNUSED_H /** * GCC will warn if you specify a function or parameter that is unused at diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h index 8d263d9e6e..8a2dd2a2b9 100644 --- a/include/prism/internal/arena.h +++ b/include/prism/internal/arena.h @@ -6,8 +6,8 @@ #ifndef PRISM_INTERNAL_ARENA_H #define PRISM_INTERNAL_ARENA_H -#include "prism/attribute/exported.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/exported.h" +#include "prism/compiler/inline.h" #include "prism/arena.h" #include diff --git a/include/prism/internal/bit.h b/include/prism/internal/bit.h index 06ac3be2ee..b4249825a3 100644 --- a/include/prism/internal/bit.h +++ b/include/prism/internal/bit.h @@ -6,7 +6,7 @@ #ifndef PRISM_INTERNAL_BIT_H #define PRISM_INTERNAL_BIT_H -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" /** * Count trailing zero bits in a 64-bit value. Used by SWAR identifier scanning diff --git a/include/prism/internal/buffer.h b/include/prism/internal/buffer.h index b1d360c91e..8066bd9a97 100644 --- a/include/prism/internal/buffer.h +++ b/include/prism/internal/buffer.h @@ -7,7 +7,7 @@ #define PRISM_INTERNAL_BUFFER_H #include "prism/buffer.h" -#include "prism/attribute/format.h" +#include "prism/compiler/format.h" #include diff --git a/include/prism/internal/char.h b/include/prism/internal/char.h index b3975862dd..6abc998c95 100644 --- a/include/prism/internal/char.h +++ b/include/prism/internal/char.h @@ -6,7 +6,7 @@ #ifndef PRISM_INTERNAL_CHAR_H #define PRISM_INTERNAL_CHAR_H -#include "prism/attribute/force_inline.h" +#include "prism/compiler/force_inline.h" #include "prism/arena.h" #include "prism/line_offset_list.h" diff --git a/include/prism/internal/line_offset_list.h b/include/prism/internal/line_offset_list.h index 97fa050924..5c8ae4763c 100644 --- a/include/prism/internal/line_offset_list.h +++ b/include/prism/internal/line_offset_list.h @@ -16,7 +16,7 @@ #include "prism/line_offset_list.h" -#include "prism/attribute/force_inline.h" +#include "prism/compiler/force_inline.h" #include "prism/arena.h" /** diff --git a/include/prism/line_offset_list.h b/include/prism/line_offset_list.h index 0211b990fe..9d0ddf3889 100644 --- a/include/prism/line_offset_list.h +++ b/include/prism/line_offset_list.h @@ -14,7 +14,7 @@ #ifndef PRISM_LINE_OFFSET_LIST_H #define PRISM_LINE_OFFSET_LIST_H -#include "prism/attribute/exported.h" +#include "prism/compiler/exported.h" #include #include diff --git a/include/prism/node.h b/include/prism/node.h index e59baedbd0..939dbb0c82 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -6,7 +6,7 @@ #ifndef PRISM_NODE_H #define PRISM_NODE_H -#include "prism/attribute/exported.h" +#include "prism/compiler/exported.h" #include "prism/arena.h" #include "prism/ast.h" diff --git a/include/prism/parser.h b/include/prism/parser.h index 9dc666661b..76f9a493d1 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -6,7 +6,7 @@ #ifndef PRISM_PARSER_H #define PRISM_PARSER_H -#include "prism/accel.h" +#include "prism/compiler/accel.h" #include "prism/arena.h" #include "prism/ast.h" #include "prism/encoding.h" diff --git a/include/prism/strings.h b/include/prism/strings.h index da28b76940..e3da5c5a9a 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -6,7 +6,7 @@ #ifndef PRISM_STRINGS_H #define PRISM_STRINGS_H -#include "prism/attribute/exported.h" +#include "prism/compiler/exported.h" #include "prism/files.h" #include diff --git a/prism.gemspec b/prism.gemspec index e2dc185e81..d0f8ff3b45 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -46,15 +46,15 @@ Gem::Specification.new do |spec| "ext/prism/extension.c", "ext/prism/extension.h", "include/prism.h", - "include/prism/attribute/align.h", - "include/prism/attribute/exported.h", - "include/prism/attribute/fallthrough.h", - "include/prism/attribute/flex_array.h", - "include/prism/attribute/force_inline.h", - "include/prism/attribute/format.h", - "include/prism/attribute/inline.h", - "include/prism/attribute/unused.h", - "include/prism/accel.h", + "include/prism/compiler/accel.h", + "include/prism/compiler/align.h", + "include/prism/compiler/exported.h", + "include/prism/compiler/fallthrough.h", + "include/prism/compiler/flex_array.h", + "include/prism/compiler/force_inline.h", + "include/prism/compiler/format.h", + "include/prism/compiler/inline.h", + "include/prism/compiler/unused.h", "include/prism/allocator.h", "include/prism/arena.h", "include/prism/ast.h", diff --git a/src/buffer.c b/src/buffer.c index a54c55182b..c5f6b72ef3 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,6 +1,6 @@ #include "prism/internal/buffer.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" #include "prism/internal/char.h" #include "prism/allocator.h" diff --git a/src/char.c b/src/char.c index 1b5438cd0c..08e457aa1f 100644 --- a/src/char.c +++ b/src/char.c @@ -1,6 +1,6 @@ #include "prism/internal/char.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" #include "prism/internal/line_offset_list.h" #define PRISM_CHAR_BIT_REGEXP_OPTION (1 << 2) diff --git a/src/constant_pool.c b/src/constant_pool.c index 7de70a47a4..0baab71997 100644 --- a/src/constant_pool.c +++ b/src/constant_pool.c @@ -1,7 +1,7 @@ #include "prism/constant_pool.h" -#include "prism/attribute/align.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/align.h" +#include "prism/compiler/inline.h" #include "prism/internal/arena.h" #include diff --git a/src/encoding.c b/src/encoding.c index f43d0fd079..0425a2c5b8 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -1,6 +1,6 @@ #include "prism/internal/encoding.h" -#include "prism/attribute/unused.h" +#include "prism/compiler/unused.h" #include "prism/internal/strncasecmp.h" #include diff --git a/src/line_offset_list.c b/src/line_offset_list.c index 17946a224a..ce217ebd3f 100644 --- a/src/line_offset_list.c +++ b/src/line_offset_list.c @@ -1,4 +1,4 @@ -#include "prism/attribute/align.h" +#include "prism/compiler/align.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/arena.h" diff --git a/src/options.c b/src/options.c index e38bd92ca9..b089071ec6 100644 --- a/src/options.c +++ b/src/options.c @@ -1,6 +1,6 @@ #include "prism/options.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" #include "prism/internal/char.h" #include "prism/allocator.h" diff --git a/src/prism.c b/src/prism.c index 0e96ee7cff..5fed8de93b 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,7 +1,8 @@ #include "prism.h" -#include "prism/attribute/fallthrough.h" -#include "prism/attribute/unused.h" +#include "prism/compiler/accel.h" +#include "prism/compiler/fallthrough.h" +#include "prism/compiler/unused.h" #include "prism/internal/arena.h" #include "prism/internal/bit.h" @@ -23,7 +24,6 @@ #include "prism/internal/strpbrk.h" #include "prism/allocator.h" -#include "prism/accel.h" #include "prism/node_new.h" #include diff --git a/src/regexp.c b/src/regexp.c index 0ed501092b..566d65a7fd 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1,7 +1,7 @@ #include "prism/internal/regexp.h" -#include "prism/attribute/inline.h" -#include "prism/attribute/fallthrough.h" +#include "prism/compiler/inline.h" +#include "prism/compiler/fallthrough.h" #include "prism/internal/buffer.h" #include "prism/internal/char.h" #include "prism/internal/diagnostic.h" diff --git a/src/static_literals.c b/src/static_literals.c index 73e479f8d3..7fc872fe25 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -1,7 +1,7 @@ #include "prism/internal/static_literals.h" -#include "prism/attribute/inline.h" -#include "prism/attribute/unused.h" +#include "prism/compiler/inline.h" +#include "prism/compiler/unused.h" #include "prism/internal/buffer.h" #include "prism/internal/integer.h" #include "prism/internal/isinf.h" diff --git a/src/strncasecmp.c b/src/strncasecmp.c index 80eb399d04..a373cad6d7 100644 --- a/src/strncasecmp.c +++ b/src/strncasecmp.c @@ -1,6 +1,6 @@ #include "prism/internal/strncasecmp.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" /** * A locale-insensitive version of `tolower(3)` diff --git a/src/strpbrk.c b/src/strpbrk.c index 59330fc172..6db4fd31bf 100644 --- a/src/strpbrk.c +++ b/src/strpbrk.c @@ -1,11 +1,12 @@ #include "prism/internal/strpbrk.h" -#include "prism/attribute/inline.h" -#include "prism/attribute/unused.h" +#include "prism/compiler/accel.h" +#include "prism/compiler/inline.h" +#include "prism/compiler/unused.h" + #include "prism/internal/bit.h" #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" -#include "prism/accel.h" #include #include diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index af3403c293..670efc7045 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -8,7 +8,7 @@ #ifndef PRISM_AST_H #define PRISM_AST_H -#include "prism/attribute/align.h" +#include "prism/compiler/align.h" #include "prism/constant_pool.h" #include "prism/integer.h" #include "prism/strings.h" diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb index a3964cc40c..1443617811 100644 --- a/templates/include/prism/diagnostic.h.erb +++ b/templates/include/prism/diagnostic.h.erb @@ -6,7 +6,7 @@ #ifndef PRISM_DIAGNOSTIC_H #define PRISM_DIAGNOSTIC_H -#include "prism/attribute/exported.h" +#include "prism/compiler/exported.h" #include "prism/ast.h" #include "prism/list.h" diff --git a/templates/include/prism/node_new.h.erb b/templates/include/prism/node_new.h.erb index 27a7ed22c6..cda6174705 100644 --- a/templates/include/prism/node_new.h.erb +++ b/templates/include/prism/node_new.h.erb @@ -10,7 +10,7 @@ #include "prism/node.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" <%- nodes.each do |node| -%> <%- params = node.fields.map(&:c_param) -%> diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 8a4abc14eb..15b2a776a7 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -1,6 +1,6 @@ #include "prism/diagnostic.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" #include "prism/internal/arena.h" #include "prism/internal/list.h" diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index db2d52ddcf..b702712742 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -1,7 +1,7 @@ <%# encoding: ASCII -%> #include "prism/prettyprint.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 39eb2b521a..a69e38f010 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,6 +1,6 @@ #include "prism.h" -#include "prism/attribute/inline.h" +#include "prism/compiler/inline.h" #include "prism/internal/buffer.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" From 1e3ec12adce5e93ed1ae1f4612b359d359204e8d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 13:58:37 -0400 Subject: [PATCH 182/289] Move allocator to internal headers --- Doxyfile | 2 +- docs/build_system.md | 2 +- include/prism/{ => internal}/allocator.h | 8 ++-- .../allocator_debug.h} | 44 ++++++++----------- prism.gemspec | 40 ++++++++--------- src/arena.c | 3 +- src/buffer.c | 3 +- src/integer.c | 5 ++- src/options.c | 3 +- src/prism.c | 2 +- src/static_literals.c | 3 +- src/strings.c | 2 +- templates/ext/prism/api_node.c.erb | 2 +- 13 files changed, 59 insertions(+), 60 deletions(-) rename include/prism/{ => internal}/allocator.h (93%) rename include/prism/{debug_allocator.h => internal/allocator_debug.h} (62%) diff --git a/Doxyfile b/Doxyfile index fca1e8c314..00bb3537ab 100644 --- a/Doxyfile +++ b/Doxyfile @@ -24,7 +24,7 @@ OUTPUT_DIRECTORY = doc JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES INPUT = src include include/prism -EXCLUDE = include/prism/debug_allocator.h +EXCLUDE = include/prism/internal/allocator_debug.h HTML_OUTPUT = c SORT_MEMBER_DOCS = NO GENERATE_LATEX = NO diff --git a/docs/build_system.md b/docs/build_system.md index 2e2749e62c..40db4a17fc 100644 --- a/docs/build_system.md +++ b/docs/build_system.md @@ -87,7 +87,7 @@ If you need to use memory allocation functions implemented outside of the standa * Additionally, include `-I [path/to/custom_allocator]` where your `prism_xallocator.h` is located * Link the implementation of `prism_xallocator.c` that contains functions declared in `prism_xallocator.h` -For further clarity, refer to `include/prism/allocator.h`. +For further clarity, refer to `include/prism/internal/allocator.h`. ### Building prism from source as a C library diff --git a/include/prism/allocator.h b/include/prism/internal/allocator.h similarity index 93% rename from include/prism/allocator.h rename to include/prism/internal/allocator.h index 6b1c26e84e..bd46257e44 100644 --- a/include/prism/allocator.h +++ b/include/prism/internal/allocator.h @@ -1,10 +1,10 @@ /** - * @file allocator.h + * @file internal/allocator.h * * Macro definitions for defining the main and a custom allocator for Prism. */ -#ifndef PRISM_ALLOCATOR_H -#define PRISM_ALLOCATOR_H +#ifndef PRISM_INTERNAL_ALLOCATOR_H +#define PRISM_INTERNAL_ALLOCATOR_H /** * If you build Prism with a custom allocator, configure it with @@ -79,7 +79,7 @@ #endif #ifdef PRISM_BUILD_DEBUG - #include "prism/debug_allocator.h" + #include "prism/internal/allocator_debug.h" #endif #endif diff --git a/include/prism/debug_allocator.h b/include/prism/internal/allocator_debug.h similarity index 62% rename from include/prism/debug_allocator.h rename to include/prism/internal/allocator_debug.h index 3e28a95efb..40f2a7b4cf 100644 --- a/include/prism/debug_allocator.h +++ b/include/prism/internal/allocator_debug.h @@ -1,37 +1,34 @@ /** - * @file debug_allocator.h + * @file internal/allocator_debug.h * * Decorate allocation function to ensure sizes are correct. */ -#ifndef PRISM_DEBUG_ALLOCATOR_H -#define PRISM_DEBUG_ALLOCATOR_H +#ifndef PRISM_INTERNAL_ALLOCATOR_DEBUG_H +#define PRISM_INTERNAL_ALLOCATOR_DEBUG_H #include #include #include static inline void * -pm_debug_malloc(size_t size) -{ +pm_allocator_debug_malloc(size_t size) { size_t *memory = xmalloc(size + sizeof(size_t)); memory[0] = size; return memory + 1; } static inline void * -pm_debug_calloc(size_t nmemb, size_t size) -{ +pm_allocator_debug_calloc(size_t nmemb, size_t size) { size_t total_size = nmemb * size; - void *ptr = pm_debug_malloc(total_size); + void *ptr = pm_allocator_debug_malloc(total_size); memset(ptr, 0, total_size); return ptr; } static inline void * -pm_debug_realloc(void *ptr, size_t size) -{ +pm_allocator_debug_realloc(void *ptr, size_t size) { if (ptr == NULL) { - return pm_debug_malloc(size); + return pm_allocator_debug_malloc(size); } size_t *memory = (size_t *)ptr; @@ -42,8 +39,7 @@ pm_debug_realloc(void *ptr, size_t size) } static inline void -pm_debug_free(void *ptr) -{ +pm_allocator_debug_free(void *ptr) { if (ptr != NULL) { size_t *memory = (size_t *)ptr; xfree(memory - 1); @@ -51,8 +47,7 @@ pm_debug_free(void *ptr) } static inline void -pm_debug_free_sized(void *ptr, size_t old_size) -{ +pm_allocator_debug_free_sized(void *ptr, size_t old_size) { if (ptr != NULL) { size_t *memory = (size_t *)ptr; if (old_size != memory[-1]) { @@ -64,14 +59,13 @@ pm_debug_free_sized(void *ptr, size_t old_size) } static inline void * -pm_debug_realloc_sized(void *ptr, size_t size, size_t old_size) -{ +pm_allocator_debug_realloc_sized(void *ptr, size_t size, size_t old_size) { if (ptr == NULL) { if (old_size != 0) { fprintf(stderr, "[BUG] realloc_sized called with NULL pointer and old size %lu\n", old_size); abort(); } - return pm_debug_malloc(size); + return pm_allocator_debug_malloc(size); } size_t *memory = (size_t *)ptr; @@ -79,7 +73,7 @@ pm_debug_realloc_sized(void *ptr, size_t size, size_t old_size) fprintf(stderr, "[BUG] buffer %p was allocated with size %lu but realloced with size %lu\n", ptr, memory[-1], old_size); abort(); } - return pm_debug_realloc(ptr, size); + return pm_allocator_debug_realloc(ptr, size); } #undef xmalloc @@ -89,11 +83,11 @@ pm_debug_realloc_sized(void *ptr, size_t size, size_t old_size) #undef xrealloc_sized #undef xfree_sized -#define xmalloc pm_debug_malloc -#define xrealloc pm_debug_realloc -#define xcalloc pm_debug_calloc -#define xfree pm_debug_free -#define xrealloc_sized pm_debug_realloc_sized -#define xfree_sized pm_debug_free_sized +#define xmalloc pm_allocator_debug_malloc +#define xrealloc pm_allocator_debug_realloc +#define xcalloc pm_allocator_debug_calloc +#define xfree pm_allocator_debug_free +#define xrealloc_sized pm_allocator_debug_realloc_sized +#define xfree_sized pm_allocator_debug_free_sized #endif diff --git a/prism.gemspec b/prism.gemspec index d0f8ff3b45..a5bde09328 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -55,12 +55,30 @@ Gem::Specification.new do |spec| "include/prism/compiler/format.h", "include/prism/compiler/inline.h", "include/prism/compiler/unused.h", - "include/prism/allocator.h", + "include/prism/internal/allocator.h", + "include/prism/internal/allocator_debug.h", + "include/prism/internal/arena.h", + "include/prism/internal/bit.h", + "include/prism/internal/buffer.h", + "include/prism/internal/char.h", + "include/prism/internal/constant_pool.h", + "include/prism/internal/diagnostic.h", + "include/prism/internal/encoding.h", + "include/prism/internal/integer.h", + "include/prism/internal/isinf.h", + "include/prism/internal/line_offset_list.h", + "include/prism/internal/list.h", + "include/prism/internal/memchr.h", + "include/prism/internal/options.h", + "include/prism/internal/regexp.h", + "include/prism/internal/static_literals.h", + "include/prism/internal/strncasecmp.h", + "include/prism/internal/strings.h", + "include/prism/internal/strpbrk.h", "include/prism/arena.h", "include/prism/ast.h", "include/prism/buffer.h", "include/prism/constant_pool.h", - "include/prism/debug_allocator.h", "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/excludes.h", @@ -76,24 +94,6 @@ Gem::Specification.new do |spec| "include/prism/static_literals.h", "include/prism/strings.h", "include/prism/version.h", - "include/prism/internal/arena.h", - "include/prism/internal/bit.h", - "include/prism/internal/buffer.h", - "include/prism/internal/char.h", - "include/prism/internal/constant_pool.h", - "include/prism/internal/diagnostic.h", - "include/prism/internal/encoding.h", - "include/prism/internal/integer.h", - "include/prism/internal/isinf.h", - "include/prism/internal/line_offset_list.h", - "include/prism/internal/list.h", - "include/prism/internal/memchr.h", - "include/prism/internal/options.h", - "include/prism/internal/regexp.h", - "include/prism/internal/static_literals.h", - "include/prism/internal/strncasecmp.h", - "include/prism/internal/strings.h", - "include/prism/internal/strpbrk.h", "lib/prism.rb", "lib/prism/compiler.rb", "lib/prism/desugar_compiler.rb", diff --git a/src/arena.c b/src/arena.c index d7ce9c043c..d0bd6f139c 100644 --- a/src/arena.c +++ b/src/arena.c @@ -1,5 +1,6 @@ #include "prism/arena.h" -#include "prism/allocator.h" + +#include "prism/internal/allocator.h" #include #include diff --git a/src/buffer.c b/src/buffer.c index c5f6b72ef3..d689a93203 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,8 +1,9 @@ #include "prism/internal/buffer.h" #include "prism/compiler/inline.h" + #include "prism/internal/char.h" -#include "prism/allocator.h" +#include "prism/internal/allocator.h" #include #include diff --git a/src/integer.c b/src/integer.c index 35dd5e0eea..1b69dbdceb 100644 --- a/src/integer.c +++ b/src/integer.c @@ -1,7 +1,8 @@ -#include "prism/allocator.h" -#include "prism/internal/buffer.h" #include "prism/internal/integer.h" +#include "prism/internal/allocator.h" +#include "prism/internal/buffer.h" + #include #include #include diff --git a/src/options.c b/src/options.c index b089071ec6..39f4f2fea5 100644 --- a/src/options.c +++ b/src/options.c @@ -1,8 +1,9 @@ #include "prism/options.h" #include "prism/compiler/inline.h" + +#include "prism/internal/allocator.h" #include "prism/internal/char.h" -#include "prism/allocator.h" #include #include diff --git a/src/prism.c b/src/prism.c index 5fed8de93b..68730a82e3 100644 --- a/src/prism.c +++ b/src/prism.c @@ -4,6 +4,7 @@ #include "prism/compiler/fallthrough.h" #include "prism/compiler/unused.h" +#include "prism/internal/allocator.h" #include "prism/internal/arena.h" #include "prism/internal/bit.h" #include "prism/internal/buffer.h" @@ -22,7 +23,6 @@ #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" #include "prism/internal/strpbrk.h" -#include "prism/allocator.h" #include "prism/node_new.h" diff --git a/src/static_literals.c b/src/static_literals.c index 7fc872fe25..c66fa7724a 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -2,11 +2,12 @@ #include "prism/compiler/inline.h" #include "prism/compiler/unused.h" + +#include "prism/internal/allocator.h" #include "prism/internal/buffer.h" #include "prism/internal/integer.h" #include "prism/internal/isinf.h" #include "prism/internal/strings.h" -#include "prism/allocator.h" #include #include diff --git a/src/strings.c b/src/strings.c index da7548112b..37b48293ab 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1,6 +1,6 @@ #include "prism/internal/strings.h" -#include "prism/allocator.h" +#include "prism/internal/allocator.h" #include #include diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index ea9754bdfd..be6bd113ad 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -1,6 +1,6 @@ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" #include "prism/extension.h" -#include "prism/allocator.h" +#include "prism/internal/allocator.h" extern VALUE rb_cPrism; extern VALUE rb_cPrismNode; From 323f7f16f84a9ec2b2e5adb03937de51014c779d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 14:01:59 -0400 Subject: [PATCH 183/289] Move file system into compiler headers --- include/prism/{files.h => compiler/filesystem.h} | 6 +++--- include/prism/node.h | 1 + include/prism/parser.h | 1 + include/prism/prettyprint.h | 2 ++ include/prism/strings.h | 2 +- prism.gemspec | 2 +- templates/include/prism/ast.h.erb | 1 + templates/include/prism/diagnostic.h.erb | 1 + templates/include/prism/node_new.h.erb | 4 ++-- 9 files changed, 13 insertions(+), 7 deletions(-) rename include/prism/{files.h => compiler/filesystem.h} (87%) diff --git a/include/prism/files.h b/include/prism/compiler/filesystem.h similarity index 87% rename from include/prism/files.h rename to include/prism/compiler/filesystem.h index 8a74e03be8..f988909db8 100644 --- a/include/prism/files.h +++ b/include/prism/compiler/filesystem.h @@ -1,10 +1,10 @@ /** - * @file files.h + * @file compiler/filesystem.h * * Platform detection for mmap and filesystem support. */ -#ifndef PRISM_FILES_H -#define PRISM_FILES_H +#ifndef PRISM_COMPILER_FILESYSTEM_H +#define PRISM_COMPILER_FILESYSTEM_H /** * In general, libc for embedded systems does not support memory-mapped files. diff --git a/include/prism/node.h b/include/prism/node.h index 939dbb0c82..6d4512bd37 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -7,6 +7,7 @@ #define PRISM_NODE_H #include "prism/compiler/exported.h" + #include "prism/arena.h" #include "prism/ast.h" diff --git a/include/prism/parser.h b/include/prism/parser.h index 76f9a493d1..53c9472171 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -7,6 +7,7 @@ #define PRISM_PARSER_H #include "prism/compiler/accel.h" + #include "prism/arena.h" #include "prism/ast.h" #include "prism/encoding.h" diff --git a/include/prism/prettyprint.h b/include/prism/prettyprint.h index 65c4302644..b59cfe1460 100644 --- a/include/prism/prettyprint.h +++ b/include/prism/prettyprint.h @@ -14,6 +14,8 @@ #else +#include "prism/compiler/exported.h" + #include "prism/ast.h" #include "prism/buffer.h" #include "prism/parser.h" diff --git a/include/prism/strings.h b/include/prism/strings.h index e3da5c5a9a..6f659fc0e7 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -7,7 +7,7 @@ #define PRISM_STRINGS_H #include "prism/compiler/exported.h" -#include "prism/files.h" +#include "prism/compiler/filesystem.h" #include #include diff --git a/prism.gemspec b/prism.gemspec index a5bde09328..6fc30c6f69 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -50,6 +50,7 @@ Gem::Specification.new do |spec| "include/prism/compiler/align.h", "include/prism/compiler/exported.h", "include/prism/compiler/fallthrough.h", + "include/prism/compiler/filesystem.h", "include/prism/compiler/flex_array.h", "include/prism/compiler/force_inline.h", "include/prism/compiler/format.h", @@ -82,7 +83,6 @@ Gem::Specification.new do |spec| "include/prism/diagnostic.h", "include/prism/encoding.h", "include/prism/excludes.h", - "include/prism/files.h", "include/prism/integer.h", "include/prism/line_offset_list.h", "include/prism/list.h", diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 670efc7045..754d05a216 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -9,6 +9,7 @@ #define PRISM_AST_H #include "prism/compiler/align.h" + #include "prism/constant_pool.h" #include "prism/integer.h" #include "prism/strings.h" diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb index 1443617811..dceb21cf65 100644 --- a/templates/include/prism/diagnostic.h.erb +++ b/templates/include/prism/diagnostic.h.erb @@ -7,6 +7,7 @@ #define PRISM_DIAGNOSTIC_H #include "prism/compiler/exported.h" + #include "prism/ast.h" #include "prism/list.h" diff --git a/templates/include/prism/node_new.h.erb b/templates/include/prism/node_new.h.erb index cda6174705..4a253fc02e 100644 --- a/templates/include/prism/node_new.h.erb +++ b/templates/include/prism/node_new.h.erb @@ -8,10 +8,10 @@ #ifndef PRISM_NODE_NEW_H #define PRISM_NODE_NEW_H -#include "prism/node.h" - #include "prism/compiler/inline.h" +#include "prism/node.h" + <%- nodes.each do |node| -%> <%- params = node.fields.map(&:c_param) -%> /** From a5dfba8dbe3b1fb2e5dacc8339ffc92485e27f4c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 14:03:35 -0400 Subject: [PATCH 184/289] Trim down even more of internal header includes --- include/prism/internal/arena.h | 1 + include/prism/internal/buffer.h | 3 ++- include/prism/internal/char.h | 1 + include/prism/internal/diagnostic.h | 2 +- include/prism/internal/line_offset_list.h | 4 ++-- include/prism/internal/static_literals.h | 3 +-- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h index 8a2dd2a2b9..747484fa2f 100644 --- a/include/prism/internal/arena.h +++ b/include/prism/internal/arena.h @@ -8,6 +8,7 @@ #include "prism/compiler/exported.h" #include "prism/compiler/inline.h" + #include "prism/arena.h" #include diff --git a/include/prism/internal/buffer.h b/include/prism/internal/buffer.h index 8066bd9a97..1d7ee93762 100644 --- a/include/prism/internal/buffer.h +++ b/include/prism/internal/buffer.h @@ -6,9 +6,10 @@ #ifndef PRISM_INTERNAL_BUFFER_H #define PRISM_INTERNAL_BUFFER_H -#include "prism/buffer.h" #include "prism/compiler/format.h" +#include "prism/buffer.h" + #include /** diff --git a/include/prism/internal/char.h b/include/prism/internal/char.h index 6abc998c95..8216a1828c 100644 --- a/include/prism/internal/char.h +++ b/include/prism/internal/char.h @@ -7,6 +7,7 @@ #define PRISM_INTERNAL_CHAR_H #include "prism/compiler/force_inline.h" + #include "prism/arena.h" #include "prism/line_offset_list.h" diff --git a/include/prism/internal/diagnostic.h b/include/prism/internal/diagnostic.h index edaaa33a14..3e58c2ad2e 100644 --- a/include/prism/internal/diagnostic.h +++ b/include/prism/internal/diagnostic.h @@ -6,8 +6,8 @@ #ifndef PRISM_INTERNAL_DIAGNOSTIC_H #define PRISM_INTERNAL_DIAGNOSTIC_H -#include "prism/diagnostic.h" #include "prism/arena.h" +#include "prism/diagnostic.h" /** * Append a diagnostic to the given list of diagnostics that is using shared diff --git a/include/prism/internal/line_offset_list.h b/include/prism/internal/line_offset_list.h index 5c8ae4763c..e18f7276e6 100644 --- a/include/prism/internal/line_offset_list.h +++ b/include/prism/internal/line_offset_list.h @@ -14,10 +14,10 @@ #ifndef PRISM_INTERNAL_LINE_OFFSET_LIST_H #define PRISM_INTERNAL_LINE_OFFSET_LIST_H -#include "prism/line_offset_list.h" - #include "prism/compiler/force_inline.h" + #include "prism/arena.h" +#include "prism/line_offset_list.h" /** * Initialize a new line offset list with the given capacity. diff --git a/include/prism/internal/static_literals.h b/include/prism/internal/static_literals.h index 0adde85780..f924dd9e6a 100644 --- a/include/prism/internal/static_literals.h +++ b/include/prism/internal/static_literals.h @@ -6,11 +6,10 @@ #ifndef PRISM_INTERNAL_STATIC_LITERALS_H #define PRISM_INTERNAL_STATIC_LITERALS_H -#include "prism/static_literals.h" - #include "prism/ast.h" #include "prism/buffer.h" #include "prism/line_offset_list.h" +#include "prism/static_literals.h" /** * An internal hash table for a set of nodes. From a4a44cb14a69ff5509e461b918d12a5b40f80cad Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 14:09:02 -0400 Subject: [PATCH 185/289] Split node.h headers --- include/prism/internal/node.h | 28 ++++++++++++++++++++++++++++ include/prism/node.h | 18 ------------------ prism.gemspec | 1 + src/prism.c | 1 + 4 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 include/prism/internal/node.h diff --git a/include/prism/internal/node.h b/include/prism/internal/node.h new file mode 100644 index 0000000000..2399b5a72a --- /dev/null +++ b/include/prism/internal/node.h @@ -0,0 +1,28 @@ +/** + * @file internal/node.h + */ +#ifndef PRISM_INTERNAL_NODE_H +#define PRISM_INTERNAL_NODE_H + +#include "prism/arena.h" +#include "prism/ast.h" + +/** + * Prepend a new node onto the beginning of the node list. + * + * @param arena The arena to allocate from. + * @param list The list to prepend to. + * @param node The node to prepend. + */ +void pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); + +/** + * Concatenate the given node list onto the end of the other node list. + * + * @param arena The arena to allocate from. + * @param list The list to concatenate onto. + * @param other The list to concatenate. + */ +void pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other); + +#endif diff --git a/include/prism/node.h b/include/prism/node.h index 6d4512bd37..44a3134bc4 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -44,24 +44,6 @@ pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { } } -/** - * Prepend a new node onto the beginning of the node list. - * - * @param arena The arena to allocate from. - * @param list The list to prepend to. - * @param node The node to prepend. - */ -void pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); - -/** - * Concatenate the given node list onto the end of the other node list. - * - * @param arena The arena to allocate from. - * @param list The list to concatenate onto. - * @param other The list to concatenate. - */ -void pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other); - /** * Returns a string representation of the given node type. * diff --git a/prism.gemspec b/prism.gemspec index 6fc30c6f69..f407e2f952 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -70,6 +70,7 @@ Gem::Specification.new do |spec| "include/prism/internal/line_offset_list.h", "include/prism/internal/list.h", "include/prism/internal/memchr.h", + "include/prism/internal/node.h", "include/prism/internal/options.h", "include/prism/internal/regexp.h", "include/prism/internal/static_literals.h", diff --git a/src/prism.c b/src/prism.c index 68730a82e3..9bb5005260 100644 --- a/src/prism.c +++ b/src/prism.c @@ -17,6 +17,7 @@ #include "prism/internal/line_offset_list.h" #include "prism/internal/list.h" #include "prism/internal/memchr.h" +#include "prism/internal/node.h" #include "prism/internal/options.h" #include "prism/internal/regexp.h" #include "prism/internal/static_literals.h" From 2b5298128ebdb871b49102fbf9d41f55f581ada0 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 14:16:14 -0400 Subject: [PATCH 186/289] pm_buffer_free -> pm_buffer_cleanup --- cpp/test.cpp | 2 +- docs/serialization.md | 6 +++--- ext/prism/extension.c | 4 ++-- fuzz/parse.c | 2 +- include/prism.h | 6 +++--- include/prism/buffer.h | 6 +++--- javascript/src/parsePrism.js | 2 +- lib/prism/ffi.rb | 4 ++-- src/buffer.c | 4 ++-- src/prism.c | 18 +++++++++--------- src/regexp.c | 6 +++--- templates/src/prettyprint.c.erb | 2 +- 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/cpp/test.cpp b/cpp/test.cpp index 3e41b270e9..76673ab87d 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -17,7 +17,7 @@ int main() { std::cout << buffer.value << std::endl; - pm_buffer_free(&buffer); + pm_buffer_cleanup(&buffer); pm_parser_free(&parser); pm_arena_free(&arena); diff --git a/docs/serialization.md b/docs/serialization.md index a7ba533566..c744e0d81a 100644 --- a/docs/serialization.md +++ b/docs/serialization.md @@ -159,8 +159,8 @@ typedef struct { size_t capacity; } pm_buffer_t; -// Free the memory associated with the buffer. -void pm_buffer_free(pm_buffer_t *); +// Free the memory held by the buffer. +void pm_buffer_cleanup(pm_buffer_t *); // Parse and serialize the AST represented by the given source to the given // buffer. @@ -177,7 +177,7 @@ serialize(const uint8_t *source, size_t length) { // Do something with the serialized string. - pm_buffer_free(&buffer); + pm_buffer_cleanup(&buffer); } ``` diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 60f33f0cb1..965f630de0 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -382,7 +382,7 @@ dump_input(pm_string_t *input, const pm_options_t *options) { pm_serialize(&parser, node, &buffer); VALUE result = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer)); - pm_buffer_free(&buffer); + pm_buffer_cleanup(&buffer); pm_parser_free(&parser); pm_arena_free(&arena); @@ -1081,7 +1081,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) { VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze); VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze); - pm_buffer_free(&buffer); + pm_buffer_cleanup(&buffer); pm_parser_free(&parser); pm_arena_free(&arena); diff --git a/fuzz/parse.c b/fuzz/parse.c index be9094d86f..0805c5489c 100644 --- a/fuzz/parse.c +++ b/fuzz/parse.c @@ -5,5 +5,5 @@ harness(const uint8_t *input, size_t size) { pm_buffer_t buffer; pm_buffer_init(&buffer); pm_serialize_parse(&buffer, input, size, NULL); - pm_buffer_free(&buffer); + pm_buffer_cleanup(&buffer); } diff --git a/include/prism.h b/include/prism.h index 55ce7e4745..c131d21aaa 100644 --- a/include/prism.h +++ b/include/prism.h @@ -365,7 +365,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * use and be aware of are: * * * `pm_buffer_t` - a small buffer object that will hold the serialized AST - * * `pm_buffer_free()` - free the memory associated with the buffer + * * `pm_buffer_cleanup()` - free the memory associated with the buffer * * `pm_serialize()` - serialize the AST into a buffer * * `pm_serialize_parse()` - parse and serialize the AST into a buffer * @@ -378,7 +378,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * pm_serialize_parse(&buffer, source, length, NULL); * printf("SERIALIZED!\n"); * - * pm_buffer_free(&buffer); + * pm_buffer_cleanup(&buffer); * } * ``` * @@ -399,7 +399,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * pm_prettyprint(&buffer, &parser, root); * printf("%*.s\n", (int) buffer.length, buffer.value); * - * pm_buffer_free(&buffer); + * pm_buffer_cleanup(&buffer); * pm_parser_free(&parser); * pm_arena_free(&arena); * } diff --git a/include/prism/buffer.h b/include/prism/buffer.h index 41b0fd8dc0..ec0571b28b 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -64,12 +64,12 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer); PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer); /** - * Free the memory associated with the buffer. + * Free the memory held by the buffer. * - * @param buffer The buffer to free. + * @param buffer The buffer whose held memory should be freed. * * \public \memberof pm_buffer_t */ -PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION void pm_buffer_cleanup(pm_buffer_t *buffer); #endif diff --git a/javascript/src/parsePrism.js b/javascript/src/parsePrism.js index 269f84c825..af6d70b841 100644 --- a/javascript/src/parsePrism.js +++ b/javascript/src/parsePrism.js @@ -45,7 +45,7 @@ export function parsePrism(prism, source, options = {}) { const serializedView = new Uint8Array(prism.memory.buffer, prism.pm_buffer_value(bufferPointer), prism.pm_buffer_length(bufferPointer)); const result = deserialize(serializedView); - prism.pm_buffer_free(bufferPointer); + prism.pm_buffer_cleanup(bufferPointer); prism.free(sourcePointer); prism.free(bufferPointer); prism.free(optionsPointer); diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index eb8cf3f4ca..4419213162 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -111,7 +111,7 @@ def self.load_exported_functions_from(header, *functions, callbacks) "pm_buffer_init", "pm_buffer_value", "pm_buffer_length", - "pm_buffer_free", + "pm_buffer_cleanup", [] ) @@ -155,7 +155,7 @@ def self.with raise unless LibRubyParser.pm_buffer_init(pointer) return yield new(pointer) ensure - LibRubyParser.pm_buffer_free(pointer) + LibRubyParser.pm_buffer_cleanup(pointer) end end end diff --git a/src/buffer.c b/src/buffer.c index d689a93203..9612cb4802 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -361,9 +361,9 @@ pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t le } /** - * Free the memory associated with the buffer. + * Free the memory held by the buffer. */ void -pm_buffer_free(pm_buffer_t *buffer) { +pm_buffer_cleanup(pm_buffer_t *buffer) { xfree_sized(buffer->value, buffer->capacity); } diff --git a/src/prism.c b/src/prism.c index 9bb5005260..6f256b4a36 100644 --- a/src/prism.c +++ b/src/prism.c @@ -2246,7 +2246,7 @@ pm_regular_expression_flags_create(pm_parser_t *parser, const pm_token_t *closin const char *word = unknown_flags_length >= 2 ? "options" : "option"; PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, PM_ERR_REGEXP_UNKNOWN_OPTIONS, word, unknown_flags_length, pm_buffer_value(&unknown_flags)); } - pm_buffer_free(&unknown_flags); + pm_buffer_cleanup(&unknown_flags); } return flags; @@ -9446,7 +9446,7 @@ lex_question_mark(pm_parser_t *parser) { // Copy buffer data into the arena and free the heap buffer. void *arena_data = pm_arena_memdup(parser->arena, buffer.value, buffer.length, PRISM_ALIGNOF(uint8_t)); pm_string_constant_init(&parser->current_string, (const char *) arena_data, buffer.length); - pm_buffer_free(&buffer); + pm_buffer_cleanup(&buffer); return PM_TOKEN_CHARACTER_LITERAL; } else { @@ -9770,13 +9770,13 @@ pm_token_buffer_copy(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { size_t len = pm_buffer_length(&token_buffer->buffer); void *arena_data = pm_arena_memdup(parser->arena, pm_buffer_value(&token_buffer->buffer), len, PRISM_ALIGNOF(uint8_t)); pm_string_constant_init(&parser->current_string, (const char *) arena_data, len); - pm_buffer_free(&token_buffer->buffer); + pm_buffer_cleanup(&token_buffer->buffer); } static PRISM_INLINE void pm_regexp_token_buffer_copy(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { pm_token_buffer_copy(parser, &token_buffer->base); - pm_buffer_free(&token_buffer->regexp_buffer); + pm_buffer_cleanup(&token_buffer->regexp_buffer); } /** @@ -13523,7 +13523,7 @@ pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *liter pm_line_offset_list_line_column(&parser->line_offsets, PM_NODE_START(node), parser->start_line).line ); - pm_buffer_free(&buffer); + pm_buffer_cleanup(&buffer); } } @@ -20779,7 +20779,7 @@ parse_regular_expression_named_capture(pm_parser_t *parser, const pm_string_t *c // If the name of the capture group isn't a valid identifier, we do // not add it to the local table. if (!pm_slice_is_valid_local(parser, source, source + length)) { - pm_buffer_free(&unescaped); + pm_buffer_cleanup(&unescaped); return; } @@ -20810,7 +20810,7 @@ parse_regular_expression_named_capture(pm_parser_t *parser, const pm_string_t *c // If the local is not already a local but it is a keyword, then we // do not want to add a capture for this. if (pm_local_is_keyword((const char *) source, length)) { - pm_buffer_free(&unescaped); + pm_buffer_cleanup(&unescaped); return; } @@ -20831,7 +20831,7 @@ parse_regular_expression_named_capture(pm_parser_t *parser, const pm_string_t *c pm_node_list_append(parser->arena, &callback_data->match->targets, target); } - pm_buffer_free(&unescaped); + pm_buffer_cleanup(&unescaped); } /** @@ -22845,7 +22845,7 @@ pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fge pm_serialize_content(&parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_buffer_free(&parser_buffer); + pm_buffer_cleanup(&parser_buffer); pm_parser_free(&parser); pm_arena_free(&arena); pm_options_free(&options); diff --git a/src/regexp.c b/src/regexp.c index 566d65a7fd..3013974367 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -1464,7 +1464,7 @@ pm_regexp_validate_encoding_modifier(pm_regexp_parser_t *parser, bool ascii_only pm_buffer_t formatted = { 0 }; pm_regexp_format_for_error(&formatted, parser->encoding, (const uint8_t *) source_start, (size_t) source_length); PM_REGEXP_ENCODING_ERROR(parser, PM_ERR_REGEXP_NON_ESCAPED_MBC, (int) formatted.length, (const char *) formatted.value); - pm_buffer_free(&formatted); + pm_buffer_cleanup(&formatted); } } @@ -1658,7 +1658,7 @@ pm_regexp_parse(pm_parser_t *parser, pm_regular_expression_node_t *node, pm_rege const char *error_source = (const char *) pm_string_source(&node->unescaped); int error_source_length = (int) pm_string_length(&node->unescaped); pm_node_flags_t encoding_flags = pm_regexp_validate_encoding(®exp_parser, ascii_only, flags, error_source, error_source_length); - pm_buffer_free(®exp_parser.hex_escape_buffer); + pm_buffer_cleanup(®exp_parser.hex_escape_buffer); // Second pass: walk unescaped content for named capture extraction. if (name_callback != NULL) { @@ -1712,5 +1712,5 @@ pm_regexp_parse_named_captures(pm_parser_t *parser, const uint8_t *source, size_ }; pm_regexp_parse_pattern(®exp_parser); - pm_buffer_free(®exp_parser.hex_escape_buffer); + pm_buffer_cleanup(®exp_parser.hex_escape_buffer); } diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index b702712742..4af8155c47 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -167,7 +167,7 @@ void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node) { pm_buffer_t prefix_buffer = { 0 }; prettyprint_node(output_buffer, parser, node, &prefix_buffer); - pm_buffer_free(&prefix_buffer); + pm_buffer_cleanup(&prefix_buffer); } #endif From 1b594e10da4807db251af2f919195ba14fcd3c47 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 14:32:46 -0400 Subject: [PATCH 187/289] Make buffer an opaque pointer --- cpp/test.cpp | 10 ++++---- docs/serialization.md | 6 ++--- ext/prism/extension.c | 16 ++++++------- fuzz/parse.c | 7 +++--- include/prism.h | 19 +++++++-------- include/prism/buffer.h | 41 ++++++++++----------------------- include/prism/internal/buffer.h | 25 ++++++++++++++++++-- javascript/src/parsePrism.js | 7 ++---- lib/prism/ffi.rb | 17 +++++++------- src/buffer.c | 35 ++++++++++++++++------------ src/prism.c | 16 ++++++------- 11 files changed, 101 insertions(+), 98 deletions(-) diff --git a/cpp/test.cpp b/cpp/test.cpp index 76673ab87d..f41ac83c61 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -10,14 +10,14 @@ int main() { pm_parser_init(&arena, &parser, reinterpret_cast("1 + 2"), 5, NULL); pm_node_t *root = pm_parse(&parser); - pm_buffer_t buffer = { 0 }; + pm_buffer_t *buffer = pm_buffer_new(); - pm_prettyprint(&buffer, &parser, root); - pm_buffer_append_byte(&buffer, '\0'); + pm_prettyprint(buffer, &parser, root); - std::cout << buffer.value << std::endl; + std::string_view view(pm_buffer_value(buffer), pm_buffer_length(buffer)); + std::cout << view << std::endl; - pm_buffer_cleanup(&buffer); + pm_buffer_free(buffer); pm_parser_free(&parser); pm_arena_free(&arena); diff --git a/docs/serialization.md b/docs/serialization.md index c744e0d81a..d087698baa 100644 --- a/docs/serialization.md +++ b/docs/serialization.md @@ -172,12 +172,12 @@ Typically you would use a stack-allocated `pm_buffer_t` and call `pm_serialize_p ```c void serialize(const uint8_t *source, size_t length) { - pm_buffer_t buffer = { 0 }; - pm_serialize_parse(&buffer, source, length, NULL); + pm_buffer_t *buffer = pm_buffer_new(); + pm_serialize_parse(buffer, source, length, NULL); // Do something with the serialized string. - pm_buffer_cleanup(&buffer); + pm_buffer_free(buffer); } ``` diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 965f630de0..d39f8abe7a 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -369,8 +369,8 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V */ static VALUE dump_input(pm_string_t *input, const pm_options_t *options) { - pm_buffer_t buffer; - if (!pm_buffer_init(&buffer)) { + pm_buffer_t *buffer = pm_buffer_new(); + if (!buffer) { rb_raise(rb_eNoMemError, "failed to allocate memory"); } @@ -379,10 +379,10 @@ dump_input(pm_string_t *input, const pm_options_t *options) { pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(&parser); - pm_serialize(&parser, node, &buffer); + pm_serialize(&parser, node, buffer); - VALUE result = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer)); - pm_buffer_cleanup(&buffer); + VALUE result = rb_str_new(pm_buffer_value(buffer), pm_buffer_length(buffer)); + pm_buffer_free(buffer); pm_parser_free(&parser); pm_arena_free(&arena); @@ -1072,16 +1072,16 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_arena_t arena = { 0 }; pm_parser_t parser; - pm_buffer_t buffer; - pm_node_t *node = pm_parse_stream(&arena, &parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); + pm_buffer_t *buffer = pm_buffer_new(); + pm_node_t *node = pm_parse_stream(&arena, &parser, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); VALUE source = pm_source_new(&parser, encoding, options.freeze); VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze); VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze); - pm_buffer_cleanup(&buffer); + pm_buffer_free(buffer); pm_parser_free(&parser); pm_arena_free(&arena); diff --git a/fuzz/parse.c b/fuzz/parse.c index 0805c5489c..c04553909e 100644 --- a/fuzz/parse.c +++ b/fuzz/parse.c @@ -2,8 +2,7 @@ void harness(const uint8_t *input, size_t size) { - pm_buffer_t buffer; - pm_buffer_init(&buffer); - pm_serialize_parse(&buffer, input, size, NULL); - pm_buffer_cleanup(&buffer); + pm_buffer_t *buffer = pm_buffer_new(); + pm_serialize_parse(buffer, input, size, NULL); + pm_buffer_free(buffer); } diff --git a/include/prism.h b/include/prism.h index c131d21aaa..80dd579829 100644 --- a/include/prism.h +++ b/include/prism.h @@ -364,8 +364,9 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * parse Ruby code. The structures and functions that you're going to want to * use and be aware of are: * - * * `pm_buffer_t` - a small buffer object that will hold the serialized AST - * * `pm_buffer_cleanup()` - free the memory associated with the buffer + * * `pm_buffer_t` - an opaque buffer object that will hold the serialized AST + * * `pm_buffer_new()` - create a new buffer + * * `pm_buffer_free()` - free the buffer and its internal memory * * `pm_serialize()` - serialize the AST into a buffer * * `pm_serialize_parse()` - parse and serialize the AST into a buffer * @@ -373,12 +374,12 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * * ```c * void serialize(const uint8_t *source, size_t length) { - * pm_buffer_t buffer = { 0 }; + * pm_buffer_t *buffer = pm_buffer_new(); * - * pm_serialize_parse(&buffer, source, length, NULL); + * pm_serialize_parse(buffer, source, length, NULL); * printf("SERIALIZED!\n"); * - * pm_buffer_cleanup(&buffer); + * pm_buffer_free(buffer); * } * ``` * @@ -394,12 +395,12 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * pm_parser_init(&arena, &parser, source, length, NULL); * * pm_node_t *root = pm_parse(&parser); - * pm_buffer_t buffer = { 0 }; + * pm_buffer_t *buffer = pm_buffer_new(); * - * pm_prettyprint(&buffer, &parser, root); - * printf("%*.s\n", (int) buffer.length, buffer.value); + * pm_prettyprint(buffer, &parser, root); + * printf("%*.s\n", (int) pm_buffer_length(buffer), pm_buffer_value(buffer)); * - * pm_buffer_cleanup(&buffer); + * pm_buffer_free(buffer); * pm_parser_free(&parser); * pm_arena_free(&arena); * } diff --git a/include/prism/buffer.h b/include/prism/buffer.h index ec0571b28b..b6e8feea31 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -8,40 +8,32 @@ #include "prism/compiler/exported.h" -#include #include /** - * A pm_buffer_t is a simple memory buffer that stores data in a contiguous - * block of memory. + * A wrapper around a contiguous block of allocated memory. */ -typedef struct { - /** The length of the buffer in bytes. */ - size_t length; - - /** The capacity of the buffer in bytes that has been allocated. */ - size_t capacity; - - /** A pointer to the start of the buffer. */ - char *value; -} pm_buffer_t; +typedef struct pm_buffer_t pm_buffer_t; /** - * Return the size of the pm_buffer_t struct. + * Allocate and initialize a new buffer. If the buffer cannot be allocated, this + * function will abort the process. * - * @returns The size of the pm_buffer_t struct. + * @returns A pointer to the initialized buffer. The caller is responsible for + * freeing the buffer with pm_buffer_free. + * + * \public \memberof pm_buffer_t */ -PRISM_EXPORTED_FUNCTION size_t pm_buffer_sizeof(void); +PRISM_EXPORTED_FUNCTION pm_buffer_t * pm_buffer_new(void); /** - * Initialize a pm_buffer_t with its default values. + * Free both the memory held by the buffer and the buffer itself. * - * @param buffer The buffer to initialize. - * @returns True if the buffer was initialized successfully, false otherwise. + * @param buffer The buffer to free. * * \public \memberof pm_buffer_t */ -PRISM_EXPORTED_FUNCTION bool pm_buffer_init(pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer); /** * Return the value of the buffer. @@ -63,13 +55,4 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer); */ PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer); -/** - * Free the memory held by the buffer. - * - * @param buffer The buffer whose held memory should be freed. - * - * \public \memberof pm_buffer_t - */ -PRISM_EXPORTED_FUNCTION void pm_buffer_cleanup(pm_buffer_t *buffer); - #endif diff --git a/include/prism/internal/buffer.h b/include/prism/internal/buffer.h index 1d7ee93762..8eb0c7e243 100644 --- a/include/prism/internal/buffer.h +++ b/include/prism/internal/buffer.h @@ -10,16 +10,37 @@ #include "prism/buffer.h" +#include #include +/** + * A simple memory buffer that stores data in a contiguous block of memory. + */ +struct pm_buffer_t { + /** The length of the buffer in bytes. */ + size_t length; + + /** The capacity of the buffer in bytes that has been allocated. */ + size_t capacity; + + /** A pointer to the start of the buffer. */ + char *value; +}; + /** * Initialize a pm_buffer_t with the given capacity. * * @param buffer The buffer to initialize. * @param capacity The capacity of the buffer. - * @returns True if the buffer was initialized successfully, false otherwise. */ -bool pm_buffer_init_capacity(pm_buffer_t *buffer, size_t capacity); +void pm_buffer_init(pm_buffer_t *buffer, size_t capacity); + +/** + * Free the memory held by the buffer. + * + * @param buffer The buffer whose held memory should be freed. + */ +void pm_buffer_cleanup(pm_buffer_t *buffer); /** * Append the given amount of space as zeroes to the buffer. diff --git a/javascript/src/parsePrism.js b/javascript/src/parsePrism.js index af6d70b841..615cc83d13 100644 --- a/javascript/src/parsePrism.js +++ b/javascript/src/parsePrism.js @@ -31,9 +31,7 @@ export function parsePrism(prism, source, options = {}) { const packedOptions = dumpOptions(options); const optionsPointer = prism.calloc(1, packedOptions.length); - - const bufferPointer = prism.calloc(prism.pm_buffer_sizeof(), 1); - prism.pm_buffer_init(bufferPointer); + const bufferPointer = prism.pm_buffer_new(); const sourceView = new Uint8Array(prism.memory.buffer, sourcePointer, sourceArray.length); sourceView.set(sourceArray); @@ -45,9 +43,8 @@ export function parsePrism(prism, source, options = {}) { const serializedView = new Uint8Array(prism.memory.buffer, prism.pm_buffer_value(bufferPointer), prism.pm_buffer_length(bufferPointer)); const result = deserialize(serializedView); - prism.pm_buffer_cleanup(bufferPointer); + prism.pm_buffer_free(bufferPointer); prism.free(sourcePointer); - prism.free(bufferPointer); prism.free(optionsPointer); return result; } diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 4419213162..e9682c527c 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -107,11 +107,10 @@ def self.load_exported_functions_from(header, *functions, callbacks) load_exported_functions_from( "prism/buffer.h", - "pm_buffer_sizeof", - "pm_buffer_init", + "pm_buffer_new", "pm_buffer_value", "pm_buffer_length", - "pm_buffer_cleanup", + "pm_buffer_free", [] ) @@ -128,8 +127,6 @@ def self.load_exported_functions_from(header, *functions, callbacks) # 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 # :nodoc: - SIZEOF = LibRubyParser.pm_buffer_sizeof - attr_reader :pointer def initialize(pointer) @@ -151,11 +148,13 @@ def read # Initialize a new buffer and yield it to the block. The buffer will be # automatically freed when the block returns. def self.with - FFI::MemoryPointer.new(SIZEOF) do |pointer| - raise unless LibRubyParser.pm_buffer_init(pointer) - return yield new(pointer) + buffer = LibRubyParser.pm_buffer_new + raise unless buffer + + begin + yield new(buffer) ensure - LibRubyParser.pm_buffer_cleanup(pointer) + LibRubyParser.pm_buffer_free(buffer) end end end diff --git a/src/buffer.c b/src/buffer.c index 9612cb4802..cb3b9a4fe8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -11,32 +11,28 @@ #include #include -/** - * Return the size of the pm_buffer_t struct. - */ -size_t -pm_buffer_sizeof(void) { - return sizeof(pm_buffer_t); -} - /** * Initialize a pm_buffer_t with the given capacity. */ -bool -pm_buffer_init_capacity(pm_buffer_t *buffer, size_t capacity) { +void +pm_buffer_init(pm_buffer_t *buffer, size_t capacity) { buffer->length = 0; buffer->capacity = capacity; buffer->value = (char *) xmalloc(capacity); - return buffer->value != NULL; + if (buffer->value == NULL) abort(); } /** - * Initialize a pm_buffer_t with its default values. + * Allocate and initialize a new buffer. */ -bool -pm_buffer_init(pm_buffer_t *buffer) { - return pm_buffer_init_capacity(buffer, 1024); +pm_buffer_t * +pm_buffer_new(void) { + pm_buffer_t *buffer = (pm_buffer_t *) xmalloc(sizeof(pm_buffer_t)); + if (buffer == NULL) abort(); + + pm_buffer_init(buffer, 1024); + return buffer; } /** @@ -367,3 +363,12 @@ void pm_buffer_cleanup(pm_buffer_t *buffer) { xfree_sized(buffer->value, buffer->capacity); } + +/** + * Free both the memory held by the buffer and the buffer itself. + */ +void +pm_buffer_free(pm_buffer_t *buffer) { + pm_buffer_cleanup(buffer); + xfree_sized(buffer, sizeof(pm_buffer_t)); +} diff --git a/src/prism.c b/src/prism.c index 6f256b4a36..db1890a5be 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9439,7 +9439,7 @@ lex_question_mark(pm_parser_t *parser) { lex_state_set(parser, PM_LEX_STATE_END); pm_buffer_t buffer; - pm_buffer_init_capacity(&buffer, 3); + pm_buffer_init(&buffer, 3); escape_read(parser, &buffer, NULL, PM_ESCAPE_FLAG_SINGLE); @@ -9825,7 +9825,7 @@ static void pm_token_buffer_escape(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { const uint8_t *start; if (token_buffer->cursor == NULL) { - pm_buffer_init_capacity(&token_buffer->buffer, PM_TOKEN_BUFFER_DEFAULT_SIZE); + pm_buffer_init(&token_buffer->buffer, PM_TOKEN_BUFFER_DEFAULT_SIZE); start = parser->current.start; } else { start = token_buffer->cursor; @@ -9842,8 +9842,8 @@ static void pm_regexp_token_buffer_escape(pm_parser_t *parser, pm_regexp_token_buffer_t *token_buffer) { const uint8_t *start; if (token_buffer->base.cursor == NULL) { - pm_buffer_init_capacity(&token_buffer->base.buffer, PM_TOKEN_BUFFER_DEFAULT_SIZE); - pm_buffer_init_capacity(&token_buffer->regexp_buffer, PM_TOKEN_BUFFER_DEFAULT_SIZE); + pm_buffer_init(&token_buffer->base.buffer, PM_TOKEN_BUFFER_DEFAULT_SIZE); + pm_buffer_init(&token_buffer->regexp_buffer, PM_TOKEN_BUFFER_DEFAULT_SIZE); start = parser->current.start; } else { start = token_buffer->base.cursor; @@ -22734,8 +22734,6 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t */ pm_node_t * pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { - pm_buffer_init(buffer); - bool eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); @@ -22839,13 +22837,13 @@ pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fge pm_options_t options = { 0 }; pm_options_read(&options, data); - pm_buffer_t parser_buffer; - pm_node_t *node = pm_parse_stream(&arena, &parser, &parser_buffer, stream, stream_fgets, stream_feof, &options); + pm_buffer_t *parser_buffer = pm_buffer_new(); + pm_node_t *node = pm_parse_stream(&arena, &parser, parser_buffer, stream, stream_fgets, stream_feof, &options); pm_serialize_header(buffer); pm_serialize_content(&parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_buffer_cleanup(&parser_buffer); + pm_buffer_free(parser_buffer); pm_parser_free(&parser); pm_arena_free(&arena); pm_options_free(&options); From b1be4b451dea9f5cd6ec8462d535a3aa819b602a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 15:01:52 -0400 Subject: [PATCH 188/289] pm_parser_free -> pm_parser_cleanup --- cpp/test.cpp | 2 +- ext/prism/extension.c | 14 +++++++------- include/prism.h | 12 ++++++------ include/prism/node.h | 2 +- rust/ruby-prism-sys/build/main.rs | 2 +- rust/ruby-prism-sys/tests/node_tests.rs | 4 ++-- rust/ruby-prism-sys/tests/parser_tests.rs | 8 ++++---- rust/ruby-prism/src/parse_result/mod.rs | 4 ++-- src/prism.c | 12 ++++++------ templates/src/serialize.c.erb | 4 ++-- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/cpp/test.cpp b/cpp/test.cpp index f41ac83c61..19a5731de9 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -18,7 +18,7 @@ int main() { std::cout << view << std::endl; pm_buffer_free(buffer); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); return 0; diff --git a/ext/prism/extension.c b/ext/prism/extension.c index d39f8abe7a..ad80a35804 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -383,7 +383,7 @@ dump_input(pm_string_t *input, const pm_options_t *options) { VALUE result = rb_str_new(pm_buffer_value(buffer), pm_buffer_length(buffer)); pm_buffer_free(buffer); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); return result; @@ -792,7 +792,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, options->freeze); } - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); return result; @@ -866,7 +866,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) { rb_obj_freeze(source); } - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); return result; @@ -974,7 +974,7 @@ profile_input(pm_string_t *input, const pm_options_t *options) { pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); pm_parse(&parser); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); } @@ -1082,7 +1082,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) { VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze); pm_buffer_free(buffer); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); return result; @@ -1103,7 +1103,7 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { VALUE source = pm_source_new(&parser, encoding, options->freeze); VALUE comments = parser_comments(&parser, source, options->freeze); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); return comments; @@ -1223,7 +1223,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { pm_parse(&parser); VALUE result = parser.error_list.size == 0 ? Qtrue : Qfalse; - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); return result; diff --git a/include/prism.h b/include/prism.h index 80dd579829..2005c57a77 100644 --- a/include/prism.h +++ b/include/prism.h @@ -44,8 +44,8 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void); /** * Initialize a parser with the given start and end pointers. * - * The resulting parser must eventually be freed with `pm_parser_free()`. The - * arena is caller-owned and must outlive the parser — `pm_parser_free()` does + * The resulting parser must eventually be freed with `pm_parser_cleanup()`. The + * arena is caller-owned and must outlive the parser — `pm_parser_cleanup()` does * not free the arena. * * @param arena The arena to use for all AST-lifetime allocations. @@ -80,7 +80,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_register_encoding_changed_callback(pm_par * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION void pm_parser_cleanup(pm_parser_t *parser); /** * Initiate the parser with the given parser. @@ -333,7 +333,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * * `pm_parser_t` - the main parser structure * * `pm_parser_init()` - initialize a parser * * `pm_parse()` - parse and return the root node - * * `pm_parser_free()` - free the internal memory of the parser + * * `pm_parser_cleanup()` - free the internal memory of the parser * * `pm_arena_free()` - free all AST-lifetime memory * * Putting all of this together would look something like: @@ -347,7 +347,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * pm_node_t *root = pm_parse(&parser); * printf("PARSED!\n"); * - * pm_parser_free(&parser); + * pm_parser_cleanup(&parser); * pm_arena_free(&arena); * } * ``` @@ -401,7 +401,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint * printf("%*.s\n", (int) pm_buffer_length(buffer), pm_buffer_value(buffer)); * * pm_buffer_free(buffer); - * pm_parser_free(&parser); + * pm_parser_cleanup(&parser); * pm_arena_free(&arena); * } * ``` diff --git a/include/prism/node.h b/include/prism/node.h index 44a3134bc4..2390dc7290 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -92,7 +92,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * size_t *data = &indent; * pm_visit_node(node, visit, data); * - * pm_parser_free(&parser); + * pm_parser_cleanup(&parser); * pm_arena_free(&arena); * return EXIT_SUCCESS; * } diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 18441ed623..3bbf4fbbeb 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -163,7 +163,7 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_function("pm_options_scope_local_get") .allowlist_function("pm_options_scopes_init") .allowlist_function("pm_parse") - .allowlist_function("pm_parser_free") + .allowlist_function("pm_parser_cleanup") .allowlist_function("pm_parser_init") .allowlist_function("pm_size_to_native") .allowlist_function("pm_string_constant_init") diff --git a/rust/ruby-prism-sys/tests/node_tests.rs b/rust/ruby-prism-sys/tests/node_tests.rs index 7c7c13629c..0de0eabe49 100644 --- a/rust/ruby-prism-sys/tests/node_tests.rs +++ b/rust/ruby-prism-sys/tests/node_tests.rs @@ -1,7 +1,7 @@ use std::{ffi::CString, mem::MaybeUninit}; use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_node_type}; -use ruby_prism_sys::{pm_parse, pm_parser_free, pm_parser_init, pm_parser_t}; +use ruby_prism_sys::{pm_parse, pm_parser_cleanup, pm_parser_init, pm_parser_t}; #[test] fn node_test() { @@ -23,7 +23,7 @@ fn node_test() { assert_eq!((*parsed_node).type_, pm_node_type::PM_PROGRAM_NODE as u16); - pm_parser_free(parser); + pm_parser_cleanup(parser); pm_arena_free(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism-sys/tests/parser_tests.rs b/rust/ruby-prism-sys/tests/parser_tests.rs index d6f827d144..3d85ef06de 100644 --- a/rust/ruby-prism-sys/tests/parser_tests.rs +++ b/rust/ruby-prism-sys/tests/parser_tests.rs @@ -5,7 +5,7 @@ use std::{ }; use ruby_prism_sys::{ - pm_arena_free, pm_arena_t, pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_parse, pm_parser_free, + pm_arena_free, pm_arena_t, pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_parse, pm_parser_cleanup, pm_parser_init, pm_parser_t, }; @@ -29,7 +29,7 @@ fn init_test() { pm_parser_init(arena.as_mut_ptr(), parser.as_mut_ptr(), source, len, std::ptr::null()); let parser = parser.assume_init_mut(); - pm_parser_free(parser); + pm_parser_cleanup(parser); pm_arena_free(arena.as_mut_ptr()); } } @@ -62,7 +62,7 @@ fn comments_test() { }; assert_eq!(location, 0..7); - pm_parser_free(parser); + pm_parser_cleanup(parser); pm_arena_free(arena.as_mut_ptr()); } } @@ -101,7 +101,7 @@ fn diagnostics_test() { }; assert_eq!(location, 10..10); - pm_parser_free(parser); + pm_parser_cleanup(parser); pm_arena_free(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index b0e7197707..4ac843661e 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -8,7 +8,7 @@ mod diagnostics; use std::ptr::NonNull; -use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_free, pm_parser_t}; +use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_cleanup, pm_parser_t}; pub use self::comments::{Comment, CommentType, Comments, MagicComment, MagicComments}; pub use self::diagnostics::{Diagnostic, Diagnostics}; @@ -260,7 +260,7 @@ impl<'pr> ParseResult<'pr> { impl Drop for ParseResult<'_> { fn drop(&mut self) { unsafe { - pm_parser_free(self.parser.as_ptr()); + pm_parser_cleanup(self.parser.as_ptr()); drop(Box::from_raw(self.parser.as_ptr())); pm_arena_free(self.arena.as_mut()); } diff --git a/src/prism.c b/src/prism.c index db1890a5be..ee5866a341 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22483,7 +22483,7 @@ pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_ch * Free any memory associated with the given parser. */ void -pm_parser_free(pm_parser_t *parser) { +pm_parser_cleanup(pm_parser_t *parser) { pm_string_free(&parser->filepath); pm_arena_free(&parser->metadata_arena); @@ -22742,7 +22742,7 @@ pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, voi while (!eof && parser->error_list.size > 0) { eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); - pm_parser_free(parser); + pm_parser_cleanup(parser); pm_arena_free(arena); pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); node = pm_parse(parser); @@ -22766,7 +22766,7 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { pm_parse(&parser); bool result = parser.error_list.size == 0; - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); pm_options_free(&options); @@ -22821,7 +22821,7 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons pm_serialize_content(&parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); pm_options_free(&options); } @@ -22844,7 +22844,7 @@ pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fge pm_buffer_append_byte(buffer, '\0'); pm_buffer_free(parser_buffer); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); pm_options_free(&options); } @@ -22867,7 +22867,7 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s pm_buffer_append_varsint(buffer, parser.start_line); pm_serialize_comment_list(&parser.comment_list, buffer); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); pm_options_free(&options); } diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index a69e38f010..69ee654242 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -338,7 +338,7 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const pm_serialize_metadata(&parser, buffer); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); pm_options_free(&options); } @@ -367,7 +367,7 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_buffer_append_byte(buffer, 0); pm_serialize(&parser, node, buffer); - pm_parser_free(&parser); + pm_parser_cleanup(&parser); pm_arena_free(&arena); pm_options_free(&options); } From 88a247a4863c39579ca02d3c5269f15e8946211f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 15:13:08 -0400 Subject: [PATCH 189/289] Move string query into its own file --- include/prism.h | 48 +--------- include/prism/string_query.h | 62 +++++++++++++ prism.gemspec | 2 + src/prism.c | 163 ---------------------------------- src/string_query.c | 166 +++++++++++++++++++++++++++++++++++ 5 files changed, 231 insertions(+), 210 deletions(-) create mode 100644 include/prism/string_query.h create mode 100644 src/string_query.c diff --git a/include/prism.h b/include/prism.h index 2005c57a77..6e5b2dd083 100644 --- a/include/prism.h +++ b/include/prism.h @@ -17,6 +17,7 @@ extern "C" { #include "prism/options.h" #include "prism/parser.h" #include "prism/prettyprint.h" +#include "prism/string_query.h" #include "prism/version.h" #include @@ -257,53 +258,6 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t #endif -/** - * Represents the results of a slice query. - */ -typedef enum { - /** Returned if the encoding given to a slice query was invalid. */ - PM_STRING_QUERY_ERROR = -1, - - /** Returned if the result of the slice query is false. */ - PM_STRING_QUERY_FALSE, - - /** Returned if the result of the slice query is true. */ - PM_STRING_QUERY_TRUE -} pm_string_query_t; - -/** - * Check that the slice is a valid local variable name. - * - * @param source The source to check. - * @param length The length of the source. - * @param encoding_name The name of the encoding of the source. - * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if - * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. - */ -PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name); - -/** - * Check that the slice is a valid constant name. - * - * @param source The source to check. - * @param length The length of the source. - * @param encoding_name The name of the encoding of the source. - * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if - * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. - */ -PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name); - -/** - * Check that the slice is a valid method name. - * - * @param source The source to check. - * @param length The length of the source. - * @param encoding_name The name of the encoding of the source. - * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if - * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. - */ -PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name); - /** * @mainpage * diff --git a/include/prism/string_query.h b/include/prism/string_query.h new file mode 100644 index 0000000000..55c6c82697 --- /dev/null +++ b/include/prism/string_query.h @@ -0,0 +1,62 @@ +/** + * @file string_query.h + * + * Functions for querying properties of strings, such as whether they are valid + * local variable names, constant names, or method names. + */ +#ifndef PRISM_STRING_QUERY_H +#define PRISM_STRING_QUERY_H + +#include "prism/compiler/exported.h" + +#include +#include + +/** + * Represents the results of a slice query. + */ +typedef enum { + /** Returned if the encoding given to a slice query was invalid. */ + PM_STRING_QUERY_ERROR = -1, + + /** Returned if the result of the slice query is false. */ + PM_STRING_QUERY_FALSE, + + /** Returned if the result of the slice query is true. */ + PM_STRING_QUERY_TRUE +} pm_string_query_t; + +/** + * Check that the slice is a valid local variable name. + * + * @param source The source to check. + * @param length The length of the source. + * @param encoding_name The name of the encoding of the source. + * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name); + +/** + * Check that the slice is a valid constant name. + * + * @param source The source to check. + * @param length The length of the source. + * @param encoding_name The name of the encoding of the source. + * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name); + +/** + * Check that the slice is a valid method name. + * + * @param source The source to check. + * @param length The length of the source. + * @param encoding_name The name of the encoding of the source. + * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. + */ +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name); + +#endif diff --git a/prism.gemspec b/prism.gemspec index f407e2f952..762ab7b590 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -93,6 +93,7 @@ Gem::Specification.new do |spec| "include/prism/parser.h", "include/prism/prettyprint.h", "include/prism/static_literals.h", + "include/prism/string_query.h", "include/prism/strings.h", "include/prism/version.h", "lib/prism.rb", @@ -201,6 +202,7 @@ Gem::Specification.new do |spec| "src/regexp.c", "src/serialize.c", "src/static_literals.c", + "src/string_query.c", "src/strings.c", "src/strncasecmp.c", "src/strpbrk.c", diff --git a/src/prism.c b/src/prism.c index ee5866a341..aee3e63599 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22873,166 +22873,3 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s } #endif - -/******************************************************************************/ -/* Slice queries for the Ruby API */ -/******************************************************************************/ - -/** The category of slice returned from pm_slice_type. */ -typedef enum { - /** Returned when the given encoding name is invalid. */ - PM_SLICE_TYPE_ERROR = -1, - - /** Returned when no other types apply to the slice. */ - PM_SLICE_TYPE_NONE, - - /** Returned when the slice is a valid local variable name. */ - PM_SLICE_TYPE_LOCAL, - - /** Returned when the slice is a valid constant name. */ - PM_SLICE_TYPE_CONSTANT, - - /** Returned when the slice is a valid method name. */ - PM_SLICE_TYPE_METHOD_NAME -} pm_slice_type_t; - -/** - * Check that the slice is a valid local variable name or constant. - */ -pm_slice_type_t -pm_slice_type(const uint8_t *source, size_t length, const char *encoding_name) { - // first, get the right encoding object - const pm_encoding_t *encoding = pm_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))); - if (encoding == NULL) return PM_SLICE_TYPE_ERROR; - - // check that there is at least one character - if (length == 0) return PM_SLICE_TYPE_NONE; - - size_t width; - if ((width = encoding->alpha_char(source, (ptrdiff_t) length)) != 0) { - // valid because alphabetical - } else if (*source == '_') { - // valid because underscore - width = 1; - } else if ((*source >= 0x80) && ((width = encoding->char_width(source, (ptrdiff_t) length)) > 0)) { - // valid because multibyte - } else { - // invalid because no match - return PM_SLICE_TYPE_NONE; - } - - // determine the type of the slice based on the first character - const uint8_t *end = source + length; - pm_slice_type_t result = encoding->isupper_char(source, end - source) ? PM_SLICE_TYPE_CONSTANT : PM_SLICE_TYPE_LOCAL; - - // next, iterate through all of the bytes of the string to ensure that they - // are all valid identifier characters - source += width; - - while (source < end) { - if ((width = encoding->alnum_char(source, end - source)) != 0) { - // valid because alphanumeric - source += width; - } else if (*source == '_') { - // valid because underscore - source++; - } else if ((*source >= 0x80) && ((width = encoding->char_width(source, end - source)) > 0)) { - // valid because multibyte - source += width; - } else { - // invalid because no match - break; - } - } - - // accept a ! or ? at the end of the slice as a method name - if (*source == '!' || *source == '?' || *source == '=') { - source++; - result = PM_SLICE_TYPE_METHOD_NAME; - } - - // valid if we are at the end of the slice - return source == end ? result : PM_SLICE_TYPE_NONE; -} - -/** - * Check that the slice is a valid local variable name. - */ -pm_string_query_t -pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) { - switch (pm_slice_type(source, length, encoding_name)) { - case PM_SLICE_TYPE_ERROR: - return PM_STRING_QUERY_ERROR; - case PM_SLICE_TYPE_NONE: - case PM_SLICE_TYPE_CONSTANT: - case PM_SLICE_TYPE_METHOD_NAME: - return PM_STRING_QUERY_FALSE; - case PM_SLICE_TYPE_LOCAL: - return PM_STRING_QUERY_TRUE; - } - - assert(false && "unreachable"); - return PM_STRING_QUERY_FALSE; -} - -/** - * Check that the slice is a valid constant name. - */ -pm_string_query_t -pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) { - switch (pm_slice_type(source, length, encoding_name)) { - case PM_SLICE_TYPE_ERROR: - return PM_STRING_QUERY_ERROR; - case PM_SLICE_TYPE_NONE: - case PM_SLICE_TYPE_LOCAL: - case PM_SLICE_TYPE_METHOD_NAME: - return PM_STRING_QUERY_FALSE; - case PM_SLICE_TYPE_CONSTANT: - return PM_STRING_QUERY_TRUE; - } - - assert(false && "unreachable"); - return PM_STRING_QUERY_FALSE; -} - -/** - * Check that the slice is a valid method name. - */ -pm_string_query_t -pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) { -#define B(p) ((p) ? PM_STRING_QUERY_TRUE : PM_STRING_QUERY_FALSE) -#define C1(c) (*source == c) -#define C2(s) (memcmp(source, s, 2) == 0) -#define C3(s) (memcmp(source, s, 3) == 0) - - switch (pm_slice_type(source, length, encoding_name)) { - case PM_SLICE_TYPE_ERROR: - return PM_STRING_QUERY_ERROR; - case PM_SLICE_TYPE_NONE: - break; - case PM_SLICE_TYPE_LOCAL: - // numbered parameters are not valid method names - return B((length != 2) || (source[0] != '_') || (source[1] == '0') || !pm_char_is_decimal_digit(source[1])); - case PM_SLICE_TYPE_CONSTANT: - // all constants are valid method names - case PM_SLICE_TYPE_METHOD_NAME: - // all method names are valid method names - return PM_STRING_QUERY_TRUE; - } - - switch (length) { - case 1: - return B(C1('&') || C1('`') || C1('!') || C1('^') || C1('>') || C1('<') || C1('-') || C1('%') || C1('|') || C1('+') || C1('/') || C1('*') || C1('~')); - case 2: - return B(C2("!=") || C2("!~") || C2("[]") || C2("==") || C2("=~") || C2(">=") || C2(">>") || C2("<=") || C2("<<") || C2("**")); - case 3: - return B(C3("===") || C3("<=>") || C3("[]=")); - default: - return PM_STRING_QUERY_FALSE; - } - -#undef B -#undef C1 -#undef C2 -#undef C3 -} diff --git a/src/string_query.c b/src/string_query.c new file mode 100644 index 0000000000..a3be418b75 --- /dev/null +++ b/src/string_query.c @@ -0,0 +1,166 @@ +#include "prism/string_query.h" + +#include "prism/internal/char.h" +#include "prism/internal/encoding.h" + +#include +#include + +/** The category of slice returned from pm_slice_type. */ +typedef enum { + /** Returned when the given encoding name is invalid. */ + PM_SLICE_TYPE_ERROR = -1, + + /** Returned when no other types apply to the slice. */ + PM_SLICE_TYPE_NONE, + + /** Returned when the slice is a valid local variable name. */ + PM_SLICE_TYPE_LOCAL, + + /** Returned when the slice is a valid constant name. */ + PM_SLICE_TYPE_CONSTANT, + + /** Returned when the slice is a valid method name. */ + PM_SLICE_TYPE_METHOD_NAME +} pm_slice_type_t; + +/** + * Check that the slice is a valid local variable name or constant. + */ +pm_slice_type_t +pm_slice_type(const uint8_t *source, size_t length, const char *encoding_name) { + // first, get the right encoding object + const pm_encoding_t *encoding = pm_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))); + if (encoding == NULL) return PM_SLICE_TYPE_ERROR; + + // check that there is at least one character + if (length == 0) return PM_SLICE_TYPE_NONE; + + size_t width; + if ((width = encoding->alpha_char(source, (ptrdiff_t) length)) != 0) { + // valid because alphabetical + } else if (*source == '_') { + // valid because underscore + width = 1; + } else if ((*source >= 0x80) && ((width = encoding->char_width(source, (ptrdiff_t) length)) > 0)) { + // valid because multibyte + } else { + // invalid because no match + return PM_SLICE_TYPE_NONE; + } + + // determine the type of the slice based on the first character + const uint8_t *end = source + length; + pm_slice_type_t result = encoding->isupper_char(source, end - source) ? PM_SLICE_TYPE_CONSTANT : PM_SLICE_TYPE_LOCAL; + + // next, iterate through all of the bytes of the string to ensure that they + // are all valid identifier characters + source += width; + + while (source < end) { + if ((width = encoding->alnum_char(source, end - source)) != 0) { + // valid because alphanumeric + source += width; + } else if (*source == '_') { + // valid because underscore + source++; + } else if ((*source >= 0x80) && ((width = encoding->char_width(source, end - source)) > 0)) { + // valid because multibyte + source += width; + } else { + // invalid because no match + break; + } + } + + // accept a ! or ? at the end of the slice as a method name + if (*source == '!' || *source == '?' || *source == '=') { + source++; + result = PM_SLICE_TYPE_METHOD_NAME; + } + + // valid if we are at the end of the slice + return source == end ? result : PM_SLICE_TYPE_NONE; +} + +/** + * Check that the slice is a valid local variable name. + */ +pm_string_query_t +pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) { + switch (pm_slice_type(source, length, encoding_name)) { + case PM_SLICE_TYPE_ERROR: + return PM_STRING_QUERY_ERROR; + case PM_SLICE_TYPE_NONE: + case PM_SLICE_TYPE_CONSTANT: + case PM_SLICE_TYPE_METHOD_NAME: + return PM_STRING_QUERY_FALSE; + case PM_SLICE_TYPE_LOCAL: + return PM_STRING_QUERY_TRUE; + } + + assert(false && "unreachable"); + return PM_STRING_QUERY_FALSE; +} + +/** + * Check that the slice is a valid constant name. + */ +pm_string_query_t +pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) { + switch (pm_slice_type(source, length, encoding_name)) { + case PM_SLICE_TYPE_ERROR: + return PM_STRING_QUERY_ERROR; + case PM_SLICE_TYPE_NONE: + case PM_SLICE_TYPE_LOCAL: + case PM_SLICE_TYPE_METHOD_NAME: + return PM_STRING_QUERY_FALSE; + case PM_SLICE_TYPE_CONSTANT: + return PM_STRING_QUERY_TRUE; + } + + assert(false && "unreachable"); + return PM_STRING_QUERY_FALSE; +} + +/** + * Check that the slice is a valid method name. + */ +pm_string_query_t +pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) { +#define B(p) ((p) ? PM_STRING_QUERY_TRUE : PM_STRING_QUERY_FALSE) +#define C1(c) (*source == c) +#define C2(s) (memcmp(source, s, 2) == 0) +#define C3(s) (memcmp(source, s, 3) == 0) + + switch (pm_slice_type(source, length, encoding_name)) { + case PM_SLICE_TYPE_ERROR: + return PM_STRING_QUERY_ERROR; + case PM_SLICE_TYPE_NONE: + break; + case PM_SLICE_TYPE_LOCAL: + // numbered parameters are not valid method names + return B((length != 2) || (source[0] != '_') || (source[1] == '0') || !pm_char_is_decimal_digit(source[1])); + case PM_SLICE_TYPE_CONSTANT: + // all constants are valid method names + case PM_SLICE_TYPE_METHOD_NAME: + // all method names are valid method names + return PM_STRING_QUERY_TRUE; + } + + switch (length) { + case 1: + return B(C1('&') || C1('`') || C1('!') || C1('^') || C1('>') || C1('<') || C1('-') || C1('%') || C1('|') || C1('+') || C1('/') || C1('*') || C1('~')); + case 2: + return B(C2("!=") || C2("!~") || C2("[]") || C2("==") || C2("=~") || C2(">=") || C2(">>") || C2("<=") || C2("<<") || C2("**")); + case 3: + return B(C3("===") || C3("<=>") || C3("[]=")); + default: + return PM_STRING_QUERY_FALSE; + } + +#undef B +#undef C1 +#undef C2 +#undef C3 +} From 6901e85f937643d39195499eee82cb845acba1fc Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 15:23:52 -0400 Subject: [PATCH 190/289] Trim down prism.h --- include/prism.h | 16 +--------------- src/prism.c | 5 +++++ templates/src/serialize.c.erb | 18 +++++++++++++----- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/prism.h b/include/prism.h index 6e5b2dd083..68b21122d3 100644 --- a/include/prism.h +++ b/include/prism.h @@ -13,6 +13,7 @@ extern "C" { #include "prism/arena.h" #include "prism/ast.h" #include "prism/diagnostic.h" +#include "prism/excludes.h" #include "prism/node.h" #include "prism/options.h" #include "prism/parser.h" @@ -20,21 +21,6 @@ extern "C" { #include "prism/string_query.h" #include "prism/version.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - /** * The prism version and the serialization format. * diff --git a/src/prism.c b/src/prism.c index aee3e63599..ffc9aad8aa 100644 --- a/src/prism.c +++ b/src/prism.c @@ -27,7 +27,12 @@ #include "prism/node_new.h" +#include +#include #include +#include +#include +#include #include /** diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 69ee654242..b62d0bf066 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,17 +1,25 @@ -#include "prism.h" +#include "prism/excludes.h" + +// We optionally support serializing to a binary string. For systems that don't +// want or need this functionality, it can be turned off with the +// PRISM_EXCLUDE_SERIALIZATION define. +#ifndef PRISM_EXCLUDE_SERIALIZATION #include "prism/compiler/inline.h" + #include "prism/internal/buffer.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" -// We optionally support serializing to a binary string. For systems that don't -// want or need this functionality, it can be turned off with the -// PRISM_EXCLUDE_SERIALIZATION define. -#ifndef PRISM_EXCLUDE_SERIALIZATION +#include "prism.h" +#include "prism/ast.h" +#include "prism/diagnostic.h" +#include "prism/parser.h" +#include #include +#include static PRISM_INLINE uint32_t pm_ptrdifft_to_u32(ptrdiff_t value) { From 92b48ce940d79f1ac58d8d497c41377644ca11b6 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 15:27:04 -0400 Subject: [PATCH 191/289] pm_string_free -> pm_string_cleanup --- ext/prism/extension.c | 28 ++++++++++++------------ include/prism/strings.h | 10 ++++----- lib/prism/ffi.rb | 4 ++-- rust/ruby-prism-sys/build/main.rs | 2 +- rust/ruby-prism-sys/tests/utils_tests.rs | 6 ++--- src/options.c | 6 ++--- src/prism.c | 6 ++--- src/regexp.c | 2 +- src/strings.c | 6 ++--- 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index ad80a35804..77a0d9dc9b 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -417,7 +417,7 @@ dump(int argc, VALUE *argv, VALUE self) { xfree_sized(dup, length); #endif - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; @@ -440,7 +440,7 @@ dump_file(int argc, VALUE *argv, VALUE self) { file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = dump_input(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; @@ -813,7 +813,7 @@ lex(int argc, VALUE *argv, VALUE self) { string_options(argc, argv, &input, &options); VALUE result = parse_lex_input(&input, &options, false); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return result; @@ -836,7 +836,7 @@ lex_file(int argc, VALUE *argv, VALUE self) { file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_lex_input(&input, &options, false); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; @@ -936,7 +936,7 @@ parse(int argc, VALUE *argv, VALUE self) { xfree_sized(dup, length); #endif - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; } @@ -958,7 +958,7 @@ parse_file(int argc, VALUE *argv, VALUE self) { file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_input(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; @@ -994,7 +994,7 @@ profile(int argc, VALUE *argv, VALUE self) { string_options(argc, argv, &input, &options); profile_input(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return Qnil; @@ -1018,7 +1018,7 @@ profile_file(int argc, VALUE *argv, VALUE self) { file_options(argc, argv, &input, &options, &encoded_filepath); profile_input(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return Qnil; @@ -1124,7 +1124,7 @@ parse_comments(int argc, VALUE *argv, VALUE self) { string_options(argc, argv, &input, &options); VALUE result = parse_input_comments(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return result; @@ -1147,7 +1147,7 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_input_comments(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; @@ -1175,7 +1175,7 @@ parse_lex(int argc, VALUE *argv, VALUE self) { string_options(argc, argv, &input, &options); VALUE value = parse_lex_input(&input, &options, true); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; @@ -1205,7 +1205,7 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { file_options(argc, argv, &input, &options, &encoded_filepath); VALUE value = parse_lex_input(&input, &options, true); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return value; @@ -1244,7 +1244,7 @@ parse_success_p(int argc, VALUE *argv, VALUE self) { string_options(argc, argv, &input, &options); VALUE result = parse_input_success_p(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return result; @@ -1280,7 +1280,7 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) { file_options(argc, argv, &input, &options, &encoded_filepath); VALUE result = parse_input_success_p(&input, &options); - pm_string_free(&input); + pm_string_cleanup(&input); pm_options_free(&options); return result; diff --git a/include/prism/strings.h b/include/prism/strings.h index 6f659fc0e7..e4de068abc 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -30,11 +30,11 @@ typedef struct { /** This is a slice of another string, and should not be freed. */ PM_STRING_SHARED, - /** This string owns its memory, and should be freed using `pm_string_free()`. */ + /** This string owns its memory, and should be freed using `pm_string_cleanup()`. */ PM_STRING_OWNED, #ifdef PRISM_HAS_MMAP - /** This string is a memory-mapped file, and should be freed using `pm_string_free()`. */ + /** This string is a memory-mapped file, and should be freed using `pm_string_cleanup()`. */ PM_STRING_MAPPED #endif } type; @@ -82,7 +82,7 @@ typedef enum { /** * Read the file indicated by the filepath parameter into source and load its * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_free` when it is no longer used. + * should be freed using `pm_string_cleanup` when it is no longer used. * * We want to use demand paging as much as possible in order to avoid having to * read the entire file into memory (which could be detrimental to performance @@ -101,7 +101,7 @@ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_ /** * Read the file indicated by the filepath parameter into source and load its * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_free` when it is no longer used. + * should be freed using `pm_string_cleanup` when it is no longer used. * * @param string The string to initialize. * @param filepath The filepath to read. @@ -138,6 +138,6 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *stri * * \public \memberof pm_string_t */ -PRISM_EXPORTED_FUNCTION void pm_string_free(pm_string_t *string); +PRISM_EXPORTED_FUNCTION void pm_string_cleanup(pm_string_t *string); #endif diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index e9682c527c..5f5c55378a 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -117,7 +117,7 @@ def self.load_exported_functions_from(header, *functions, callbacks) load_exported_functions_from( "prism/strings.h", "pm_string_mapped_init", - "pm_string_free", + "pm_string_cleanup", "pm_string_source", "pm_string_length", "pm_string_sizeof", @@ -219,7 +219,7 @@ def self.with_file(filepath) raise "Unknown error initializing pm_string_t: #{result.inspect}" end ensure - LibRubyParser.pm_string_free(pm_string) + LibRubyParser.pm_string_cleanup(pm_string) end end end diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 3bbf4fbbeb..76bbe603f1 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -167,7 +167,7 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_function("pm_parser_init") .allowlist_function("pm_size_to_native") .allowlist_function("pm_string_constant_init") - .allowlist_function("pm_string_free") + .allowlist_function("pm_string_cleanup") .allowlist_function("pm_string_length") .allowlist_function("pm_string_source") .allowlist_function("pm_version") diff --git a/rust/ruby-prism-sys/tests/utils_tests.rs b/rust/ruby-prism-sys/tests/utils_tests.rs index 2c42750dd9..20cce8ea2e 100644 --- a/rust/ruby-prism-sys/tests/utils_tests.rs +++ b/rust/ruby-prism-sys/tests/utils_tests.rs @@ -14,7 +14,7 @@ fn version_test() { mod string { use ruby_prism_sys::{ - pm_string_free, pm_string_length, pm_string_source, pm_string_t, pm_string_t__bindgen_ty_1, PM_STRING_CONSTANT, + pm_string_cleanup, pm_string_length, pm_string_source, pm_string_t, pm_string_t__bindgen_ty_1, PM_STRING_CONSTANT, PM_STRING_MAPPED, PM_STRING_OWNED, PM_STRING_SHARED, }; @@ -54,7 +54,7 @@ mod string { let result_start = pm_string_source(&raw const s.pm_string); assert_eq!(s.start_ptr(), result_start); - pm_string_free(&raw mut s.pm_string); + pm_string_cleanup(&raw mut s.pm_string); } } @@ -84,7 +84,7 @@ mod string { let result_start = pm_string_source(&raw const s.pm_string); assert_eq!(s.pm_string.source, result_start); - pm_string_free(&raw mut s.pm_string); + pm_string_cleanup(&raw mut s.pm_string); } } diff --git a/src/options.c b/src/options.c index 39f4f2fea5..4848fa0ac9 100644 --- a/src/options.c +++ b/src/options.c @@ -224,14 +224,14 @@ pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) { */ void pm_options_free(pm_options_t *options) { - pm_string_free(&options->filepath); - pm_string_free(&options->encoding); + pm_string_cleanup(&options->filepath); + pm_string_cleanup(&options->encoding); for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { pm_options_scope_t *scope = &options->scopes[scope_index]; for (size_t local_index = 0; local_index < scope->locals_count; local_index++) { - pm_string_free(&scope->locals[local_index]); + pm_string_cleanup(&scope->locals[local_index]); } xfree_sized(scope->locals, scope->locals_count * sizeof(pm_string_t)); diff --git a/src/prism.c b/src/prism.c index ffc9aad8aa..24d7a49038 100644 --- a/src/prism.c +++ b/src/prism.c @@ -7807,7 +7807,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { // When we're done, we want to free the string in case we had to // allocate memory for it. - pm_string_free(&key); + pm_string_cleanup(&key); // Allocate a new magic comment node to append to the parser's list. pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) pm_arena_alloc(&parser->metadata_arena, sizeof(pm_magic_comment_t), PRISM_ALIGNOF(pm_magic_comment_t)); @@ -21375,7 +21375,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t pm_string_owned_init(&owned, (uint8_t *) memory, total_length); result = parse_interpolated_regular_expression_named_captures(parser, &owned, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)); - pm_string_free(&owned); + pm_string_cleanup(&owned); } } else if (PM_NODE_TYPE_P(node, PM_REGULAR_EXPRESSION_NODE)) { // If we have a regular expression node, then we can parse @@ -22489,7 +22489,7 @@ pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_ch */ void pm_parser_cleanup(pm_parser_t *parser) { - pm_string_free(&parser->filepath); + pm_string_cleanup(&parser->filepath); pm_arena_free(&parser->metadata_arena); while (parser->current_scope != NULL) { diff --git a/src/regexp.c b/src/regexp.c index 3013974367..2ee2555686 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -168,7 +168,7 @@ pm_regexp_parser_named_capture(pm_regexp_parser_t *parser, const uint8_t *start, pm_string_t string; pm_string_shared_init(&string, start, end); parser->name_callback(parser->parser, &string, parser->shared, parser->name_data); - pm_string_free(&string); + pm_string_cleanup(&string); } /** diff --git a/src/strings.c b/src/strings.c index 37b48293ab..88bb5ad24f 100644 --- a/src/strings.c +++ b/src/strings.c @@ -127,7 +127,7 @@ pm_string_file_handle_close(pm_string_file_handle_t *handle) { /** * Read the file indicated by the filepath parameter into source and load its * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_free` when it is no longer used. + * should be freed using `pm_string_cleanup` when it is no longer used. * * We want to use demand paging as much as possible in order to avoid having to * read the entire file into memory (which could be detrimental to performance @@ -223,7 +223,7 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { /** * Read the file indicated by the filepath parameter into source and load its * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_free` when it is no longer used. + * should be freed using `pm_string_cleanup` when it is no longer used. */ pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath) { @@ -383,7 +383,7 @@ pm_string_source(const pm_string_t *string) { * Free the associated memory of the given string. */ void -pm_string_free(pm_string_t *string) { +pm_string_cleanup(pm_string_t *string) { void *memory = (void *) string->source; if (string->type == PM_STRING_OWNED) { From 0edaefbf2be84a39ca49a5cfb04eff83867d8a59 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 15:27:32 -0400 Subject: [PATCH 192/289] pm_options_free -> pm_options_cleanup --- ext/prism/extension.c | 38 +++++++++++++++---------------- include/prism/options.h | 2 +- rust/ruby-prism-sys/build/main.rs | 2 +- rust/ruby-prism/src/lib.rs | 4 ++-- src/options.c | 4 ++-- src/prism.c | 8 +++---- templates/src/serialize.c.erb | 4 ++-- 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 77a0d9dc9b..d6e446907b 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -288,14 +288,14 @@ extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) { rb_protect(build_options, (VALUE) argument, &state); if (state != 0) { - pm_options_free(options); + pm_options_cleanup(options); rb_jump_tag(state); } } if (!NIL_P(filepath)) { if (!RB_TYPE_P(filepath, T_STRING)) { - pm_options_free(options); + pm_options_cleanup(options); rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(filepath)); } @@ -336,7 +336,7 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V case PM_STRING_INIT_SUCCESS: break; case PM_STRING_INIT_ERROR_GENERIC: { - pm_options_free(options); + pm_options_cleanup(options); #ifdef _WIN32 int e = rb_w32_map_errno(GetLastError()); @@ -348,11 +348,11 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V break; } case PM_STRING_INIT_ERROR_DIRECTORY: - pm_options_free(options); + pm_options_cleanup(options); rb_syserr_fail(EISDIR, source); break; default: - pm_options_free(options); + pm_options_cleanup(options); rb_raise(rb_eRuntimeError, "Unknown error (%d) initializing file: %s", result, source); break; } @@ -418,7 +418,7 @@ dump(int argc, VALUE *argv, VALUE self) { #endif pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -441,7 +441,7 @@ dump_file(int argc, VALUE *argv, VALUE self) { VALUE value = dump_input(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -814,7 +814,7 @@ lex(int argc, VALUE *argv, VALUE self) { VALUE result = parse_lex_input(&input, &options, false); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return result; } @@ -837,7 +837,7 @@ lex_file(int argc, VALUE *argv, VALUE self) { VALUE value = parse_lex_input(&input, &options, false); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -937,7 +937,7 @@ parse(int argc, VALUE *argv, VALUE self) { #endif pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -959,7 +959,7 @@ parse_file(int argc, VALUE *argv, VALUE self) { VALUE value = parse_input(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -995,7 +995,7 @@ profile(int argc, VALUE *argv, VALUE self) { string_options(argc, argv, &input, &options); profile_input(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return Qnil; } @@ -1019,7 +1019,7 @@ profile_file(int argc, VALUE *argv, VALUE self) { profile_input(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return Qnil; } @@ -1125,7 +1125,7 @@ parse_comments(int argc, VALUE *argv, VALUE self) { VALUE result = parse_input_comments(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return result; } @@ -1148,7 +1148,7 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { VALUE value = parse_input_comments(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -1176,7 +1176,7 @@ parse_lex(int argc, VALUE *argv, VALUE self) { VALUE value = parse_lex_input(&input, &options, true); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -1206,7 +1206,7 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { VALUE value = parse_lex_input(&input, &options, true); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return value; } @@ -1245,7 +1245,7 @@ parse_success_p(int argc, VALUE *argv, VALUE self) { VALUE result = parse_input_success_p(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return result; } @@ -1281,7 +1281,7 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) { VALUE result = parse_input_success_p(&input, &options); pm_string_cleanup(&input); - pm_options_free(&options); + pm_options_cleanup(&options); return result; } diff --git a/include/prism/options.h b/include/prism/options.h index 4c8728c69a..75fed285b8 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -414,6 +414,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); +PRISM_EXPORTED_FUNCTION void pm_options_cleanup(pm_options_t *options); #endif diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 76bbe603f1..d239dbc51e 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -152,7 +152,7 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_function("pm_options_encoding_locked_set") .allowlist_function("pm_options_encoding_set") .allowlist_function("pm_options_filepath_set") - .allowlist_function("pm_options_free") + .allowlist_function("pm_options_cleanup") .allowlist_function("pm_options_frozen_string_literal_set") .allowlist_function("pm_options_line_set") .allowlist_function("pm_options_main_script_set") diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 3725633378..540f140555 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -27,7 +27,7 @@ pub use self::node_ext::{ConstantPathError, FullName}; pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnostics, Location, MagicComment, MagicComments, ParseResult}; use ruby_prism_sys::{ - pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_free, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_partial_script_set, pm_options_scope_forwarding_set, + pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_cleanup, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_partial_script_set, pm_options_scope_forwarding_set, pm_options_scope_get, pm_options_scope_init, pm_options_scope_local_get, pm_options_scopes_init, pm_options_t, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, }; @@ -324,7 +324,7 @@ pub struct ParseOptions { impl Drop for ParseOptions { fn drop(&mut self) { - unsafe { pm_options_free(&raw mut self.options) }; + unsafe { pm_options_cleanup(&raw mut self.options) }; } } diff --git a/src/options.c b/src/options.c index 4848fa0ac9..9817691e73 100644 --- a/src/options.c +++ b/src/options.c @@ -223,7 +223,7 @@ pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) { * Free the internal memory associated with the options. */ void -pm_options_free(pm_options_t *options) { +pm_options_cleanup(pm_options_t *options) { pm_string_cleanup(&options->filepath); pm_string_cleanup(&options->encoding); @@ -323,7 +323,7 @@ pm_options_read(pm_options_t *options, const char *data) { pm_options_scope_t *scope = &options->scopes[scope_index]; if (!pm_options_scope_init(scope, locals_count)) { - pm_options_free(options); + pm_options_cleanup(options); return; } diff --git a/src/prism.c b/src/prism.c index 24d7a49038..06cfc14b9a 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22773,7 +22773,7 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { bool result = parser.error_list.size == 0; pm_parser_cleanup(&parser); pm_arena_free(&arena); - pm_options_free(&options); + pm_options_cleanup(&options); return result; } @@ -22828,7 +22828,7 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons pm_parser_cleanup(&parser); pm_arena_free(&arena); - pm_options_free(&options); + pm_options_cleanup(&options); } /** @@ -22851,7 +22851,7 @@ pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fge pm_buffer_free(parser_buffer); pm_parser_cleanup(&parser); pm_arena_free(&arena); - pm_options_free(&options); + pm_options_cleanup(&options); } /** @@ -22874,7 +22874,7 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s pm_parser_cleanup(&parser); pm_arena_free(&arena); - pm_options_free(&options); + pm_options_cleanup(&options); } #endif diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index b62d0bf066..b305a95d7e 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -348,7 +348,7 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const pm_parser_cleanup(&parser); pm_arena_free(&arena); - pm_options_free(&options); + pm_options_cleanup(&options); } /** @@ -377,7 +377,7 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_parser_cleanup(&parser); pm_arena_free(&arena); - pm_options_free(&options); + pm_options_cleanup(&options); } #endif From 20de0e4c9c7aff85fc686acb084a2d301ce9437c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 15:35:06 -0400 Subject: [PATCH 193/289] Do not return bool from pm_options_scope_init --- ext/prism/extension.c | 4 +--- include/prism/options.h | 6 +++--- src/options.c | 9 +++------ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index d6e446907b..e352eeef4f 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -149,9 +149,7 @@ build_options_scopes(pm_options_t *options, VALUE scopes) { // Initialize the scope array. size_t locals_count = RARRAY_LEN(locals); pm_options_scope_t *options_scope = &options->scopes[scope_index]; - if (!pm_options_scope_init(options_scope, locals_count)) { - rb_raise(rb_eNoMemError, "failed to allocate memory"); - } + pm_options_scope_init(options_scope, locals_count); // Iterate over the locals and add them to the scope. for (size_t local_index = 0; local_index < locals_count; local_index++) { diff --git a/include/prism/options.h b/include/prism/options.h index 75fed285b8..607394d092 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -376,15 +376,15 @@ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm /** * Create a new options scope struct. This will hold a set of locals that are in - * scope surrounding the code that is being parsed. + * scope surrounding the code that is being parsed. If the scope was unable to + * allocate its locals, this function will abort the process. * * @param scope The scope struct to initialize. * @param locals_count The number of locals to allocate. - * @return Whether or not the scope was initialized successfully. * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count); +PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count); /** * Return a pointer to the local at the given index within the given scope. diff --git a/src/options.c b/src/options.c index 9817691e73..b99db37ab5 100644 --- a/src/options.c +++ b/src/options.c @@ -195,12 +195,12 @@ pm_options_scope_get(const pm_options_t *options, size_t index) { * Create a new options scope struct. This will hold a set of locals that are in * scope surrounding the code that is being parsed. */ -bool +void pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) { scope->locals_count = locals_count; scope->locals = xcalloc(locals_count, sizeof(pm_string_t)); scope->forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE; - return scope->locals != NULL; + if (scope->locals == NULL) abort(); } /** @@ -322,10 +322,7 @@ pm_options_read(pm_options_t *options, const char *data) { data += 4; pm_options_scope_t *scope = &options->scopes[scope_index]; - if (!pm_options_scope_init(scope, locals_count)) { - pm_options_cleanup(options); - return; - } + pm_options_scope_init(scope, locals_count); uint8_t forwarding = (uint8_t) *data++; pm_options_scope_forwarding_set(&options->scopes[scope_index], forwarding); From 01676454903c352056b51166605a1d2e179664aa Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 19:42:45 -0400 Subject: [PATCH 194/289] Make options fully opaque --- ext/prism/extension.c | 174 +++++++++++------------ include/prism/internal/options.h | 116 ++++++++++++++++ include/prism/node.h | 7 +- include/prism/options.h | 222 +++++++++++++----------------- rust/ruby-prism-sys/build/main.rs | 10 +- rust/ruby-prism/src/lib.rs | 55 ++++---- src/options.c | 122 ++++++++++++---- 7 files changed, 439 insertions(+), 267 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index e352eeef4f..5c4e309d42 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -148,7 +148,7 @@ build_options_scopes(pm_options_t *options, VALUE scopes) { // Initialize the scope array. size_t locals_count = RARRAY_LEN(locals); - pm_options_scope_t *options_scope = &options->scopes[scope_index]; + pm_options_scope_t *options_scope = pm_options_scope_get_mut(options, scope_index); pm_options_scope_init(options_scope, locals_count); // Iterate over the locals and add them to the scope. @@ -162,7 +162,7 @@ build_options_scopes(pm_options_t *options, VALUE scopes) { } // Add the local to the scope. - pm_string_t *scope_local = &options_scope->locals[local_index]; + pm_string_t *scope_local = pm_options_scope_local_get_mut(options_scope, local_index); const char *name = rb_id2name(SYM2ID(local)); pm_string_constant_init(scope_local, name, strlen(name)); } @@ -206,10 +206,10 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { if (!pm_options_version_set(options, ruby_version, 3)) { // Prism doesn't know this specific version. Is it lower? if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { - options->version = PM_OPTIONS_VERSION_CRUBY_3_3; + pm_options_version_set_lowest(options); } else { // Must be higher. - options->version = PM_OPTIONS_VERSION_LATEST; + pm_options_version_set_highest(options); } } } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { @@ -276,7 +276,7 @@ build_options(VALUE argument) { */ static void extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) { - options->line = 1; // default + pm_options_line_set(options, 1); /* default */ if (!NIL_P(keywords)) { struct build_options_data data = { .options = options, .keywords = keywords }; @@ -286,14 +286,14 @@ extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) { rb_protect(build_options, (VALUE) argument, &state); if (state != 0) { - pm_options_cleanup(options); + pm_options_free(options); rb_jump_tag(state); } } if (!NIL_P(filepath)) { if (!RB_TYPE_P(filepath, T_STRING)) { - pm_options_cleanup(options); + pm_options_free(options); rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(filepath)); } @@ -327,14 +327,14 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V *encoded_filepath = rb_str_encode_ospath(filepath); extract_options(options, *encoded_filepath, keywords); - const char *source = (const char *) pm_string_source(&options->filepath); + const char *source = (const char *) pm_string_source(pm_options_filepath_get(options)); pm_string_init_result_t result; switch (result = pm_string_file_init(input, source)) { case PM_STRING_INIT_SUCCESS: break; case PM_STRING_INIT_ERROR_GENERIC: { - pm_options_cleanup(options); + pm_options_free(options); #ifdef _WIN32 int e = rb_w32_map_errno(GetLastError()); @@ -346,11 +346,11 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V break; } case PM_STRING_INIT_ERROR_DIRECTORY: - pm_options_cleanup(options); + pm_options_free(options); rb_syserr_fail(EISDIR, source); break; default: - pm_options_cleanup(options); + pm_options_free(options); rb_raise(rb_eRuntimeError, "Unknown error (%d) initializing file: %s", result, source); break; } @@ -398,8 +398,8 @@ dump_input(pm_string_t *input, const pm_options_t *options) { static VALUE dump(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; - string_options(argc, argv, &input, &options); + pm_options_t *options = pm_options_new(); + string_options(argc, argv, &input, options); #ifdef PRISM_BUILD_DEBUG size_t length = pm_string_length(&input); @@ -408,15 +408,15 @@ dump(int argc, VALUE *argv, VALUE self) { pm_string_constant_init(&input, dup, length); #endif - VALUE value = dump_input(&input, &options); - if (options.freeze) rb_obj_freeze(value); + VALUE value = dump_input(&input, options); + if (pm_options_freeze_get(options)) rb_obj_freeze(value); #ifdef PRISM_BUILD_DEBUG xfree_sized(dup, length); #endif pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -432,14 +432,14 @@ dump(int argc, VALUE *argv, VALUE self) { static VALUE dump_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, &options, &encoded_filepath); + file_options(argc, argv, &input, options, &encoded_filepath); - VALUE value = dump_input(&input, &options); + VALUE value = dump_input(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -749,7 +749,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod .source = source, .tokens = rb_ary_new(), .encoding = rb_utf8_encoding(), - .freeze = options->freeze, + .freeze = pm_options_freeze_get(options), }; parse_lex_data_t *data = &parse_lex_data; @@ -772,7 +772,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod rb_ary_push(offsets, ULONG2NUM(parser.line_offsets.offsets[index])); } - if (options->freeze) { + if (pm_options_freeze_get(options)) { rb_obj_freeze(source_string); rb_obj_freeze(offsets); rb_obj_freeze(source); @@ -782,12 +782,12 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod VALUE result; if (return_nodes) { VALUE value = rb_ary_new_capa(2); - rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source, options->freeze)); + rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source, pm_options_freeze_get(options))); rb_ary_push(value, parse_lex_data.tokens); - if (options->freeze) rb_obj_freeze(value); - result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source, options->freeze); + if (pm_options_freeze_get(options)) rb_obj_freeze(value); + result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source, pm_options_freeze_get(options)); } else { - result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, options->freeze); + result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, pm_options_freeze_get(options)); } pm_parser_cleanup(&parser); @@ -807,12 +807,12 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod static VALUE lex(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; - string_options(argc, argv, &input, &options); + pm_options_t *options = pm_options_new(); + string_options(argc, argv, &input, options); - VALUE result = parse_lex_input(&input, &options, false); + VALUE result = parse_lex_input(&input, options, false); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return result; } @@ -828,14 +828,14 @@ lex(int argc, VALUE *argv, VALUE self) { static VALUE lex_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, &options, &encoded_filepath); + file_options(argc, argv, &input, options, &encoded_filepath); - VALUE value = parse_lex_input(&input, &options, false); + VALUE value = parse_lex_input(&input, options, false); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -856,11 +856,12 @@ parse_input(pm_string_t *input, const pm_options_t *options) { pm_node_t *node = pm_parse(&parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); - VALUE source = pm_source_new(&parser, encoding, options->freeze); - VALUE value = pm_ast_new(&parser, node, encoding, source, options->freeze); - VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options->freeze); + bool freeze = pm_options_freeze_get(options); + VALUE source = pm_source_new(&parser, encoding, freeze); + VALUE value = pm_ast_new(&parser, node, encoding, source, freeze); + VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, freeze); - if (options->freeze) { + if (freeze) { rb_obj_freeze(source); } @@ -918,8 +919,8 @@ parse_input(pm_string_t *input, const pm_options_t *options) { static VALUE parse(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; - string_options(argc, argv, &input, &options); + pm_options_t *options = pm_options_new(); + string_options(argc, argv, &input, options); #ifdef PRISM_BUILD_DEBUG size_t length = pm_string_length(&input); @@ -928,14 +929,14 @@ parse(int argc, VALUE *argv, VALUE self) { pm_string_constant_init(&input, dup, length); #endif - VALUE value = parse_input(&input, &options); + VALUE value = parse_input(&input, options); #ifdef PRISM_BUILD_DEBUG xfree_sized(dup, length); #endif pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -950,14 +951,14 @@ parse(int argc, VALUE *argv, VALUE self) { static VALUE parse_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, &options, &encoded_filepath); + file_options(argc, argv, &input, options, &encoded_filepath); - VALUE value = parse_input(&input, &options); + VALUE value = parse_input(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -988,12 +989,12 @@ profile_input(pm_string_t *input, const pm_options_t *options) { static VALUE profile(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); - string_options(argc, argv, &input, &options); - profile_input(&input, &options); + string_options(argc, argv, &input, options); + profile_input(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return Qnil; } @@ -1010,14 +1011,14 @@ profile(int argc, VALUE *argv, VALUE self) { static VALUE profile_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, &options, &encoded_filepath); + file_options(argc, argv, &input, options, &encoded_filepath); - profile_input(&input, &options); + profile_input(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return Qnil; } @@ -1065,23 +1066,24 @@ parse_stream(int argc, VALUE *argv, VALUE self) { VALUE keywords; rb_scan_args(argc, argv, "1:", &stream, &keywords); - pm_options_t options = { 0 }; - extract_options(&options, Qnil, keywords); + pm_options_t *options = pm_options_new(); + extract_options(options, Qnil, keywords); pm_arena_t arena = { 0 }; pm_parser_t parser; pm_buffer_t *buffer = pm_buffer_new(); - pm_node_t *node = pm_parse_stream(&arena, &parser, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options); + pm_node_t *node = pm_parse_stream(&arena, &parser, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, options); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); - VALUE source = pm_source_new(&parser, encoding, options.freeze); - VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze); - VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze); + VALUE source = pm_source_new(&parser, encoding, pm_options_freeze_get(options)); + VALUE value = pm_ast_new(&parser, node, encoding, source, pm_options_freeze_get(options)); + VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, pm_options_freeze_get(options)); pm_buffer_free(buffer); pm_parser_cleanup(&parser); pm_arena_free(&arena); + pm_options_free(options); return result; } @@ -1098,8 +1100,8 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { pm_parse(&parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); - VALUE source = pm_source_new(&parser, encoding, options->freeze); - VALUE comments = parser_comments(&parser, source, options->freeze); + VALUE source = pm_source_new(&parser, encoding, pm_options_freeze_get(options)); + VALUE comments = parser_comments(&parser, source, pm_options_freeze_get(options)); pm_parser_cleanup(&parser); pm_arena_free(&arena); @@ -1118,12 +1120,12 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { static VALUE parse_comments(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; - string_options(argc, argv, &input, &options); + pm_options_t *options = pm_options_new(); + string_options(argc, argv, &input, options); - VALUE result = parse_input_comments(&input, &options); + VALUE result = parse_input_comments(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return result; } @@ -1139,14 +1141,14 @@ parse_comments(int argc, VALUE *argv, VALUE self) { static VALUE parse_file_comments(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, &options, &encoded_filepath); + file_options(argc, argv, &input, options, &encoded_filepath); - VALUE value = parse_input_comments(&input, &options); + VALUE value = parse_input_comments(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -1169,12 +1171,12 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { static VALUE parse_lex(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; - string_options(argc, argv, &input, &options); + pm_options_t *options = pm_options_new(); + string_options(argc, argv, &input, options); - VALUE value = parse_lex_input(&input, &options, true); + VALUE value = parse_lex_input(&input, options, true); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -1197,14 +1199,14 @@ parse_lex(int argc, VALUE *argv, VALUE self) { static VALUE parse_lex_file(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, &options, &encoded_filepath); + file_options(argc, argv, &input, options, &encoded_filepath); - VALUE value = parse_lex_input(&input, &options, true); + VALUE value = parse_lex_input(&input, options, true); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return value; } @@ -1238,12 +1240,12 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { static VALUE parse_success_p(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; - string_options(argc, argv, &input, &options); + pm_options_t *options = pm_options_new(); + string_options(argc, argv, &input, options); - VALUE result = parse_input_success_p(&input, &options); + VALUE result = parse_input_success_p(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return result; } @@ -1272,14 +1274,14 @@ parse_failure_p(int argc, VALUE *argv, VALUE self) { static VALUE parse_file_success_p(int argc, VALUE *argv, VALUE self) { pm_string_t input; - pm_options_t options = { 0 }; + pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, &options, &encoded_filepath); + file_options(argc, argv, &input, options, &encoded_filepath); - VALUE result = parse_input_success_p(&input, &options); + VALUE result = parse_input_success_p(&input, options); pm_string_cleanup(&input); - pm_options_cleanup(&options); + pm_options_free(options); return result; } diff --git a/include/prism/internal/options.h b/include/prism/internal/options.h index e3fb0a9e5e..2dea2f9422 100644 --- a/include/prism/internal/options.h +++ b/include/prism/internal/options.h @@ -8,6 +8,122 @@ #include "prism/options.h" +/** + * A scope of locals surrounding the code that is being parsed. + */ +struct pm_options_scope_t { + /** The number of locals in the scope. */ + size_t locals_count; + + /** The names of the locals in the scope. */ + pm_string_t *locals; + + /** Flags for the set of forwarding parameters in this scope. */ + uint8_t forwarding; +}; + +/** + * The options that can be passed to the parser. + */ +struct pm_options_t { + /** + * The callback to call when additional switches are found in a shebang + * comment. + */ + pm_options_shebang_callback_t shebang_callback; + + /** + * Any additional data that should be passed along to the shebang callback + * if one was set. + */ + void *shebang_callback_data; + + /** The name of the file that is currently being parsed. */ + pm_string_t filepath; + + /** + * The line within the file that the parse starts on. This value is + * 1-indexed. + */ + int32_t line; + + /** + * The name of the encoding that the source file is in. Note that this must + * correspond to a name that can be found with Encoding.find in Ruby. + */ + pm_string_t encoding; + + /** + * The number of scopes surrounding the code that is being parsed. + */ + size_t scopes_count; + + /** + * The scopes surrounding the code that is being parsed. For most parses + * this will be NULL, but for evals it will be the locals that are in scope + * surrounding the eval. Scopes are ordered from the outermost scope to the + * innermost one. + */ + pm_options_scope_t *scopes; + + /** + * The version of prism that we should be parsing with. This is used to + * allow consumers to specify which behavior they want in case they need to + * parse exactly as a specific version of CRuby. + */ + pm_options_version_t version; + + /** A bitset of the various options that were set on the command line. */ + uint8_t command_line; + + /** + * Whether or not the frozen string literal option has been set. + * May be: + * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET + */ + int8_t frozen_string_literal; + + /** + * Whether or not the encoding magic comments should be respected. This is a + * niche use-case where you want to parse a file with a specific encoding + * but ignore any encoding magic comments at the top of the file. + */ + bool encoding_locked; + + /** + * When the file being parsed is the main script, the shebang will be + * considered for command-line flags (or for implicit -x). The caller needs + * to pass this information to the parser so that it can behave correctly. + */ + bool main_script; + + /** + * When the file being parsed is considered a "partial" script, jumps will + * not be marked as errors if they are not contained within loops/blocks. + * This is used in the case that you're parsing a script that you know will + * be embedded inside another script later, but you do not have that context + * yet. For example, when parsing an ERB template that will be evaluated + * inside another script. + */ + bool partial_script; + + /** + * Whether or not the parser should freeze the nodes that it creates. This + * makes it possible to have a deeply frozen AST that is safe to share + * between concurrency primitives. + */ + bool freeze; +}; + +/** + * Free the internal memory associated with the options. + * + * @param options The options struct whose internal memory should be freed. + */ +void pm_options_cleanup(pm_options_t *options); + /** * Deserialize an options struct from the given binary string. This is used to * pass options to the parser from an FFI call so that consumers of the library diff --git a/include/prism/node.h b/include/prism/node.h index 2390dc7290..576919047c 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -82,9 +82,10 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * size_t size = strlen(source); * * pm_arena_t arena = { 0 }; + * pm_options_t *options = pm_options_new(); + * * pm_parser_t parser; - * pm_options_t options = { 0 }; - * pm_parser_init(&arena, &parser, (const uint8_t *) source, size, &options); + * pm_parser_init(&arena, &parser, (const uint8_t *) source, size, options); * * size_t indent = 0; * pm_node_t *node = pm_parse(&parser); @@ -93,7 +94,9 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * pm_visit_node(node, visit, data); * * pm_parser_cleanup(&parser); + * pm_options_free(options); * pm_arena_free(&arena); + * * return EXIT_SUCCESS; * } * ``` diff --git a/include/prism/options.h b/include/prism/options.h index 607394d092..477b593b2a 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -11,6 +11,16 @@ #include #include +/** + * A scope of locals surrounding the code that is being parsed. + */ +typedef struct pm_options_scope_t pm_options_scope_t; + +/** + * The options that can be passed to the parser. + */ +typedef struct pm_options_t pm_options_t; + /** * String literals should be made frozen. */ @@ -27,20 +37,6 @@ */ #define PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED ((int8_t) 1) -/** - * A scope of locals surrounding the code that is being parsed. - */ -typedef struct pm_options_scope { - /** The number of locals in the scope. */ - size_t locals_count; - - /** The names of the locals in the scope. */ - pm_string_t *locals; - - /** Flags for the set of forwarding parameters in this scope. */ - uint8_t forwarding; -} pm_options_scope_t; - /** The default value for parameters. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_NONE = 0x0; @@ -56,9 +52,6 @@ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_BLOCK = 0x4; /** When the scope is fowarding with the ... parameter. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_ALL = 0x8; -/* Forward declaration needed by the callback typedef. */ -struct pm_options; - /** * The callback called when additional switches are found in a shebang comment * that need to be processed by the runtime. @@ -71,7 +64,7 @@ struct pm_options; * @param shebang_callback_data Any additional data that should be passed along * to the callback. */ -typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const uint8_t *source, size_t length, void *shebang_callback_data); +typedef void (*pm_options_shebang_callback_t)(pm_options_t *options, const uint8_t *source, size_t length, void *shebang_callback_data); /** * The version of Ruby syntax that we should be parsing with. This is used to @@ -104,101 +97,6 @@ typedef enum { PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_4_1 } pm_options_version_t; -/** - * The options that can be passed to the parser. - */ -typedef struct pm_options { - /** - * The callback to call when additional switches are found in a shebang - * comment. - */ - pm_options_shebang_callback_t shebang_callback; - - /** - * Any additional data that should be passed along to the shebang callback - * if one was set. - */ - void *shebang_callback_data; - - /** The name of the file that is currently being parsed. */ - pm_string_t filepath; - - /** - * The line within the file that the parse starts on. This value is - * 1-indexed. - */ - int32_t line; - - /** - * The name of the encoding that the source file is in. Note that this must - * correspond to a name that can be found with Encoding.find in Ruby. - */ - pm_string_t encoding; - - /** - * The number of scopes surrounding the code that is being parsed. - */ - size_t scopes_count; - - /** - * The scopes surrounding the code that is being parsed. For most parses - * this will be NULL, but for evals it will be the locals that are in scope - * surrounding the eval. Scopes are ordered from the outermost scope to the - * innermost one. - */ - pm_options_scope_t *scopes; - - /** - * The version of prism that we should be parsing with. This is used to - * allow consumers to specify which behavior they want in case they need to - * parse exactly as a specific version of CRuby. - */ - pm_options_version_t version; - - /** A bitset of the various options that were set on the command line. */ - uint8_t command_line; - - /** - * Whether or not the frozen string literal option has been set. - * May be: - * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED - * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED - * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET - */ - int8_t frozen_string_literal; - - /** - * Whether or not the encoding magic comments should be respected. This is a - * niche use-case where you want to parse a file with a specific encoding - * but ignore any encoding magic comments at the top of the file. - */ - bool encoding_locked; - - /** - * When the file being parsed is the main script, the shebang will be - * considered for command-line flags (or for implicit -x). The caller needs - * to pass this information to the parser so that it can behave correctly. - */ - bool main_script; - - /** - * When the file being parsed is considered a "partial" script, jumps will - * not be marked as errors if they are not contained within loops/blocks. - * This is used in the case that you're parsing a script that you know will - * be embedded inside another script later, but you do not have that context - * yet. For example, when parsing an ERB template that will be evaluated - * inside another script. - */ - bool partial_script; - - /** - * Whether or not the parser should freeze the nodes that it creates. This - * makes it possible to have a deeply frozen AST that is safe to share - * between concurrency primitives. - */ - bool freeze; -} pm_options_t; - /** * A bit representing whether or not the command line -a option was set. -a * splits the input line $_ into $F. @@ -236,6 +134,26 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_P = 0x10; */ static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20; +/** + * Allocate a new options struct. If the options struct cannot be allocated, + * this function aborts the process. + * + * @return A new options struct with default values. It is the responsibility of + * the caller to free this struct using pm_options_free(). + * + * \public \memberof pm_options + */ +PRISM_EXPORTED_FUNCTION pm_options_t * pm_options_new(void); + +/** + * Free both the held memory of the given options struct and the struct itself. + * + * @param options The options struct to free. + * + * \public \memberof pm_options + */ +PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); + /** * Set the shebang callback option on the given options struct. * @@ -248,6 +166,16 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20; */ PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data); +/** + * Get the filepath option on the given options struct. + * + * @param options The options struct to get the filepath from. + * @return The filepath. + * + * \public \memberof pm_options + */ +PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_filepath_get(pm_options_t *options); + /** * Set the filepath option on the given options struct. * @@ -322,6 +250,26 @@ PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, */ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length); +/** + * Set the version option on the given options struct to the lowest version of + * Ruby that prism supports. + * + * @param options The options struct to set the version on. + * + * \public \memberof pm_options + */ +PRISM_EXPORTED_FUNCTION void pm_options_version_set_lowest(pm_options_t *options); + +/** + * Set the version option on the given options struct to the highest version of + * Ruby that prism supports. + * + * @param options The options struct to set the version on. + * + * \public \memberof pm_options + */ +PRISM_EXPORTED_FUNCTION void pm_options_version_set_highest(pm_options_t *options); + /** * Set the main script option on the given options struct. * @@ -342,6 +290,15 @@ PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, b */ PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script); +/** + * Get the freeze option on the given options struct. + * + * @param options The options struct to get the freeze value from. + * + * \public \memberof pm_options + */ +PRISM_EXPORTED_FUNCTION bool pm_options_freeze_get(const pm_options_t *options); + /** * Set the freeze option on the given options struct. * @@ -364,16 +321,29 @@ PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool f PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count); /** - * Return a pointer to the scope at the given index within the given options. + * Return a constant pointer to the scope at the given index within the given + * options. * * @param options The options struct to get the scope from. * @param index The index of the scope to get. - * @return A pointer to the scope at the given index. + * @return A constant pointer to the scope at the given index. * * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index); +/** + * Return a mutable pointer to the scope at the given index within the given + * options. + * + * @param options The options struct to get the scope from. + * @param index The index of the scope to get. + * @return A mutable pointer to the scope at the given index. + * + * \public \memberof pm_options + */ +PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_get_mut(pm_options_t *options, size_t index); + /** * Create a new options scope struct. This will hold a set of locals that are in * scope surrounding the code that is being parsed. If the scope was unable to @@ -387,33 +357,37 @@ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count); /** - * Return a pointer to the local at the given index within the given scope. + * Return a constant pointer to the local at the given index within the given + * scope. * * @param scope The scope struct to get the local from. * @param index The index of the local to get. - * @return A pointer to the local at the given index. + * @return A constant pointer to the local at the given index. * * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index); /** - * Set the forwarding option on the given scope struct. + * Return a mutable pointer to the local at the given index within the given + * scope. * - * @param scope The scope struct to set the forwarding on. - * @param forwarding The forwarding value to set. + * @param scope The scope struct to get the local from. + * @param index The index of the local to get. + * @return A mutable pointer to the local at the given index. * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding); +PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_get_mut(pm_options_scope_t *scope, size_t index); /** - * Free the internal memory associated with the options. + * Set the forwarding option on the given scope struct. * - * @param options The options struct whose internal memory should be freed. + * @param scope The scope struct to set the forwarding on. + * @param forwarding The forwarding value to set. * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_cleanup(pm_options_t *options); +PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding); #endif diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index d239dbc51e..4cf5add131 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -135,7 +135,6 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_type("pm_node_type") .allowlist_type("pm_options_t") .allowlist_type("pm_options_scope_t") - .allowlist_type("pm_options_version_t") .allowlist_type("pm_parser_t") .allowlist_type("pm_string_t") .allowlist_type(r"^pm_\w+_node_t") @@ -144,7 +143,6 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .rustified_non_exhaustive_enum("pm_comment_type_t") .rustified_non_exhaustive_enum(r"pm_\w+_flags") .rustified_non_exhaustive_enum("pm_node_type") - .rustified_non_exhaustive_enum("pm_options_version_t") // Functions .allowlist_function("pm_arena_free") .allowlist_function("pm_line_offset_list_line_column") @@ -152,16 +150,18 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_function("pm_options_encoding_locked_set") .allowlist_function("pm_options_encoding_set") .allowlist_function("pm_options_filepath_set") - .allowlist_function("pm_options_cleanup") + .allowlist_function("pm_options_free") .allowlist_function("pm_options_frozen_string_literal_set") .allowlist_function("pm_options_line_set") .allowlist_function("pm_options_main_script_set") + .allowlist_function("pm_options_new") .allowlist_function("pm_options_partial_script_set") .allowlist_function("pm_options_scope_forwarding_set") - .allowlist_function("pm_options_scope_get") + .allowlist_function("pm_options_scope_get_mut") .allowlist_function("pm_options_scope_init") - .allowlist_function("pm_options_scope_local_get") + .allowlist_function("pm_options_scope_local_get_mut") .allowlist_function("pm_options_scopes_init") + .allowlist_function("pm_options_version_set") .allowlist_function("pm_parse") .allowlist_function("pm_parser_cleanup") .allowlist_function("pm_parser_init") diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 540f140555..7c678e1a67 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -27,8 +27,8 @@ pub use self::node_ext::{ConstantPathError, FullName}; pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnostics, Location, MagicComment, MagicComments, ParseResult}; use ruby_prism_sys::{ - pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_cleanup, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_partial_script_set, pm_options_scope_forwarding_set, - pm_options_scope_get, pm_options_scope_init, pm_options_scope_local_get, pm_options_scopes_init, pm_options_t, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, + pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_free, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_new, pm_options_partial_script_set, pm_options_scope_forwarding_set, + pm_options_scope_get_mut, pm_options_scope_init, pm_options_scope_local_get_mut, pm_options_scopes_init, pm_options_t, pm_options_version_set, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, }; /// The version of Ruby syntax to parse with. @@ -46,14 +46,16 @@ pub enum Version { CRuby4_1, } -impl From for ruby_prism_sys::pm_options_version_t { - fn from(version: Version) -> Self { - match version { - Version::Latest => Self::PM_OPTIONS_VERSION_LATEST, - Version::CRuby3_3 => Self::PM_OPTIONS_VERSION_CRUBY_3_3, - Version::CRuby3_4 => Self::PM_OPTIONS_VERSION_CRUBY_3_4, - Version::CRuby3_5 => Self::PM_OPTIONS_VERSION_CRUBY_3_5, - Version::CRuby4_1 => Self::PM_OPTIONS_VERSION_CRUBY_4_1, +impl Version { + /// Calls `pm_options_version_set` with the appropriate version string. + /// `Latest` passes `NULL` to get the default behavior. + unsafe fn set_on(self, opts: *mut pm_options_t) { + match self { + Version::Latest => { pm_options_version_set(opts, std::ptr::null(), 0); }, + Version::CRuby3_3 => { pm_options_version_set(opts, c"3.3".as_ptr(), 3); }, + Version::CRuby3_4 => { pm_options_version_set(opts, c"3.4".as_ptr(), 3); }, + Version::CRuby3_5 => { pm_options_version_set(opts, c"3.5".as_ptr(), 3); }, + Version::CRuby4_1 => { pm_options_version_set(opts, c"4.1".as_ptr(), 3); }, } } } @@ -238,58 +240,58 @@ impl Options { /// Panics if `filepath` or `encoding` contain interior null bytes. #[must_use] pub fn build(self) -> ParseOptions { - let mut opts = pm_options_t::default(); + let opts = unsafe { pm_options_new() }; let c_filepath = self.filepath.map(|filepath| { let cstring = CString::new(filepath).unwrap(); - unsafe { pm_options_filepath_set(&raw mut opts, cstring.as_ptr()) }; + unsafe { pm_options_filepath_set(opts, cstring.as_ptr()) }; cstring }); if let Some(line) = self.line { - unsafe { pm_options_line_set(&raw mut opts, line) }; + unsafe { pm_options_line_set(opts, line) }; } let c_encoding = self.encoding.map(|encoding| { let cstring = CString::new(encoding).unwrap(); - unsafe { pm_options_encoding_set(&raw mut opts, cstring.as_ptr()) }; + unsafe { pm_options_encoding_set(opts, cstring.as_ptr()) }; cstring }); if self.encoding_locked { - unsafe { pm_options_encoding_locked_set(&raw mut opts, true) }; + unsafe { pm_options_encoding_locked_set(opts, true) }; } if let Some(frozen) = self.frozen_string_literal { - unsafe { pm_options_frozen_string_literal_set(&raw mut opts, frozen) }; + unsafe { pm_options_frozen_string_literal_set(opts, frozen) }; } let command_line = self.command_line.iter().fold(0u8, |acc, &flag| acc | u8::from(flag)); if command_line != 0 { - unsafe { pm_options_command_line_set(&raw mut opts, command_line) }; + unsafe { pm_options_command_line_set(opts, command_line) }; } if let Some(version) = self.version { - opts.version = version.into(); + unsafe { version.set_on(opts) }; } if self.main_script { - unsafe { pm_options_main_script_set(&raw mut opts, true) }; + unsafe { pm_options_main_script_set(opts, true) }; } if self.partial_script { - unsafe { pm_options_partial_script_set(&raw mut opts, true) }; + unsafe { pm_options_partial_script_set(opts, true) }; } if !self.scopes.is_empty() { - unsafe { pm_options_scopes_init(&raw mut opts, self.scopes.len()) }; + unsafe { pm_options_scopes_init(opts, self.scopes.len()) }; for (scope_index, scope) in self.scopes.iter().enumerate() { - let pm_scope = unsafe { pm_options_scope_get(&raw const opts, scope_index).cast_mut() }; + let pm_scope = unsafe { pm_options_scope_get_mut(opts, scope_index) }; unsafe { pm_options_scope_init(pm_scope, scope.locals.len()) }; for (local_index, local) in scope.locals.iter().enumerate() { - let pm_local = unsafe { pm_options_scope_local_get(pm_scope, local_index).cast_mut() }; + let pm_local = unsafe { pm_options_scope_local_get_mut(pm_scope, local_index) }; unsafe { pm_string_constant_init(pm_local, local.as_ptr().cast::(), local.len()) }; } @@ -311,9 +313,8 @@ impl Options { /// The C-level parse options. Created from [`Options::build`]. Must outlive /// any [`ParseResult`] created with [`parse_with_options`]. -#[derive(Debug)] pub struct ParseOptions { - options: pm_options_t, + options: *mut pm_options_t, // These CStrings back the constant pm_string_t values inside `options`. // They must not be dropped before `options` is freed. _filepath: Option, @@ -324,7 +325,7 @@ pub struct ParseOptions { impl Drop for ParseOptions { fn drop(&mut self) { - unsafe { pm_options_cleanup(&raw mut self.options) }; + unsafe { pm_options_free(self.options) }; } } @@ -369,7 +370,7 @@ pub fn parse(source: &[u8]) -> ParseResult<'_> { /// #[must_use] pub fn parse_with_options<'a>(source: &'a [u8], options: &'a ParseOptions) -> ParseResult<'a> { - unsafe { parse_impl(source, &raw const options.options) } + unsafe { parse_impl(source, options.options) } } #[cfg(test)] diff --git a/src/options.c b/src/options.c index b99db37ab5..ecdeba58f3 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -#include "prism/options.h" +#include "prism/internal/options.h" #include "prism/compiler/inline.h" @@ -8,6 +8,49 @@ #include #include +/** + * Allocate a new options struct. If the options struct cannot be allocated, + * this function aborts the process. + */ +pm_options_t * +pm_options_new(void) { + pm_options_t *options = xcalloc(1, sizeof(pm_options_t)); + if (options == NULL) abort(); + return options; +} + +/** + * Free the internal memory associated with the options. + */ +void +pm_options_cleanup(pm_options_t *options) { + pm_string_cleanup(&options->filepath); + pm_string_cleanup(&options->encoding); + + for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { + pm_options_scope_t *scope = &options->scopes[scope_index]; + + for (size_t local_index = 0; local_index < scope->locals_count; local_index++) { + pm_string_cleanup(&scope->locals[local_index]); + } + + xfree_sized(scope->locals, scope->locals_count * sizeof(pm_string_t)); + } + + xfree_sized(options->scopes, options->scopes_count * sizeof(pm_options_scope_t)); +} + +/** + * Free both the held memory of the given options struct and the struct itself. + * + * @param options The options struct to free. + */ +void +pm_options_free(pm_options_t *options) { + pm_options_cleanup(options); + xfree(options); +} + /** * Set the shebang callback option on the given options struct. */ @@ -17,6 +60,14 @@ pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callba options->shebang_callback_data = shebang_callback_data; } +/** + * Get the filepath option on the given options struct. + */ +pm_string_t * +pm_options_filepath_get(pm_options_t *options) { + return &options->filepath; +} + /** * Set the filepath option on the given options struct. */ @@ -141,6 +192,24 @@ pm_options_version_set(pm_options_t *options, const char *version, size_t length return false; } +/** + * Set the version option on the given options struct to the lowest version of + * Ruby that prism supports. + */ +void +pm_options_version_set_lowest(pm_options_t *options) { + options->version = PM_OPTIONS_VERSION_CRUBY_3_3; +} + +/** + * Set the version option on the given options struct to the highest version of + * Ruby that prism supports. + */ +void +pm_options_version_set_highest(pm_options_t *options) { + options->version = PM_OPTIONS_VERSION_LATEST; +} + /** * Set the main script option on the given options struct. */ @@ -157,6 +226,14 @@ pm_options_partial_script_set(pm_options_t *options, bool partial_script) { options->partial_script = partial_script; } +/** + * Get the freeze option on the given options struct. + */ +bool +pm_options_freeze_get(const pm_options_t *options) { + return options->freeze; +} + /** * Set the freeze option on the given options struct. */ @@ -184,13 +261,23 @@ pm_options_scopes_init(pm_options_t *options, size_t scopes_count) { } /** - * Return a pointer to the scope at the given index within the given options. + * Return a constant pointer to the scope at the given index within the given + * options. */ const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index) { return &options->scopes[index]; } +/** + * Return a mutable pointer to the scope at the given index within the given + * options. + */ +pm_options_scope_t * +pm_options_scope_get_mut(pm_options_t *options, size_t index) { + return &options->scopes[index]; +} + /** * Create a new options scope struct. This will hold a set of locals that are in * scope surrounding the code that is being parsed. @@ -204,7 +291,8 @@ pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) { } /** - * Return a pointer to the local at the given index within the given scope. + * Return a constant pointer to the local at the given index within the given + * scope. */ const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { @@ -212,32 +300,20 @@ pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { } /** - * Set the forwarding option on the given scope struct. + * Return a mutable pointer to the local at the given index within the given + * scope. */ -void -pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) { - scope->forwarding = forwarding; +pm_string_t * +pm_options_scope_local_get_mut(pm_options_scope_t *scope, size_t index) { + return &scope->locals[index]; } /** - * Free the internal memory associated with the options. + * Set the forwarding option on the given scope struct. */ void -pm_options_cleanup(pm_options_t *options) { - pm_string_cleanup(&options->filepath); - pm_string_cleanup(&options->encoding); - - for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { - pm_options_scope_t *scope = &options->scopes[scope_index]; - - for (size_t local_index = 0; local_index < scope->locals_count; local_index++) { - pm_string_cleanup(&scope->locals[local_index]); - } - - xfree_sized(scope->locals, scope->locals_count * sizeof(pm_string_t)); - } - - xfree_sized(options->scopes, options->scopes_count * sizeof(pm_options_scope_t)); +pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) { + scope->forwarding = forwarding; } /** From d3153258af99d8db971445a3c083f3056d365f79 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 17 Mar 2026 20:04:20 -0400 Subject: [PATCH 195/289] Give full lifetime functions to parser --- cpp/test.cpp | 9 +++-- ext/prism/extension.c | 80 ++++++++++++++++++++----------------------- include/prism.h | 58 +++++++++++++++++++++---------- include/prism/node.h | 7 ++-- src/prism.c | 25 ++++++++++++++ 5 files changed, 108 insertions(+), 71 deletions(-) diff --git a/cpp/test.cpp b/cpp/test.cpp index 19a5731de9..8ef742d957 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -6,19 +6,18 @@ extern "C" { int main() { pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, reinterpret_cast("1 + 2"), 5, NULL); + pm_parser_t *parser = pm_parser_new(&arena, reinterpret_cast("1 + 2"), 5, NULL); - pm_node_t *root = pm_parse(&parser); + pm_node_t *root = pm_parse(parser); pm_buffer_t *buffer = pm_buffer_new(); - pm_prettyprint(buffer, &parser, root); + pm_prettyprint(buffer, parser, root); std::string_view view(pm_buffer_value(buffer), pm_buffer_length(buffer)); std::cout << view << std::endl; pm_buffer_free(buffer); - pm_parser_cleanup(&parser); + pm_parser_free(parser); pm_arena_free(&arena); return 0; diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 5c4e309d42..804e3f0728 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -373,15 +373,14 @@ dump_input(pm_string_t *input, const pm_options_t *options) { } pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); - pm_serialize(&parser, node, buffer); + pm_node_t *node = pm_parse(parser); + pm_serialize(parser, node, buffer); VALUE result = rb_str_new(pm_buffer_value(buffer), pm_buffer_length(buffer)); pm_buffer_free(buffer); - pm_parser_cleanup(&parser); + pm_parser_free(parser); pm_arena_free(&arena); return result; @@ -737,13 +736,12 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) { static VALUE parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nodes) { pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); - pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback); + pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); + pm_parser_register_encoding_changed_callback(parser, parse_lex_encoding_changed_callback); VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input)); - VALUE offsets = rb_ary_new_capa(parser.line_offsets.size); - VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser.start_line), offsets); + VALUE offsets = rb_ary_new_capa(parser->line_offsets.size); + VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser->start_line), offsets); parse_lex_data_t parse_lex_data = { .source = source, @@ -758,18 +756,18 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod .callback = parse_lex_token, }; - parser.lex_callback = &lex_callback; - pm_node_t *node = pm_parse(&parser); + parser->lex_callback = &lex_callback; + pm_node_t *node = pm_parse(parser); // Here we need to update the Source object to have the correct // encoding for the source string and the correct newline offsets. // We do it here because we've already created the Source object and given // it over to all of the tokens, and both of these are only set after pm_parse(). - rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); rb_enc_associate(source_string, encoding); - for (size_t index = 0; index < parser.line_offsets.size; index++) { - rb_ary_push(offsets, ULONG2NUM(parser.line_offsets.offsets[index])); + for (size_t index = 0; index < parser->line_offsets.size; index++) { + rb_ary_push(offsets, ULONG2NUM(parser->line_offsets.offsets[index])); } if (pm_options_freeze_get(options)) { @@ -782,15 +780,15 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod VALUE result; if (return_nodes) { VALUE value = rb_ary_new_capa(2); - rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source, pm_options_freeze_get(options))); + rb_ary_push(value, pm_ast_new(parser, node, parse_lex_data.encoding, source, pm_options_freeze_get(options))); rb_ary_push(value, parse_lex_data.tokens); if (pm_options_freeze_get(options)) rb_obj_freeze(value); - result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source, pm_options_freeze_get(options)); + result = parse_result_create(rb_cPrismParseLexResult, parser, value, parse_lex_data.encoding, source, pm_options_freeze_get(options)); } else { - result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, pm_options_freeze_get(options)); + result = parse_result_create(rb_cPrismLexResult, parser, parse_lex_data.tokens, parse_lex_data.encoding, source, pm_options_freeze_get(options)); } - pm_parser_cleanup(&parser); + pm_parser_free(parser); pm_arena_free(&arena); return result; @@ -850,22 +848,21 @@ lex_file(int argc, VALUE *argv, VALUE self) { static VALUE parse_input(pm_string_t *input, const pm_options_t *options) { pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); - pm_node_t *node = pm_parse(&parser); - rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); + pm_node_t *node = pm_parse(parser); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); bool freeze = pm_options_freeze_get(options); - VALUE source = pm_source_new(&parser, encoding, freeze); - VALUE value = pm_ast_new(&parser, node, encoding, source, freeze); - VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, freeze); + VALUE source = pm_source_new(parser, encoding, freeze); + VALUE value = pm_ast_new(parser, node, encoding, source, freeze); + VALUE result = parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, freeze); if (freeze) { rb_obj_freeze(source); } - pm_parser_cleanup(&parser); + pm_parser_free(parser); pm_arena_free(&arena); return result; @@ -969,11 +966,10 @@ parse_file(int argc, VALUE *argv, VALUE self) { static void profile_input(pm_string_t *input, const pm_options_t *options) { pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); - pm_parse(&parser); - pm_parser_cleanup(&parser); + pm_parse(parser); + pm_parser_free(parser); pm_arena_free(&arena); } @@ -1094,16 +1090,15 @@ parse_stream(int argc, VALUE *argv, VALUE self) { static VALUE parse_input_comments(pm_string_t *input, const pm_options_t *options) { pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); - pm_parse(&parser); - rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); + pm_parse(parser); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); - VALUE source = pm_source_new(&parser, encoding, pm_options_freeze_get(options)); - VALUE comments = parser_comments(&parser, source, pm_options_freeze_get(options)); + VALUE source = pm_source_new(parser, encoding, pm_options_freeze_get(options)); + VALUE comments = parser_comments(parser, source, pm_options_freeze_get(options)); - pm_parser_cleanup(&parser); + pm_parser_free(parser); pm_arena_free(&arena); return comments; @@ -1217,13 +1212,12 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { static VALUE parse_input_success_p(pm_string_t *input, const pm_options_t *options) { pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); - pm_parse(&parser); + pm_parse(parser); - VALUE result = parser.error_list.size == 0 ? Qtrue : Qfalse; - pm_parser_cleanup(&parser); + VALUE result = parser->error_list.size == 0 ? Qtrue : Qfalse; + pm_parser_free(parser); pm_arena_free(&arena); return result; diff --git a/include/prism.h b/include/prism.h index 68b21122d3..631563a996 100644 --- a/include/prism.h +++ b/include/prism.h @@ -31,21 +31,34 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void); /** * Initialize a parser with the given start and end pointers. * - * The resulting parser must eventually be freed with `pm_parser_cleanup()`. The - * arena is caller-owned and must outlive the parser — `pm_parser_cleanup()` does - * not free the arena. - * - * @param arena The arena to use for all AST-lifetime allocations. + * @param arena The arena to use for all AST-lifetime allocations. It is caller- + * owned and must outlive the parser. * @param parser The parser to initialize. * @param source The source to parse. * @param size The size of the source. * @param options The optional options to use when parsing. These options must - * live for the whole lifetime of this parser. + * live for the whole lifetime of this parser. * * \public \memberof pm_parser */ PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); +/** + * Allocate and initialize a parser with the given start and end pointers. + * + * @param arena The arena to use for all AST-lifetime allocations. It is caller- + * owned and must outlive the parser. + * @param source The source to parse. + * @param size The size of the source. + * @param options The optional options to use when parsing. These options must + * live for the whole lifetime of this parser. + * @return The initialized parser. It is the responsibility of the caller to + * free the parser with `pm_parser_free()`. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options); + /** * Register a callback that will be called whenever prism changes the encoding * it is using to parse based on the magic comment. @@ -58,17 +71,26 @@ PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_arena_t *arena, pm_parser_t *pars PRISM_EXPORTED_FUNCTION void pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_changed_callback_t callback); /** - * Free any memory associated with the given parser. + * Free the memory held by the given parser. * * This does not free the `pm_options_t` object that was used to initialize the * parser. * - * @param parser The parser to free. + * @param parser The parser whose held memory should be freed. * * \public \memberof pm_parser */ PRISM_EXPORTED_FUNCTION void pm_parser_cleanup(pm_parser_t *parser); +/** + * Free both the memory held by the given parser and the parser itself. + * + * @param parser The parser to free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser); + /** * Initiate the parser with the given parser. * @@ -271,9 +293,9 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * * * `pm_arena_t` - the arena allocator for AST-lifetime memory * * `pm_parser_t` - the main parser structure - * * `pm_parser_init()` - initialize a parser + * * `pm_parser_new()` - allocate and initialize a new parser * * `pm_parse()` - parse and return the root node - * * `pm_parser_cleanup()` - free the internal memory of the parser + * * `pm_parser_free()` - free the parser and its internal memory * * `pm_arena_free()` - free all AST-lifetime memory * * Putting all of this together would look something like: @@ -281,13 +303,12 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * ```c * void parse(const uint8_t *source, size_t length) { * pm_arena_t arena = { 0 }; - * pm_parser_t parser; - * pm_parser_init(&arena, &parser, source, length, NULL); + * pm_parser_t *parser = pm_parser_new(&arena, source, length, NULL); * - * pm_node_t *root = pm_parse(&parser); + * pm_node_t *root = pm_parse(parser); * printf("PARSED!\n"); * - * pm_parser_cleanup(&parser); + * pm_parser_free(parser); * pm_arena_free(&arena); * } * ``` @@ -331,17 +352,16 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * ```c * void prettyprint(const uint8_t *source, size_t length) { * pm_arena_t arena = { 0 }; - * pm_parser_t parser; - * pm_parser_init(&arena, &parser, source, length, NULL); + * pm_parser_t *parser = pm_parser_new(&arena, source, length, NULL); * - * pm_node_t *root = pm_parse(&parser); + * pm_node_t *root = pm_parse(parser); * pm_buffer_t *buffer = pm_buffer_new(); * - * pm_prettyprint(buffer, &parser, root); + * pm_prettyprint(buffer, parser, root); * printf("%*.s\n", (int) pm_buffer_length(buffer), pm_buffer_value(buffer)); * * pm_buffer_free(buffer); - * pm_parser_cleanup(&parser); + * pm_parser_free(parser); * pm_arena_free(&arena); * } * ``` diff --git a/include/prism/node.h b/include/prism/node.h index 576919047c..ac7c337ad9 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -84,16 +84,15 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * pm_arena_t arena = { 0 }; * pm_options_t *options = pm_options_new(); * - * pm_parser_t parser; - * pm_parser_init(&arena, &parser, (const uint8_t *) source, size, options); + * pm_parser_t *parser = pm_parser_new(&arena, (const uint8_t *) source, size, options); * * size_t indent = 0; - * pm_node_t *node = pm_parse(&parser); + * pm_node_t *node = pm_parse(parser); * * size_t *data = &indent; * pm_visit_node(node, visit, data); * - * pm_parser_cleanup(&parser); + * pm_parser_free(parser); * pm_options_free(options); * pm_arena_free(&arena); * diff --git a/src/prism.c b/src/prism.c index 06cfc14b9a..9b9092f2a6 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22475,6 +22475,22 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si parser->encoding_comment_start += pm_strspn_inline_whitespace(parser->encoding_comment_start, parser->end - parser->encoding_comment_start); } +/** + * Allocate and initialize a parser with the given start and end pointers. + * + * The resulting parser must eventually be freed with `pm_parser_free()`. The + * arena is caller-owned and must outlive the parser — `pm_parser_cleanup()` + * does not free the arena. + */ +pm_parser_t * +pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options) { + pm_parser_t *parser = (pm_parser_t *) xmalloc(sizeof(pm_parser_t)); + if (parser == NULL) abort(); + + pm_parser_init(arena, parser, source, size, options); + return parser; +} + /** * Register a callback that will be called whenever prism changes the encoding * it is using to parse based on the magic comment. @@ -22505,6 +22521,15 @@ pm_parser_cleanup(pm_parser_t *parser) { } } +/** + * Free both the memory held by the given parser and the parser itself. + */ +void +pm_parser_free(pm_parser_t *parser) { + pm_parser_cleanup(parser); + xfree(parser); +} + /** * Returns true if the given diagnostic ID represents an error that cannot be * fixed by appending more input. These are errors where the existing source From 035061c5062181f33e69f5c08f48a54d042d3258 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 08:25:57 -0400 Subject: [PATCH 196/289] Update pm_parse_stream API to make parser opaque --- ext/prism/extension.c | 14 +++++++------- include/prism.h | 4 ++-- lib/prism/ffi.rb | 7 ++++++- src/prism.c | 24 +++++++++++++----------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 804e3f0728..f2ac4e7766 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -1066,18 +1066,18 @@ parse_stream(int argc, VALUE *argv, VALUE self) { extract_options(options, Qnil, keywords); pm_arena_t arena = { 0 }; - pm_parser_t parser; + pm_parser_t *parser; pm_buffer_t *buffer = pm_buffer_new(); - pm_node_t *node = pm_parse_stream(&arena, &parser, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, options); - rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(&parser)); + pm_node_t *node = pm_parse_stream(&parser, &arena, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, options); + rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); - VALUE source = pm_source_new(&parser, encoding, pm_options_freeze_get(options)); - VALUE value = pm_ast_new(&parser, node, encoding, source, pm_options_freeze_get(options)); - VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, pm_options_freeze_get(options)); + VALUE source = pm_source_new(parser, encoding, pm_options_freeze_get(options)); + VALUE value = pm_ast_new(parser, node, encoding, source, pm_options_freeze_get(options)); + VALUE result = parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, pm_options_freeze_get(options)); pm_buffer_free(buffer); - pm_parser_cleanup(&parser); + pm_parser_free(parser); pm_arena_free(&arena); pm_options_free(options); diff --git a/include/prism.h b/include/prism.h index 631563a996..768c7312a8 100644 --- a/include/prism.h +++ b/include/prism.h @@ -118,8 +118,8 @@ typedef int (pm_parse_stream_feof_t)(void *stream); /** * Parse a stream of Ruby source and return the tree. * + * @param parser The out parameter to write the parser to. * @param arena The arena to use for all AST-lifetime allocations. - * @param parser The parser to use. * @param buffer The buffer to use. * @param stream The stream to parse. * @param stream_fgets The function to use to read from the stream. @@ -129,7 +129,7 @@ typedef int (pm_parse_stream_feof_t)(void *stream); * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); // We optionally support serializing to a binary string. For systems that don't // want or need this functionality, it can be turned off with the diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 5f5c55378a..d4a9ad0302 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -99,10 +99,15 @@ def self.load_exported_functions_from(header, *functions, callbacks) "pm_serialize_lex", "pm_serialize_parse_lex", "pm_parse_success_p", + [:pm_parse_stream_fgets_t, :pm_parse_stream_feof_t] + ) + + load_exported_functions_from( + "prism/string_query.h", "pm_string_query_local", "pm_string_query_constant", "pm_string_query_method_name", - [:pm_parse_stream_fgets_t, :pm_parse_stream_feof_t] + [] ) load_exported_functions_from( diff --git a/src/prism.c b/src/prism.c index 9b9092f2a6..c0363afd9c 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22763,21 +22763,23 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t * can stream stdin in to Ruby so we need to support a streaming API. */ pm_node_t * -pm_parse_stream(pm_arena_t *arena, pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { +pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { bool eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); - pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); - pm_node_t *node = pm_parse(parser); + pm_parser_t *tmp = pm_parser_new(arena, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + pm_node_t *node = pm_parse(tmp); - while (!eof && parser->error_list.size > 0) { + while (!eof && tmp->error_list.size > 0) { eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); - pm_parser_cleanup(parser); + pm_parser_free(tmp); pm_arena_free(arena); - pm_parser_init(arena, parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); - node = pm_parse(parser); + + tmp = pm_parser_new(arena, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + node = pm_parse(tmp); } + *parser = tmp; return node; } @@ -22863,18 +22865,18 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) { pm_arena_t arena = { 0 }; - pm_parser_t parser; + pm_parser_t *parser; pm_options_t options = { 0 }; pm_options_read(&options, data); pm_buffer_t *parser_buffer = pm_buffer_new(); - pm_node_t *node = pm_parse_stream(&arena, &parser, parser_buffer, stream, stream_fgets, stream_feof, &options); + pm_node_t *node = pm_parse_stream(&parser, &arena, parser_buffer, stream, stream_fgets, stream_feof, &options); pm_serialize_header(buffer); - pm_serialize_content(&parser, node, buffer); + pm_serialize_content(parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); pm_buffer_free(parser_buffer); - pm_parser_cleanup(&parser); + pm_parser_free(parser); pm_arena_free(&arena); pm_options_cleanup(&options); } From 3da08fd638649c2f327c58d33e54f9e6db0166ad Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 09:55:47 -0400 Subject: [PATCH 197/289] Make parser an opaque pointer --- docs/encoding.md | 4 +- ext/prism/extension.c | 55 +- include/prism.h | 12 +- include/prism/internal/constant_pool.h | 2 + include/prism/internal/parser.h | 935 +++++++++++++++++++++ include/prism/parser.h | 1025 +++--------------------- src/parser.c | 135 +++- src/prism.c | 14 +- src/regexp.c | 1 + src/strpbrk.c | 1 + templates/ext/prism/api_node.c.erb | 22 +- templates/src/node.c.erb | 2 +- templates/src/prettyprint.c.erb | 2 + templates/src/serialize.c.erb | 19 +- 14 files changed, 1244 insertions(+), 985 deletions(-) create mode 100644 include/prism/internal/parser.h diff --git a/docs/encoding.md b/docs/encoding.md index a9090a9880..8f2fd18d0a 100644 --- a/docs/encoding.md +++ b/docs/encoding.md @@ -107,7 +107,7 @@ For each of these encodings, prism provides functions for checking if the subseq ## Getting notified when the encoding changes -You may want to get notified when the encoding changes based on the result of parsing an encoding comment. We use this internally for our `lex` function in order to provide the correct encodings for the tokens that are returned. For that you can register a callback with `pm_parser_register_encoding_changed_callback`. The callback will be called with a pointer to the parser. The encoding can be accessed through `parser->encoding`. +You may want to get notified when the encoding changes based on the result of parsing an encoding comment. We use this internally for our `lex` function in order to provide the correct encodings for the tokens that are returned. For that you can register a callback with `pm_parser_encoding_changed_callback_set`. The callback will be called with a pointer to the parser. The encoding can be accessed through `parser->encoding`. ```c // When the encoding that is being used to parse the source is changed by prism, @@ -117,5 +117,5 @@ typedef void (*pm_encoding_changed_callback_t)(pm_parser_t *parser); // Register a callback that will be called whenever prism changes the encoding // it is using to parse based on the magic comment. PRISM_EXPORTED_FUNCTION void -pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_changed_callback_t callback); +pm_parser_encoding_changed_callback_set(pm_parser_t *parser, pm_encoding_changed_callback_t callback); ``` diff --git a/ext/prism/extension.c b/ext/prism/extension.c index f2ac4e7766..9b03387fc9 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -490,10 +490,11 @@ parser_comment(VALUE source, bool freeze, const pm_comment_t *comment) { */ static VALUE parser_comments(const pm_parser_t *parser, VALUE source, bool freeze) { - VALUE comments = rb_ary_new_capa(parser->comment_list.size); + const pm_list_t *comments_list = pm_parser_comments(parser); + VALUE comments = rb_ary_new_capa(comments_list->size); for ( - const pm_comment_t *comment = (const pm_comment_t *) parser->comment_list.head; + const pm_comment_t *comment = (const pm_comment_t *) comments_list->head; comment != NULL; comment = (const pm_comment_t *) comment->node.next ) { @@ -521,10 +522,11 @@ parser_magic_comment(VALUE source, bool freeze, const pm_magic_comment_t *magic_ */ static VALUE parser_magic_comments(const pm_parser_t *parser, VALUE source, bool freeze) { - VALUE magic_comments = rb_ary_new_capa(parser->magic_comment_list.size); + const pm_list_t *magic_comments_list = pm_parser_magic_comments(parser); + VALUE magic_comments = rb_ary_new_capa(magic_comments_list->size); for ( - const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) parser->magic_comment_list.head; + const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) magic_comments_list->head; magic_comment != NULL; magic_comment = (const pm_magic_comment_t *) magic_comment->node.next ) { @@ -542,10 +544,12 @@ parser_magic_comments(const pm_parser_t *parser, VALUE source, bool freeze) { */ static VALUE parser_data_loc(const pm_parser_t *parser, VALUE source, bool freeze) { - if (parser->data_loc.length == 0) { + const pm_location_t *data_loc = pm_parser_data_loc(parser); + + if (data_loc->length == 0) { return Qnil; } else { - return parser_location(source, freeze, parser->data_loc.start, parser->data_loc.length); + return parser_location(source, freeze, data_loc->start, data_loc->length); } } @@ -554,10 +558,11 @@ parser_data_loc(const pm_parser_t *parser, VALUE source, bool freeze) { */ static VALUE parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) { - VALUE errors = rb_ary_new_capa(parser->error_list.size); + const pm_list_t *error_list = pm_parser_errors(parser); + VALUE errors = rb_ary_new_capa(error_list->size); for ( - const pm_diagnostic_t *error = (const pm_diagnostic_t *) parser->error_list.head; + const pm_diagnostic_t *error = (const pm_diagnostic_t *) error_list->head; error != NULL; error = (const pm_diagnostic_t *) error->node.next ) { @@ -594,10 +599,11 @@ parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bo */ static VALUE parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) { - VALUE warnings = rb_ary_new_capa(parser->warning_list.size); + const pm_list_t *warning_list = pm_parser_warnings(parser); + VALUE warnings = rb_ary_new_capa(warning_list->size); for ( - const pm_diagnostic_t *warning = (const pm_diagnostic_t *) parser->warning_list.head; + const pm_diagnostic_t *warning = (const pm_diagnostic_t *) warning_list->head; warning != NULL; warning = (const pm_diagnostic_t *) warning->node.next ) { @@ -638,7 +644,7 @@ parse_result_create(VALUE class, const pm_parser_t *parser, VALUE value, rb_enco parser_data_loc(parser, source, freeze), parser_errors(parser, encoding, source, freeze), parser_warnings(parser, encoding, source, freeze), - parser->continuable ? Qtrue : Qfalse, + pm_parser_continuable(parser) ? Qtrue : Qfalse, source }; @@ -667,11 +673,11 @@ typedef struct { * onto the tokens array. */ static void -parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) { - parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data; +parse_lex_token(pm_parser_t *parser, pm_token_t *token, void *data) { + parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) data; VALUE value = pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source, parse_lex_data->freeze); - VALUE yields = rb_assoc_new(value, INT2FIX(parser->lex_state)); + VALUE yields = rb_assoc_new(value, INT2FIX(pm_parser_lex_state(parser))); if (parse_lex_data->freeze) { rb_obj_freeze(value); @@ -688,7 +694,7 @@ parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) { */ static void parse_lex_encoding_changed_callback(pm_parser_t *parser) { - parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data; + parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) pm_parser_lex_callback_data(parser); parse_lex_data->encoding = rb_enc_find(pm_parser_encoding_name(parser)); // Since the encoding changed, we need to go back and change the encoding of @@ -737,11 +743,11 @@ static VALUE parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nodes) { pm_arena_t arena = { 0 }; pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); - pm_parser_register_encoding_changed_callback(parser, parse_lex_encoding_changed_callback); + pm_parser_encoding_changed_callback_set(parser, parse_lex_encoding_changed_callback); VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input)); - VALUE offsets = rb_ary_new_capa(parser->line_offsets.size); - VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser->start_line), offsets); + VALUE offsets = rb_ary_new_capa(pm_parser_line_offsets(parser)->size); + VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(pm_parser_start_line(parser)), offsets); parse_lex_data_t parse_lex_data = { .source = source, @@ -751,12 +757,8 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod }; parse_lex_data_t *data = &parse_lex_data; - pm_lex_callback_t lex_callback = (pm_lex_callback_t) { - .data = (void *) data, - .callback = parse_lex_token, - }; + pm_parser_lex_callback_set(parser, parse_lex_token, data); - parser->lex_callback = &lex_callback; pm_node_t *node = pm_parse(parser); // Here we need to update the Source object to have the correct @@ -766,8 +768,9 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); rb_enc_associate(source_string, encoding); - for (size_t index = 0; index < parser->line_offsets.size; index++) { - rb_ary_push(offsets, ULONG2NUM(parser->line_offsets.offsets[index])); + const pm_line_offset_list_t *line_offsets = pm_parser_line_offsets(parser); + for (size_t index = 0; index < line_offsets->size; index++) { + rb_ary_push(offsets, ULONG2NUM(line_offsets->offsets[index])); } if (pm_options_freeze_get(options)) { @@ -1216,7 +1219,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { pm_parse(parser); - VALUE result = parser->error_list.size == 0 ? Qtrue : Qfalse; + VALUE result = pm_parser_errors(parser)->size == 0 ? Qtrue : Qfalse; pm_parser_free(parser); pm_arena_free(&arena); diff --git a/include/prism.h b/include/prism.h index 768c7312a8..3a35b257d6 100644 --- a/include/prism.h +++ b/include/prism.h @@ -13,6 +13,7 @@ extern "C" { #include "prism/arena.h" #include "prism/ast.h" #include "prism/diagnostic.h" +#include "prism/encoding.h" #include "prism/excludes.h" #include "prism/node.h" #include "prism/options.h" @@ -59,17 +60,6 @@ PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_arena_t *arena, pm_parser_t *pars */ PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options); -/** - * Register a callback that will be called whenever prism changes the encoding - * it is using to parse based on the magic comment. - * - * @param parser The parser to register the callback with. - * @param callback The callback to register. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION void pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_changed_callback_t callback); - /** * Free the memory held by the given parser. * diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h index b204dfe39f..03671938a6 100644 --- a/include/prism/internal/constant_pool.h +++ b/include/prism/internal/constant_pool.h @@ -12,6 +12,8 @@ #include "prism/constant_pool.h" +#include "prism/arena.h" + /** * Initialize a list of constant ids. * diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h new file mode 100644 index 0000000000..f56dee8964 --- /dev/null +++ b/include/prism/internal/parser.h @@ -0,0 +1,935 @@ +/** + * @file internal/parser.h + * + * The parser used to parse Ruby source. + */ +#ifndef PRISM_INTERNAL_PARSER_H +#define PRISM_INTERNAL_PARSER_H + +#include "prism/compiler/accel.h" + +#include "prism/arena.h" +#include "prism/ast.h" +#include "prism/encoding.h" +#include "prism/line_offset_list.h" +#include "prism/list.h" +#include "prism/options.h" +#include "prism/parser.h" +#include "prism/static_literals.h" + +#include +#include +#include + +/** + * This enum provides various bits that represent different kinds of states that + * the lexer can track. This is used to determine which kind of token to return + * based on the context of the parser. + */ +typedef enum { + PM_LEX_STATE_BIT_BEG, + PM_LEX_STATE_BIT_END, + PM_LEX_STATE_BIT_ENDARG, + PM_LEX_STATE_BIT_ENDFN, + PM_LEX_STATE_BIT_ARG, + PM_LEX_STATE_BIT_CMDARG, + PM_LEX_STATE_BIT_MID, + PM_LEX_STATE_BIT_FNAME, + PM_LEX_STATE_BIT_DOT, + PM_LEX_STATE_BIT_CLASS, + PM_LEX_STATE_BIT_LABEL, + PM_LEX_STATE_BIT_LABELED, + PM_LEX_STATE_BIT_FITEM +} pm_lex_state_bit_t; + +/** + * This enum combines the various bits from the above enum into individual + * values that represent the various states of the lexer. + */ +typedef enum { + PM_LEX_STATE_NONE = 0, + PM_LEX_STATE_BEG = (1 << PM_LEX_STATE_BIT_BEG), + PM_LEX_STATE_END = (1 << PM_LEX_STATE_BIT_END), + PM_LEX_STATE_ENDARG = (1 << PM_LEX_STATE_BIT_ENDARG), + PM_LEX_STATE_ENDFN = (1 << PM_LEX_STATE_BIT_ENDFN), + PM_LEX_STATE_ARG = (1 << PM_LEX_STATE_BIT_ARG), + PM_LEX_STATE_CMDARG = (1 << PM_LEX_STATE_BIT_CMDARG), + PM_LEX_STATE_MID = (1 << PM_LEX_STATE_BIT_MID), + PM_LEX_STATE_FNAME = (1 << PM_LEX_STATE_BIT_FNAME), + PM_LEX_STATE_DOT = (1 << PM_LEX_STATE_BIT_DOT), + PM_LEX_STATE_CLASS = (1 << PM_LEX_STATE_BIT_CLASS), + PM_LEX_STATE_LABEL = (1 << PM_LEX_STATE_BIT_LABEL), + PM_LEX_STATE_LABELED = (1 << PM_LEX_STATE_BIT_LABELED), + PM_LEX_STATE_FITEM = (1 << PM_LEX_STATE_BIT_FITEM), + PM_LEX_STATE_BEG_ANY = PM_LEX_STATE_BEG | PM_LEX_STATE_MID | PM_LEX_STATE_CLASS, + PM_LEX_STATE_ARG_ANY = PM_LEX_STATE_ARG | PM_LEX_STATE_CMDARG, + PM_LEX_STATE_END_ANY = PM_LEX_STATE_END | PM_LEX_STATE_ENDARG | PM_LEX_STATE_ENDFN +} pm_lex_state_t; + +/** + * The type of quote that a heredoc uses. + */ +typedef enum { + PM_HEREDOC_QUOTE_NONE, + PM_HEREDOC_QUOTE_SINGLE = '\'', + PM_HEREDOC_QUOTE_DOUBLE = '"', + PM_HEREDOC_QUOTE_BACKTICK = '`', +} pm_heredoc_quote_t; + +/** + * The type of indentation that a heredoc uses. + */ +typedef enum { + PM_HEREDOC_INDENT_NONE, + PM_HEREDOC_INDENT_DASH, + PM_HEREDOC_INDENT_TILDE, +} pm_heredoc_indent_t; + +/** + * All of the information necessary to store to lexing a heredoc. + */ +typedef struct { + /** A pointer to the start of the heredoc identifier. */ + const uint8_t *ident_start; + + /** The length of the heredoc identifier. */ + size_t ident_length; + + /** The type of quote that the heredoc uses. */ + pm_heredoc_quote_t quote; + + /** The type of indentation that the heredoc uses. */ + pm_heredoc_indent_t indent; +} pm_heredoc_lex_mode_t; + +/** + * When lexing Ruby source, the lexer has a small amount of state to tell which + * kind of token it is currently lexing. For example, when we find the start of + * a string, the first token that we return is a TOKEN_STRING_BEGIN token. After + * that the lexer is now in the PM_LEX_STRING mode, and will return tokens that + * are found as part of a string. + */ +typedef struct pm_lex_mode { + /** The type of this lex mode. */ + enum { + /** This state is used when any given token is being lexed. */ + PM_LEX_DEFAULT, + + /** + * This state is used when we're lexing as normal but inside an embedded + * expression of a string. + */ + PM_LEX_EMBEXPR, + + /** + * This state is used when we're lexing a variable that is embedded + * directly inside of a string with the # shorthand. + */ + PM_LEX_EMBVAR, + + /** This state is used when you are inside the content of a heredoc. */ + PM_LEX_HEREDOC, + + /** + * This state is used when we are lexing a list of tokens, as in a %w + * word list literal or a %i symbol list literal. + */ + PM_LEX_LIST, + + /** + * This state is used when a regular expression has been begun and we + * are looking for the terminator. + */ + PM_LEX_REGEXP, + + /** + * This state is used when we are lexing a string or a string-like + * token, as in string content with either quote or an xstring. + */ + PM_LEX_STRING + } mode; + + /** The data associated with this type of lex mode. */ + union { + struct { + /** This keeps track of the nesting level of the list. */ + size_t nesting; + + /** Whether or not interpolation is allowed in this list. */ + bool interpolation; + + /** + * When lexing a list, it takes into account balancing the + * terminator if the terminator is one of (), [], {}, or <>. + */ + uint8_t incrementor; + + /** This is the terminator of the list literal. */ + uint8_t terminator; + + /** + * This is the character set that should be used to delimit the + * tokens within the list. + */ + uint8_t breakpoints[11]; + } list; + + struct { + /** + * This keeps track of the nesting level of the regular expression. + */ + size_t nesting; + + /** + * When lexing a regular expression, it takes into account balancing + * the terminator if the terminator is one of (), [], {}, or <>. + */ + uint8_t incrementor; + + /** This is the terminator of the regular expression. */ + uint8_t terminator; + + /** + * This is the character set that should be used to delimit the + * tokens within the regular expression. + */ + uint8_t breakpoints[7]; + } regexp; + + struct { + /** This keeps track of the nesting level of the string. */ + size_t nesting; + + /** Whether or not interpolation is allowed in this string. */ + bool interpolation; + + /** + * Whether or not at the end of the string we should allow a :, + * which would indicate this was a dynamic symbol instead of a + * string. + */ + bool label_allowed; + + /** + * When lexing a string, it takes into account balancing the + * terminator if the terminator is one of (), [], {}, or <>. + */ + uint8_t incrementor; + + /** + * This is the terminator of the string. It is typically either a + * single or double quote. + */ + uint8_t terminator; + + /** + * This is the character set that should be used to delimit the + * tokens within the string. + */ + uint8_t breakpoints[7]; + } string; + + struct { + /** + * All of the data necessary to lex a heredoc. + */ + pm_heredoc_lex_mode_t base; + + /** + * This is the pointer to the character where lexing should resume + * once the heredoc has been completely processed. + */ + const uint8_t *next_start; + + /** + * This is used to track the amount of common whitespace on each + * line so that we know how much to dedent each line in the case of + * a tilde heredoc. + */ + size_t *common_whitespace; + + /** True if the previous token ended with a line continuation. */ + bool line_continuation; + } heredoc; + } as; + + /** The previous lex state so that it knows how to pop. */ + struct pm_lex_mode *prev; +} pm_lex_mode_t; + +/** + * We pre-allocate a certain number of lex states in order to avoid having to + * call malloc too many times while parsing. You really shouldn't need more than + * this because you only really nest deeply when doing string interpolation. + */ +#define PM_LEX_STACK_SIZE 4 + +/** + * While parsing, we keep track of a stack of contexts. This is helpful for + * error recovery so that we can pop back to a previous context when we hit a + * token that is understood by a parent context but not by the current context. + */ +typedef enum { + /** a null context, used for returning a value from a function */ + PM_CONTEXT_NONE = 0, + + /** a begin statement */ + PM_CONTEXT_BEGIN, + + /** an ensure statement with an explicit begin */ + PM_CONTEXT_BEGIN_ENSURE, + + /** a rescue else statement with an explicit begin */ + PM_CONTEXT_BEGIN_ELSE, + + /** a rescue statement with an explicit begin */ + PM_CONTEXT_BEGIN_RESCUE, + + /** expressions in block arguments using braces */ + PM_CONTEXT_BLOCK_BRACES, + + /** expressions in block arguments using do..end */ + PM_CONTEXT_BLOCK_KEYWORDS, + + /** an ensure statement within a do..end block */ + PM_CONTEXT_BLOCK_ENSURE, + + /** a rescue else statement within a do..end block */ + PM_CONTEXT_BLOCK_ELSE, + + /** expressions in block parameters `foo do |...| end ` */ + PM_CONTEXT_BLOCK_PARAMETERS, + + /** a rescue statement within a do..end block */ + PM_CONTEXT_BLOCK_RESCUE, + + /** a case when statements */ + PM_CONTEXT_CASE_WHEN, + + /** a case in statements */ + PM_CONTEXT_CASE_IN, + + /** a class declaration */ + PM_CONTEXT_CLASS, + + /** an ensure statement within a class statement */ + PM_CONTEXT_CLASS_ENSURE, + + /** a rescue else statement within a class statement */ + PM_CONTEXT_CLASS_ELSE, + + /** a rescue statement within a class statement */ + PM_CONTEXT_CLASS_RESCUE, + + /** a method definition */ + PM_CONTEXT_DEF, + + /** an ensure statement within a method definition */ + PM_CONTEXT_DEF_ENSURE, + + /** a rescue else statement within a method definition */ + PM_CONTEXT_DEF_ELSE, + + /** a rescue statement within a method definition */ + PM_CONTEXT_DEF_RESCUE, + + /** a method definition's parameters */ + PM_CONTEXT_DEF_PARAMS, + + /** a defined? expression */ + PM_CONTEXT_DEFINED, + + /** a method definition's default parameter */ + PM_CONTEXT_DEFAULT_PARAMS, + + /** an else clause */ + PM_CONTEXT_ELSE, + + /** an elsif clause */ + PM_CONTEXT_ELSIF, + + /** an interpolated expression */ + PM_CONTEXT_EMBEXPR, + + /** a for loop */ + PM_CONTEXT_FOR, + + /** a for loop's index */ + PM_CONTEXT_FOR_INDEX, + + /** an if statement */ + PM_CONTEXT_IF, + + /** a lambda expression with braces */ + PM_CONTEXT_LAMBDA_BRACES, + + /** a lambda expression with do..end */ + PM_CONTEXT_LAMBDA_DO_END, + + /** an ensure statement within a lambda expression */ + PM_CONTEXT_LAMBDA_ENSURE, + + /** a rescue else statement within a lambda expression */ + PM_CONTEXT_LAMBDA_ELSE, + + /** a rescue statement within a lambda expression */ + PM_CONTEXT_LAMBDA_RESCUE, + + /** the predicate clause of a loop statement */ + PM_CONTEXT_LOOP_PREDICATE, + + /** the top level context */ + PM_CONTEXT_MAIN, + + /** a module declaration */ + PM_CONTEXT_MODULE, + + /** an ensure statement within a module statement */ + PM_CONTEXT_MODULE_ENSURE, + + /** a rescue else statement within a module statement */ + PM_CONTEXT_MODULE_ELSE, + + /** a rescue statement within a module statement */ + PM_CONTEXT_MODULE_RESCUE, + + /** a multiple target expression */ + PM_CONTEXT_MULTI_TARGET, + + /** a parenthesized expression */ + PM_CONTEXT_PARENS, + + /** an END block */ + PM_CONTEXT_POSTEXE, + + /** a predicate inside an if/elsif/unless statement */ + PM_CONTEXT_PREDICATE, + + /** a BEGIN block */ + PM_CONTEXT_PREEXE, + + /** a modifier rescue clause */ + PM_CONTEXT_RESCUE_MODIFIER, + + /** a singleton class definition */ + PM_CONTEXT_SCLASS, + + /** an ensure statement with a singleton class */ + PM_CONTEXT_SCLASS_ENSURE, + + /** a rescue else statement with a singleton class */ + PM_CONTEXT_SCLASS_ELSE, + + /** a rescue statement with a singleton class */ + PM_CONTEXT_SCLASS_RESCUE, + + /** a ternary expression */ + PM_CONTEXT_TERNARY, + + /** an unless statement */ + PM_CONTEXT_UNLESS, + + /** an until statement */ + PM_CONTEXT_UNTIL, + + /** a while statement */ + PM_CONTEXT_WHILE, +} pm_context_t; + +/** This is a node in a linked list of contexts. */ +typedef struct pm_context_node { + /** The context that this node represents. */ + pm_context_t context; + + /** A pointer to the previous context in the linked list. */ + struct pm_context_node *prev; +} pm_context_node_t; + +/** The type of shareable constant value that can be set. */ +typedef uint8_t pm_shareable_constant_value_t; +static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0; +static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL; +static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING; +static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY; + +/** + * This tracks an individual local variable in a certain lexical context, as + * well as the number of times is it read. + */ +typedef struct { + /** The name of the local variable. */ + pm_constant_id_t name; + + /** The location of the local variable in the source. */ + pm_location_t location; + + /** The index of the local variable in the local table. */ + uint32_t index; + + /** The number of times the local variable is read. */ + uint32_t reads; + + /** The hash of the local variable. */ + uint32_t hash; +} pm_local_t; + +/** + * This is a set of local variables in a certain lexical context (method, class, + * module, etc.). We need to track how many times these variables are read in + * order to warn if they only get written. + */ +typedef struct pm_locals { + /** The number of local variables in the set. */ + uint32_t size; + + /** The capacity of the local variables set. */ + uint32_t capacity; + + /** + * A bloom filter over constant IDs stored in this set. Used to quickly + * reject lookups for names that are definitely not present, avoiding the + * cost of a linear scan or hash probe. + */ + uint32_t bloom; + + /** The nullable allocated memory for the local variables in the set. */ + pm_local_t *locals; +} pm_locals_t; + +/** The flags about scope parameters that can be set. */ +typedef uint8_t pm_scope_parameters_t; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NONE = 0x0; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x1; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x2; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x4; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x8; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED = 0x10; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_INNER = 0x20; +static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_FOUND = 0x40; + +/** + * This struct represents a node in a linked list of scopes. Some scopes can see + * into their parent scopes, while others cannot. + */ +typedef struct pm_scope { + /** A pointer to the previous scope in the linked list. */ + struct pm_scope *previous; + + /** The IDs of the locals in the given scope. */ + pm_locals_t locals; + + /** + * This is a list of the implicit parameters contained within the block. + * These will be processed after the block is parsed to determine the kind + * of parameters node that should be used and to check if any errors need to + * be added. + */ + pm_node_list_t implicit_parameters; + + /** + * This is a bitfield that indicates the parameters that are being used in + * this scope. It is a combination of the PM_SCOPE_PARAMETERS_* constants. + * There are three different kinds of parameters that can be used in a + * scope: + * + * - Ordinary parameters (e.g., def foo(bar); end) + * - Numbered parameters (e.g., def foo; _1; end) + * - The it parameter (e.g., def foo; it; end) + * + * If ordinary parameters are being used, then certain parameters can be + * forwarded to another method/structure. Those are indicated by four + * additional bits in the params field. For example, some combinations of: + * + * - def foo(*); end + * - def foo(**); end + * - def foo(&); end + * - def foo(...); end + */ + pm_scope_parameters_t parameters; + + /** + * The current state of constant shareability for this scope. This is + * changed by magic shareable_constant_value comments. + */ + pm_shareable_constant_value_t shareable_constant; + + /** + * A boolean indicating whether or not this scope can see into its parent. + * If closed is true, then the scope cannot see into its parent. + */ + bool closed; +} pm_scope_t; + +/** + * A struct that represents a stack of boolean values. + */ +typedef uint32_t pm_state_stack_t; + +/** + * This struct represents the overall parser. It contains a reference to the + * source file, as well as pointers that indicate where in the source it's + * currently parsing. It also contains the most recent and current token that + * it's considering. + */ +struct pm_parser_t { + /** The arena used for all AST-lifetime allocations. Caller-owned. */ + pm_arena_t *arena; + + /** The arena used for parser metadata (comments, diagnostics, etc.). */ + pm_arena_t metadata_arena; + + /** + * The next node identifier that will be assigned. This is a unique + * identifier used to track nodes such that the syntax tree can be dropped + * but the node can be found through another parse. + */ + uint32_t node_id; + + /** The current state of the lexer. */ + pm_lex_state_t lex_state; + + /** Tracks the current nesting of (), [], and {}. */ + int enclosure_nesting; + + /** + * Used to temporarily track the nesting of enclosures to determine if a { + * is the beginning of a lambda following the parameters of a lambda. + */ + int lambda_enclosure_nesting; + + /** + * Used to track the nesting of braces to ensure we get the correct value + * when we are interpolating blocks with braces. + */ + int brace_nesting; + + /** + * The stack used to determine if a do keyword belongs to the predicate of a + * while, until, or for loop. + */ + pm_state_stack_t do_loop_stack; + + /** + * The stack used to determine if a do keyword belongs to the beginning of a + * block. + */ + pm_state_stack_t accepts_block_stack; + + /** A stack of lex modes. */ + struct { + /** The current mode of the lexer. */ + pm_lex_mode_t *current; + + /** The stack of lexer modes. */ + pm_lex_mode_t stack[PM_LEX_STACK_SIZE]; + + /** The current index into the lexer mode stack. */ + size_t index; + } lex_modes; + + /** The pointer to the start of the source. */ + const uint8_t *start; + + /** The pointer to the end of the source. */ + const uint8_t *end; + + /** The previous token we were considering. */ + pm_token_t previous; + + /** The current token we're considering. */ + pm_token_t current; + + /** + * This is a special field set on the parser when we need the parser to jump + * to a specific location when lexing the next token, as opposed to just + * using the end of the previous token. Normally this is NULL. + */ + const uint8_t *next_start; + + /** + * This field indicates the end of a heredoc whose identifier was found on + * the current line. If another heredoc is found on the same line, then this + * will be moved forward to the end of that heredoc. If no heredocs are + * found on a line then this is NULL. + */ + const uint8_t *heredoc_end; + + /** The list of comments that have been found while parsing. */ + pm_list_t comment_list; + + /** The list of magic comments that have been found while parsing. */ + pm_list_t magic_comment_list; + + /** + * An optional location that represents the location of the __END__ marker + * and the rest of the content of the file. This content is loaded into the + * DATA constant when the file being parsed is the main file being executed. + */ + pm_location_t data_loc; + + /** The list of warnings that have been found while parsing. */ + pm_list_t warning_list; + + /** The list of errors that have been found while parsing. */ + pm_list_t error_list; + + /** The current local scope. */ + pm_scope_t *current_scope; + + /** The current parsing context. */ + pm_context_node_t *current_context; + + /** + * The hash keys for the hash that is currently being parsed. This is not + * usually necessary because it can pass it down the various call chains, + * but in the event that you're parsing a hash that is being directly + * pushed into another hash with **, we need to share the hash keys so that + * we can warn for the nested hash as well. + */ + pm_static_literals_t *current_hash_keys; + + /** + * The encoding functions for the current file is attached to the parser as + * it's parsing so that it can change with a magic comment. + */ + const pm_encoding_t *encoding; + + /** + * When the encoding that is being used to parse the source is changed by + * prism, we provide the ability here to call out to a user-defined + * function. + */ + pm_encoding_changed_callback_t encoding_changed_callback; + + /** + * This pointer indicates where a comment must start if it is to be + * considered an encoding comment. + */ + const uint8_t *encoding_comment_start; + + /** + * When you are lexing through a file, the lexer needs all of the information + * that the parser additionally provides (for example, the local table). So if + * you want to properly lex Ruby, you need to actually lex it in the context of + * the parser. In order to provide this functionality, we optionally allow a + * struct to be attached to the parser that calls back out to a user-provided + * callback when each token is lexed. + */ + struct { + /** + * This is the callback that is called when a token is lexed. It is + * passed the opaque data pointer, the parser, and the token that was + * lexed. + */ + pm_lex_callback_t callback; + + /** + * This opaque pointer is used to provide whatever information the user + * deemed necessary to the callback. In our case we use it to pass the + * array that the tokens get appended into. + */ + void *data; + } lex_callback; + + /** + * This is the path of the file being parsed. We use the filepath when + * constructing SourceFileNodes. + */ + pm_string_t filepath; + + /** + * This constant pool keeps all of the constants defined throughout the file + * so that we can reference them later. + */ + pm_constant_pool_t constant_pool; + + /** This is the list of line offsets in the source file. */ + pm_line_offset_list_t line_offsets; + + /** + * State communicated from the lexer to the parser for integer tokens. + */ + struct { + /** + * A flag indicating the base of the integer (binary, octal, decimal, + * hexadecimal). Set during lexing and read during node creation. + */ + pm_node_flags_t base; + + /** + * When lexing a decimal integer that fits in a uint32_t, we compute + * the value during lexing to avoid re-scanning the digits during + * parsing. If lexed is true, this holds the result and + * pm_integer_parse can be skipped. + */ + uint32_t value; + + /** Whether value holds a valid pre-computed integer. */ + bool lexed; + } integer; + + /** + * This string is used to pass information from the lexer to the parser. It + * is particularly necessary because of escape sequences. + */ + pm_string_t current_string; + + /** + * The line number at the start of the parse. This will be used to offset + * the line numbers of all of the locations. + */ + int32_t start_line; + + /** + * When a string-like expression is being lexed, any byte or escape sequence + * that resolves to a value whose top bit is set (i.e., >= 0x80) will + * explicitly set the encoding to the same encoding as the source. + * Alternatively, if a unicode escape sequence is used (e.g., \\u{80}) that + * resolves to a value whose top bit is set, then the encoding will be + * explicitly set to UTF-8. + * + * The _next_ time this happens, if the encoding that is about to become the + * explicitly set encoding does not match the previously set explicit + * encoding, a mixed encoding error will be emitted. + * + * When the expression is finished being lexed, the explicit encoding + * controls the encoding of the expression. For the most part this means + * that the expression will either be encoded in the source encoding or + * UTF-8. This holds for all encodings except US-ASCII. If the source is + * US-ASCII and an explicit encoding was set that was _not_ UTF-8, then the + * expression will be encoded as ASCII-8BIT. + * + * Note that if the expression is a list, different elements within the same + * list can have different encodings, so this will get reset between each + * element. Furthermore all of this only applies to lists that support + * interpolation, because otherwise escapes that could change the encoding + * are ignored. + * + * At first glance, it may make more sense for this to live on the lexer + * mode, but we need it here to communicate back to the parser for character + * literals that do not push a new lexer mode. + */ + const pm_encoding_t *explicit_encoding; + + /** + * When parsing block exits (e.g., break, next, redo), we need to validate + * that they are in correct contexts. For the most part we can do this by + * looking at our parent contexts. However, modifier while and until + * expressions can change that context to make block exits valid. In these + * cases, we need to keep track of the block exits and then validate them + * after the expression has been parsed. + * + * We use a pointer here because we don't want to keep a whole list attached + * since this will only be used in the context of begin/end expressions. + */ + pm_node_list_t *current_block_exits; + + /** The version of prism that we should use to parse. */ + pm_options_version_t version; + + /** The command line flags given from the options. */ + uint8_t command_line; + + /** + * Whether or not we have found a frozen_string_literal magic comment with + * a true or false value. + * May be: + * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED + * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET + */ + int8_t frozen_string_literal; + + /** + * Whether or not we are parsing an eval string. This impacts whether or not + * we should evaluate if block exits/yields are valid. + */ + bool parsing_eval; + + /** + * Whether or not we are parsing a "partial" script, which is a script that + * will be evaluated in the context of another script, so we should not + * check jumps (next/break/etc.) for validity. + */ + bool partial_script; + + /** Whether or not we're at the beginning of a command. */ + bool command_start; + + /** + * Whether or not we're currently parsing the body of an endless method + * definition. In this context, PM_TOKEN_KEYWORD_DO_BLOCK should not be + * consumed by commands (it should bubble up to the outer context). + */ + bool in_endless_def_body; + + /** Whether or not we're currently recovering from a syntax error. */ + bool recovering; + + /** + * Whether or not the source being parsed could become valid if more input + * were appended. This is set to false when the parser encounters a token + * that is definitively wrong (e.g., a stray `end` or `]`) as opposed to + * merely incomplete. + */ + bool continuable; + + /** + * This is very specialized behavior for when you want to parse in a context + * that does not respect encoding comments. Its main use case is translating + * into the whitequark/parser AST which re-encodes source files in UTF-8 + * before they are parsed and ignores encoding comments. + */ + bool encoding_locked; + + /** + * Whether or not the encoding has been changed by a magic comment. We use + * this to provide a fast path for the lexer instead of going through the + * function pointer. + */ + bool encoding_changed; + + /** + * This flag indicates that we are currently parsing a pattern matching + * expression and impacts that calculation of newlines. + */ + bool pattern_matching_newlines; + + /** This flag indicates that we are currently parsing a keyword argument. */ + bool in_keyword_arg; + + /** + * Whether or not the parser has seen a token that has semantic meaning + * (i.e., a token that is not a comment or whitespace). + */ + bool semantic_token_seen; + + /** + * By default, Ruby always warns about mismatched indentation. This can be + * toggled with a magic comment. + */ + bool warn_mismatched_indentation; + +#if defined(PRISM_HAS_NEON) || defined(PRISM_HAS_SSSE3) || defined(PRISM_HAS_SWAR) + /** + * Cached lookup tables for pm_strpbrk's SIMD fast path. Avoids rebuilding + * the nibble-based tables on every call when the charset hasn't changed + * (which is the common case during string/regex/list lexing). + */ + struct { + /** The cached charset (null-terminated, max 11 chars + NUL). */ + uint8_t charset[12]; + + /** Nibble-based low lookup table for SIMD matching. */ + uint8_t low_lut[16]; + + /** Nibble-based high lookup table for SIMD matching. */ + uint8_t high_lut[16]; + + /** Scalar fallback table (4 x 64-bit bitmasks covering all ASCII). */ + uint64_t table[4]; + } strpbrk_cache; +#endif +}; + +#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index 53c9472171..047999142c 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -6,455 +6,14 @@ #ifndef PRISM_PARSER_H #define PRISM_PARSER_H -#include "prism/compiler/accel.h" - -#include "prism/arena.h" #include "prism/ast.h" -#include "prism/encoding.h" #include "prism/line_offset_list.h" #include "prism/list.h" -#include "prism/options.h" -#include "prism/static_literals.h" - -#include -#include -#include - -/** - * This enum provides various bits that represent different kinds of states that - * the lexer can track. This is used to determine which kind of token to return - * based on the context of the parser. - */ -typedef enum { - PM_LEX_STATE_BIT_BEG, - PM_LEX_STATE_BIT_END, - PM_LEX_STATE_BIT_ENDARG, - PM_LEX_STATE_BIT_ENDFN, - PM_LEX_STATE_BIT_ARG, - PM_LEX_STATE_BIT_CMDARG, - PM_LEX_STATE_BIT_MID, - PM_LEX_STATE_BIT_FNAME, - PM_LEX_STATE_BIT_DOT, - PM_LEX_STATE_BIT_CLASS, - PM_LEX_STATE_BIT_LABEL, - PM_LEX_STATE_BIT_LABELED, - PM_LEX_STATE_BIT_FITEM -} pm_lex_state_bit_t; - -/** - * This enum combines the various bits from the above enum into individual - * values that represent the various states of the lexer. - */ -typedef enum { - PM_LEX_STATE_NONE = 0, - PM_LEX_STATE_BEG = (1 << PM_LEX_STATE_BIT_BEG), - PM_LEX_STATE_END = (1 << PM_LEX_STATE_BIT_END), - PM_LEX_STATE_ENDARG = (1 << PM_LEX_STATE_BIT_ENDARG), - PM_LEX_STATE_ENDFN = (1 << PM_LEX_STATE_BIT_ENDFN), - PM_LEX_STATE_ARG = (1 << PM_LEX_STATE_BIT_ARG), - PM_LEX_STATE_CMDARG = (1 << PM_LEX_STATE_BIT_CMDARG), - PM_LEX_STATE_MID = (1 << PM_LEX_STATE_BIT_MID), - PM_LEX_STATE_FNAME = (1 << PM_LEX_STATE_BIT_FNAME), - PM_LEX_STATE_DOT = (1 << PM_LEX_STATE_BIT_DOT), - PM_LEX_STATE_CLASS = (1 << PM_LEX_STATE_BIT_CLASS), - PM_LEX_STATE_LABEL = (1 << PM_LEX_STATE_BIT_LABEL), - PM_LEX_STATE_LABELED = (1 << PM_LEX_STATE_BIT_LABELED), - PM_LEX_STATE_FITEM = (1 << PM_LEX_STATE_BIT_FITEM), - PM_LEX_STATE_BEG_ANY = PM_LEX_STATE_BEG | PM_LEX_STATE_MID | PM_LEX_STATE_CLASS, - PM_LEX_STATE_ARG_ANY = PM_LEX_STATE_ARG | PM_LEX_STATE_CMDARG, - PM_LEX_STATE_END_ANY = PM_LEX_STATE_END | PM_LEX_STATE_ENDARG | PM_LEX_STATE_ENDFN -} pm_lex_state_t; - -/** - * The type of quote that a heredoc uses. - */ -typedef enum { - PM_HEREDOC_QUOTE_NONE, - PM_HEREDOC_QUOTE_SINGLE = '\'', - PM_HEREDOC_QUOTE_DOUBLE = '"', - PM_HEREDOC_QUOTE_BACKTICK = '`', -} pm_heredoc_quote_t; - -/** - * The type of indentation that a heredoc uses. - */ -typedef enum { - PM_HEREDOC_INDENT_NONE, - PM_HEREDOC_INDENT_DASH, - PM_HEREDOC_INDENT_TILDE, -} pm_heredoc_indent_t; - -/** - * All of the information necessary to store to lexing a heredoc. - */ -typedef struct { - /** A pointer to the start of the heredoc identifier. */ - const uint8_t *ident_start; - - /** The length of the heredoc identifier. */ - size_t ident_length; - - /** The type of quote that the heredoc uses. */ - pm_heredoc_quote_t quote; - - /** The type of indentation that the heredoc uses. */ - pm_heredoc_indent_t indent; -} pm_heredoc_lex_mode_t; - -/** - * The size of the breakpoints and strpbrk cache charset buffers. All - * breakpoint arrays and the strpbrk cache charset must share this size so - * that memcmp can safely compare the full buffer without overreading. - */ -#define PM_STRPBRK_CACHE_SIZE 16 - -/** - * When lexing Ruby source, the lexer has a small amount of state to tell which - * kind of token it is currently lexing. For example, when we find the start of - * a string, the first token that we return is a TOKEN_STRING_BEGIN token. After - * that the lexer is now in the PM_LEX_STRING mode, and will return tokens that - * are found as part of a string. - */ -typedef struct pm_lex_mode { - /** The type of this lex mode. */ - enum { - /** This state is used when any given token is being lexed. */ - PM_LEX_DEFAULT, - - /** - * This state is used when we're lexing as normal but inside an embedded - * expression of a string. - */ - PM_LEX_EMBEXPR, - - /** - * This state is used when we're lexing a variable that is embedded - * directly inside of a string with the # shorthand. - */ - PM_LEX_EMBVAR, - - /** This state is used when you are inside the content of a heredoc. */ - PM_LEX_HEREDOC, - - /** - * This state is used when we are lexing a list of tokens, as in a %w - * word list literal or a %i symbol list literal. - */ - PM_LEX_LIST, - - /** - * This state is used when a regular expression has been begun and we - * are looking for the terminator. - */ - PM_LEX_REGEXP, - - /** - * This state is used when we are lexing a string or a string-like - * token, as in string content with either quote or an xstring. - */ - PM_LEX_STRING - } mode; - - /** The data associated with this type of lex mode. */ - union { - struct { - /** This keeps track of the nesting level of the list. */ - size_t nesting; - - /** Whether or not interpolation is allowed in this list. */ - bool interpolation; - - /** - * When lexing a list, it takes into account balancing the - * terminator if the terminator is one of (), [], {}, or <>. - */ - uint8_t incrementor; - - /** This is the terminator of the list literal. */ - uint8_t terminator; - - /** - * This is the character set that should be used to delimit the - * tokens within the list. - */ - uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE]; - } list; - - struct { - /** - * This keeps track of the nesting level of the regular expression. - */ - size_t nesting; - - /** - * When lexing a regular expression, it takes into account balancing - * the terminator if the terminator is one of (), [], {}, or <>. - */ - uint8_t incrementor; - - /** This is the terminator of the regular expression. */ - uint8_t terminator; - - /** - * This is the character set that should be used to delimit the - * tokens within the regular expression. - */ - uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE]; - } regexp; - - struct { - /** This keeps track of the nesting level of the string. */ - size_t nesting; - - /** Whether or not interpolation is allowed in this string. */ - bool interpolation; - - /** - * Whether or not at the end of the string we should allow a :, - * which would indicate this was a dynamic symbol instead of a - * string. - */ - bool label_allowed; - - /** - * When lexing a string, it takes into account balancing the - * terminator if the terminator is one of (), [], {}, or <>. - */ - uint8_t incrementor; - - /** - * This is the terminator of the string. It is typically either a - * single or double quote. - */ - uint8_t terminator; - - /** - * This is the character set that should be used to delimit the - * tokens within the string. - */ - uint8_t breakpoints[PM_STRPBRK_CACHE_SIZE]; - } string; - - struct { - /** - * All of the data necessary to lex a heredoc. - */ - pm_heredoc_lex_mode_t base; - - /** - * This is the pointer to the character where lexing should resume - * once the heredoc has been completely processed. - */ - const uint8_t *next_start; - - /** - * This is used to track the amount of common whitespace on each - * line so that we know how much to dedent each line in the case of - * a tilde heredoc. - */ - size_t *common_whitespace; - - /** True if the previous token ended with a line continuation. */ - bool line_continuation; - } heredoc; - } as; - - /** The previous lex state so that it knows how to pop. */ - struct pm_lex_mode *prev; -} pm_lex_mode_t; - -/** - * We pre-allocate a certain number of lex states in order to avoid having to - * call malloc too many times while parsing. You really shouldn't need more than - * this because you only really nest deeply when doing string interpolation. - */ -#define PM_LEX_STACK_SIZE 4 /** * The parser used to parse Ruby source. */ -typedef struct pm_parser pm_parser_t; - -/** - * While parsing, we keep track of a stack of contexts. This is helpful for - * error recovery so that we can pop back to a previous context when we hit a - * token that is understood by a parent context but not by the current context. - */ -typedef enum { - /** a null context, used for returning a value from a function */ - PM_CONTEXT_NONE = 0, - - /** a begin statement */ - PM_CONTEXT_BEGIN, - - /** an ensure statement with an explicit begin */ - PM_CONTEXT_BEGIN_ENSURE, - - /** a rescue else statement with an explicit begin */ - PM_CONTEXT_BEGIN_ELSE, - - /** a rescue statement with an explicit begin */ - PM_CONTEXT_BEGIN_RESCUE, - - /** expressions in block arguments using braces */ - PM_CONTEXT_BLOCK_BRACES, - - /** expressions in block arguments using do..end */ - PM_CONTEXT_BLOCK_KEYWORDS, - - /** an ensure statement within a do..end block */ - PM_CONTEXT_BLOCK_ENSURE, - - /** a rescue else statement within a do..end block */ - PM_CONTEXT_BLOCK_ELSE, - - /** expressions in block parameters `foo do |...| end ` */ - PM_CONTEXT_BLOCK_PARAMETERS, - - /** a rescue statement within a do..end block */ - PM_CONTEXT_BLOCK_RESCUE, - - /** a case when statements */ - PM_CONTEXT_CASE_WHEN, - - /** a case in statements */ - PM_CONTEXT_CASE_IN, - - /** a class declaration */ - PM_CONTEXT_CLASS, - - /** an ensure statement within a class statement */ - PM_CONTEXT_CLASS_ENSURE, - - /** a rescue else statement within a class statement */ - PM_CONTEXT_CLASS_ELSE, - - /** a rescue statement within a class statement */ - PM_CONTEXT_CLASS_RESCUE, - - /** a method definition */ - PM_CONTEXT_DEF, - - /** an ensure statement within a method definition */ - PM_CONTEXT_DEF_ENSURE, - - /** a rescue else statement within a method definition */ - PM_CONTEXT_DEF_ELSE, - - /** a rescue statement within a method definition */ - PM_CONTEXT_DEF_RESCUE, - - /** a method definition's parameters */ - PM_CONTEXT_DEF_PARAMS, - - /** a defined? expression */ - PM_CONTEXT_DEFINED, - - /** a method definition's default parameter */ - PM_CONTEXT_DEFAULT_PARAMS, - - /** an else clause */ - PM_CONTEXT_ELSE, - - /** an elsif clause */ - PM_CONTEXT_ELSIF, - - /** an interpolated expression */ - PM_CONTEXT_EMBEXPR, - - /** a for loop */ - PM_CONTEXT_FOR, - - /** a for loop's index */ - PM_CONTEXT_FOR_INDEX, - - /** an if statement */ - PM_CONTEXT_IF, - - /** a lambda expression with braces */ - PM_CONTEXT_LAMBDA_BRACES, - - /** a lambda expression with do..end */ - PM_CONTEXT_LAMBDA_DO_END, - - /** an ensure statement within a lambda expression */ - PM_CONTEXT_LAMBDA_ENSURE, - - /** a rescue else statement within a lambda expression */ - PM_CONTEXT_LAMBDA_ELSE, - - /** a rescue statement within a lambda expression */ - PM_CONTEXT_LAMBDA_RESCUE, - - /** the predicate clause of a loop statement */ - PM_CONTEXT_LOOP_PREDICATE, - - /** the top level context */ - PM_CONTEXT_MAIN, - - /** a module declaration */ - PM_CONTEXT_MODULE, - - /** an ensure statement within a module statement */ - PM_CONTEXT_MODULE_ENSURE, - - /** a rescue else statement within a module statement */ - PM_CONTEXT_MODULE_ELSE, - - /** a rescue statement within a module statement */ - PM_CONTEXT_MODULE_RESCUE, - - /** a multiple target expression */ - PM_CONTEXT_MULTI_TARGET, - - /** a parenthesized expression */ - PM_CONTEXT_PARENS, - - /** an END block */ - PM_CONTEXT_POSTEXE, - - /** a predicate inside an if/elsif/unless statement */ - PM_CONTEXT_PREDICATE, - - /** a BEGIN block */ - PM_CONTEXT_PREEXE, - - /** a modifier rescue clause */ - PM_CONTEXT_RESCUE_MODIFIER, - - /** a singleton class definition */ - PM_CONTEXT_SCLASS, - - /** an ensure statement with a singleton class */ - PM_CONTEXT_SCLASS_ENSURE, - - /** a rescue else statement with a singleton class */ - PM_CONTEXT_SCLASS_ELSE, - - /** a rescue statement with a singleton class */ - PM_CONTEXT_SCLASS_RESCUE, - - /** a ternary expression */ - PM_CONTEXT_TERNARY, - - /** an unless statement */ - PM_CONTEXT_UNLESS, - - /** an until statement */ - PM_CONTEXT_UNTIL, - - /** a while statement */ - PM_CONTEXT_WHILE, -} pm_context_t; - -/** This is a node in a linked list of contexts. */ -typedef struct pm_context_node { - /** The context that this node represents. */ - pm_context_t context; - - /** A pointer to the previous context in the linked list. */ - struct pm_context_node *prev; -} pm_context_node_t; +typedef struct pm_parser_t pm_parser_t; /** This is the type of a comment that we've found while parsing. */ typedef enum { @@ -502,503 +61,149 @@ typedef struct { typedef void (*pm_encoding_changed_callback_t)(pm_parser_t *parser); /** - * When you are lexing through a file, the lexer needs all of the information - * that the parser additionally provides (for example, the local table). So if - * you want to properly lex Ruby, you need to actually lex it in the context of - * the parser. In order to provide this functionality, we optionally allow a - * struct to be attached to the parser that calls back out to a user-provided - * callback when each token is lexed. + * This is the callback that is called when a token is lexed. It is passed + * the opaque data pointer, the parser, and the token that was lexed. */ -typedef struct { - /** - * This opaque pointer is used to provide whatever information the user - * deemed necessary to the callback. In our case we use it to pass the array - * that the tokens get appended into. - */ - void *data; - - /** - * This is the callback that is called when a token is lexed. It is passed - * the opaque data pointer, the parser, and the token that was lexed. - */ - void (*callback)(void *data, pm_parser_t *parser, pm_token_t *token); -} pm_lex_callback_t; - -/** The type of shareable constant value that can be set. */ -typedef uint8_t pm_shareable_constant_value_t; -static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0; -static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL; -static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING; -static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY; +typedef void (*pm_lex_callback_t)(pm_parser_t *parser, pm_token_t *token, void *data); /** - * This tracks an individual local variable in a certain lexical context, as - * well as the number of times is it read. + * Register a callback that will be called whenever prism changes the encoding + * it is using to parse based on the magic comment. + * + * @param parser The parser to register the callback with. + * @param callback The callback to register. + * + * \public \memberof pm_parser */ -typedef struct { - /** The name of the local variable. */ - pm_constant_id_t name; - - /** The location of the local variable in the source. */ - pm_location_t location; - - /** The index of the local variable in the local table. */ - uint32_t index; - - /** The number of times the local variable is read. */ - uint32_t reads; - - /** The hash of the local variable. */ - uint32_t hash; -} pm_local_t; +PRISM_EXPORTED_FUNCTION void pm_parser_encoding_changed_callback_set(pm_parser_t *parser, pm_encoding_changed_callback_t callback); /** - * This is a set of local variables in a certain lexical context (method, class, - * module, etc.). We need to track how many times these variables are read in - * order to warn if they only get written. + * Register a callback that will be called whenever a token is lexed. + * + * @param parser The parser to register the callback with. + * @param data The opaque data to pass to the callback when it is called. + * @param callback The callback to register. + * + * \public \memberof pm_parser */ -typedef struct pm_locals { - /** The number of local variables in the set. */ - uint32_t size; - - /** The capacity of the local variables set. */ - uint32_t capacity; - - /** - * A bloom filter over constant IDs stored in this set. Used to quickly - * reject lookups for names that are definitely not present, avoiding the - * cost of a linear scan or hash probe. - */ - uint32_t bloom; - - /** The nullable allocated memory for the local variables in the set. */ - pm_local_t *locals; -} pm_locals_t; - -/** The flags about scope parameters that can be set. */ -typedef uint8_t pm_scope_parameters_t; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NONE = 0x0; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x1; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x2; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x4; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x8; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED = 0x10; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_INNER = 0x20; -static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_FOUND = 0x40; +PRISM_EXPORTED_FUNCTION void pm_parser_lex_callback_set(pm_parser_t *parser, pm_lex_callback_t callback, void *data); /** - * This struct represents a node in a linked list of scopes. Some scopes can see - * into their parent scopes, while others cannot. + * Returns the opaque data that is passed to the lex callback when it is called. + * + * @param parser The parser whose lex callback data we want to get. + * @return The opaque data that is passed to the lex callback when it is called. */ -typedef struct pm_scope { - /** A pointer to the previous scope in the linked list. */ - struct pm_scope *previous; - - /** The IDs of the locals in the given scope. */ - pm_locals_t locals; - - /** - * This is a list of the implicit parameters contained within the block. - * These will be processed after the block is parsed to determine the kind - * of parameters node that should be used and to check if any errors need to - * be added. - */ - pm_node_list_t implicit_parameters; - - /** - * This is a bitfield that indicates the parameters that are being used in - * this scope. It is a combination of the PM_SCOPE_PARAMETERS_* constants. - * There are three different kinds of parameters that can be used in a - * scope: - * - * - Ordinary parameters (e.g., def foo(bar); end) - * - Numbered parameters (e.g., def foo; _1; end) - * - The it parameter (e.g., def foo; it; end) - * - * If ordinary parameters are being used, then certain parameters can be - * forwarded to another method/structure. Those are indicated by four - * additional bits in the params field. For example, some combinations of: - * - * - def foo(*); end - * - def foo(**); end - * - def foo(&); end - * - def foo(...); end - */ - pm_scope_parameters_t parameters; - - /** - * The current state of constant shareability for this scope. This is - * changed by magic shareable_constant_value comments. - */ - pm_shareable_constant_value_t shareable_constant; - - /** - * A boolean indicating whether or not this scope can see into its parent. - * If closed is true, then the scope cannot see into its parent. - */ - bool closed; -} pm_scope_t; +PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(pm_parser_t *parser); /** - * A struct that represents a stack of boolean values. + * Returns the raw pointer to the start of the source that is being parsed. + * + * @param parser the parser whose start pointer we want to get + * @return the raw pointer to the start of the source that is being parsed */ -typedef uint32_t pm_state_stack_t; +PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_start(const pm_parser_t *parser); /** - * This struct represents the overall parser. It contains a reference to the - * source file, as well as pointers that indicate where in the source it's - * currently parsing. It also contains the most recent and current token that - * it's considering. + * Returns the raw pointer to the end of the source that is being parsed. + * + * @param parser the parser whose end pointer we want to get + * @return the raw pointer to the end of the source that is being parsed */ -struct pm_parser { - /** The arena used for all AST-lifetime allocations. Caller-owned. */ - pm_arena_t *arena; - - /** The arena used for parser metadata (comments, diagnostics, etc.). */ - pm_arena_t metadata_arena; - - /** - * The next node identifier that will be assigned. This is a unique - * identifier used to track nodes such that the syntax tree can be dropped - * but the node can be found through another parse. - */ - uint32_t node_id; - - /** The current state of the lexer. */ - pm_lex_state_t lex_state; - - /** Tracks the current nesting of (), [], and {}. */ - int enclosure_nesting; - - /** - * Used to temporarily track the nesting of enclosures to determine if a { - * is the beginning of a lambda following the parameters of a lambda. - */ - int lambda_enclosure_nesting; - - /** - * Used to track the nesting of braces to ensure we get the correct value - * when we are interpolating blocks with braces. - */ - int brace_nesting; - - /** - * The stack used to determine if a do keyword belongs to the predicate of a - * while, until, or for loop. - */ - pm_state_stack_t do_loop_stack; - - /** - * The stack used to determine if a do keyword belongs to the beginning of a - * block. - */ - pm_state_stack_t accepts_block_stack; - - /** A stack of lex modes. */ - struct { - /** The current mode of the lexer. */ - pm_lex_mode_t *current; - - /** The stack of lexer modes. */ - pm_lex_mode_t stack[PM_LEX_STACK_SIZE]; - - /** The current index into the lexer mode stack. */ - size_t index; - } lex_modes; - - /** The pointer to the start of the source. */ - const uint8_t *start; - - /** The pointer to the end of the source. */ - const uint8_t *end; - - /** The previous token we were considering. */ - pm_token_t previous; - - /** The current token we're considering. */ - pm_token_t current; - - /** - * This is a special field set on the parser when we need the parser to jump - * to a specific location when lexing the next token, as opposed to just - * using the end of the previous token. Normally this is NULL. - */ - const uint8_t *next_start; - - /** - * This field indicates the end of a heredoc whose identifier was found on - * the current line. If another heredoc is found on the same line, then this - * will be moved forward to the end of that heredoc. If no heredocs are - * found on a line then this is NULL. - */ - const uint8_t *heredoc_end; - - /** The list of comments that have been found while parsing. */ - pm_list_t comment_list; - - /** The list of magic comments that have been found while parsing. */ - pm_list_t magic_comment_list; - - /** - * An optional location that represents the location of the __END__ marker - * and the rest of the content of the file. This content is loaded into the - * DATA constant when the file being parsed is the main file being executed. - */ - pm_location_t data_loc; - - /** The list of warnings that have been found while parsing. */ - pm_list_t warning_list; - - /** The list of errors that have been found while parsing. */ - pm_list_t error_list; - - /** The current local scope. */ - pm_scope_t *current_scope; - - /** The current parsing context. */ - pm_context_node_t *current_context; - - /** - * The hash keys for the hash that is currently being parsed. This is not - * usually necessary because it can pass it down the various call chains, - * but in the event that you're parsing a hash that is being directly - * pushed into another hash with **, we need to share the hash keys so that - * we can warn for the nested hash as well. - */ - pm_static_literals_t *current_hash_keys; - - /** - * The encoding functions for the current file is attached to the parser as - * it's parsing so that it can change with a magic comment. - */ - const pm_encoding_t *encoding; - - /** - * When the encoding that is being used to parse the source is changed by - * prism, we provide the ability here to call out to a user-defined - * function. - */ - pm_encoding_changed_callback_t encoding_changed_callback; - - /** - * This pointer indicates where a comment must start if it is to be - * considered an encoding comment. - */ - const uint8_t *encoding_comment_start; - - /** - * This is an optional callback that can be attached to the parser that will - * be called whenever a new token is lexed by the parser. - */ - pm_lex_callback_t *lex_callback; +PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_end(const pm_parser_t *parser); - /** - * This is the path of the file being parsed. We use the filepath when - * constructing SourceFileNodes. - */ - pm_string_t filepath; - - /** - * This constant pool keeps all of the constants defined throughout the file - * so that we can reference them later. - */ - pm_constant_pool_t constant_pool; - - /** This is the list of line offsets in the source file. */ - pm_line_offset_list_t line_offsets; - - /** - * State communicated from the lexer to the parser for integer tokens. - */ - struct { - /** - * A flag indicating the base of the integer (binary, octal, decimal, - * hexadecimal). Set during lexing and read during node creation. - */ - pm_node_flags_t base; - - /** - * When lexing a decimal integer that fits in a uint32_t, we compute - * the value during lexing to avoid re-scanning the digits during - * parsing. If lexed is true, this holds the result and - * pm_integer_parse can be skipped. - */ - uint32_t value; - - /** Whether value holds a valid pre-computed integer. */ - bool lexed; - } integer; - - /** - * This string is used to pass information from the lexer to the parser. It - * is particularly necessary because of escape sequences. - */ - pm_string_t current_string; - - /** - * The line number at the start of the parse. This will be used to offset - * the line numbers of all of the locations. - */ - int32_t start_line; - - /** - * When a string-like expression is being lexed, any byte or escape sequence - * that resolves to a value whose top bit is set (i.e., >= 0x80) will - * explicitly set the encoding to the same encoding as the source. - * Alternatively, if a unicode escape sequence is used (e.g., \\u{80}) that - * resolves to a value whose top bit is set, then the encoding will be - * explicitly set to UTF-8. - * - * The _next_ time this happens, if the encoding that is about to become the - * explicitly set encoding does not match the previously set explicit - * encoding, a mixed encoding error will be emitted. - * - * When the expression is finished being lexed, the explicit encoding - * controls the encoding of the expression. For the most part this means - * that the expression will either be encoded in the source encoding or - * UTF-8. This holds for all encodings except US-ASCII. If the source is - * US-ASCII and an explicit encoding was set that was _not_ UTF-8, then the - * expression will be encoded as ASCII-8BIT. - * - * Note that if the expression is a list, different elements within the same - * list can have different encodings, so this will get reset between each - * element. Furthermore all of this only applies to lists that support - * interpolation, because otherwise escapes that could change the encoding - * are ignored. - * - * At first glance, it may make more sense for this to live on the lexer - * mode, but we need it here to communicate back to the parser for character - * literals that do not push a new lexer mode. - */ - const pm_encoding_t *explicit_encoding; - - /** - * When parsing block exits (e.g., break, next, redo), we need to validate - * that they are in correct contexts. For the most part we can do this by - * looking at our parent contexts. However, modifier while and until - * expressions can change that context to make block exits valid. In these - * cases, we need to keep track of the block exits and then validate them - * after the expression has been parsed. - * - * We use a pointer here because we don't want to keep a whole list attached - * since this will only be used in the context of begin/end expressions. - */ - pm_node_list_t *current_block_exits; - - /** The version of prism that we should use to parse. */ - pm_options_version_t version; - - /** The command line flags given from the options. */ - uint8_t command_line; - - /** - * Whether or not we have found a frozen_string_literal magic comment with - * a true or false value. - * May be: - * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED - * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED - * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET - */ - int8_t frozen_string_literal; - - /** - * Whether or not we are parsing an eval string. This impacts whether or not - * we should evaluate if block exits/yields are valid. - */ - bool parsing_eval; - - /** - * Whether or not we are parsing a "partial" script, which is a script that - * will be evaluated in the context of another script, so we should not - * check jumps (next/break/etc.) for validity. - */ - bool partial_script; - - /** Whether or not we're at the beginning of a command. */ - bool command_start; - - /** - * Whether or not we're currently parsing the body of an endless method - * definition. In this context, PM_TOKEN_KEYWORD_DO_BLOCK should not be - * consumed by commands (it should bubble up to the outer context). - */ - bool in_endless_def_body; - - /** Whether or not we're currently recovering from a syntax error. */ - bool recovering; - - /** - * Whether or not the source being parsed could become valid if more input - * were appended. This is set to false when the parser encounters a token - * that is definitively wrong (e.g., a stray `end` or `]`) as opposed to - * merely incomplete. - */ - bool continuable; - - /** - * This is very specialized behavior for when you want to parse in a context - * that does not respect encoding comments. Its main use case is translating - * into the whitequark/parser AST which re-encodes source files in UTF-8 - * before they are parsed and ignores encoding comments. - */ - bool encoding_locked; +/** + * Returns the line that the parser was considered to have started on. + * + * @param parser the parser whose start line we want to get + * @return the line that the parser was considered to have started on + */ +PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser); - /** - * Whether or not the encoding has been changed by a magic comment. We use - * this to provide a fast path for the lexer instead of going through the - * function pointer. - */ - bool encoding_changed; +/** + * Returns the name of the encoding that is being used to parse the source. + * + * @param parser the parser whose encoding name we want to get + * @return the name of the encoding that is being used to parse the source + */ +PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser); - /** - * This flag indicates that we are currently parsing a pattern matching - * expression and impacts that calculation of newlines. - */ - bool pattern_matching_newlines; +/** + * Returns the errors that are associated with the given parser. + * + * @param parser the parser whose errors we want to get + * @return the errors that are associated with the given parser + */ +PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_errors(const pm_parser_t *parser); - /** This flag indicates that we are currently parsing a keyword argument. */ - bool in_keyword_arg; +/** + * Returns the warnings that are associated with the given parser. + * + * @param parser the parser whose warnings we want to get + * @return the warnings that are associated with the given parser + */ +PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_warnings(const pm_parser_t *parser); - /** - * Whether or not the parser has seen a token that has semantic meaning - * (i.e., a token that is not a comment or whitespace). - */ - bool semantic_token_seen; +/** + * Returns the comments that are associated with the given parser. + * + * @param parser the parser whose comments we want to get + * @return the comments that are associated with the given parser + */ +PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_comments(const pm_parser_t *parser); - /** - * By default, Ruby always warns about mismatched indentation. This can be - * toggled with a magic comment. - */ - bool warn_mismatched_indentation; +/** + * Returns the magic comments that are associated with the given parser. + * + * @param parser the parser whose magic comments we want to get + * @return the magic comments that are associated with the given parser + */ +PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_magic_comments(const pm_parser_t *parser); -#if defined(PRISM_HAS_NEON) || defined(PRISM_HAS_SSSE3) || defined(PRISM_HAS_SWAR) - /** - * Cached lookup tables for pm_strpbrk's SIMD fast path. Avoids rebuilding - * the nibble-based tables on every call when the charset hasn't changed - * (which is the common case during string/regex/list lexing). - */ - struct { - /** The cached charset (null-terminated, NUL-padded). */ - uint8_t charset[PM_STRPBRK_CACHE_SIZE]; +/** + * Returns the line offsets that are associated with the given parser. + * + * @param parser the parser whose line offsets we want to get + * @return the line offsets that are associated with the given parser + */ +PRISM_EXPORTED_FUNCTION const pm_line_offset_list_t * pm_parser_line_offsets(const pm_parser_t *parser); - /** Nibble-based low lookup table for SIMD matching. */ - uint8_t low_lut[16]; +/** + * Returns the constant pool associated with the given parser. + * + * @param parser the parser whose constant pool we want to get + * @return the constant pool associated with the given parser + */ +PRISM_EXPORTED_FUNCTION const pm_constant_pool_t * pm_parser_constant_pool(const pm_parser_t *parser); - /** Nibble-based high lookup table for SIMD matching. */ - uint8_t high_lut[16]; +/** + * Returns the location of the __DATA__ section that is associated with the + * given parser. + * + * @param parser the parser whose data location we want to get + * @return the location of the __DATA__ section that is associated with the + * given parser. If it is unset, then the length will be set to 0. + */ +PRISM_EXPORTED_FUNCTION const pm_location_t * pm_parser_data_loc(const pm_parser_t *parser); - /** Scalar fallback table (4 x 64-bit bitmasks covering all ASCII). */ - uint64_t table[4]; - } strpbrk_cache; -#endif -}; +/** + * Returns whether the given parser is continuable, meaning that it could become + * valid if more input were appended, as opposed to being definitively invalid. + * + * @param parser the parser whose continuable status we want to get + * @return whether the given parser is continuable + */ +PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser); /** - * Returns the name of the encoding that is being used to parse the source. + * Returns the lex state of the parser. Note that this is an internal detail, + * and we are purposefully not returning an instance of the internal enum that + * we use to track this. This is only exposed because we need it for some very + * niche use cases. Most consumers should avoid this function. * - * @param parser the parser whose encoding name we want to get - * @return the name of the encoding that is being used to parse the source + * @param parser the parser whose lex state we want to get + * @return the lex state of the parser */ -PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); #endif diff --git a/src/parser.c b/src/parser.c index 356700796f..209f748ff2 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,7 +1,60 @@ -#include "prism/parser.h" +#include "prism/internal/parser.h" #include "prism/internal/encoding.h" +/** + * Register a callback that will be called whenever prism changes the encoding + * it is using to parse based on the magic comment. + */ +void +pm_parser_encoding_changed_callback_set(pm_parser_t *parser, pm_encoding_changed_callback_t callback) { + parser->encoding_changed_callback = callback; +} + +/** + * Register a callback that will be called whenever a token is lexed. + */ +void +pm_parser_lex_callback_set(pm_parser_t *parser, pm_lex_callback_t callback, void *data) { + parser->lex_callback.callback = callback; + parser->lex_callback.data = data; +} + +/** + * Returns the opaque data that is passed to the lex callback when it is called. + */ +void * +pm_parser_lex_callback_data(pm_parser_t *parser) { + return parser->lex_callback.data; +} + +/** + * Returns the raw pointer to the start of the source that is being parsed. + */ +const uint8_t * +pm_parser_start(const pm_parser_t *parser) { + return parser->start; +} + +/** + * Returns the raw pointer to the end of the source that is being parsed. + */ +const uint8_t * +pm_parser_end(const pm_parser_t *parser) { + return parser->end; +} + +/** + * Returns the line that the parser was considered to have started on. + * + * @param parser the parser whose start line we want to get + * @return the line that the parser was considered to have started on + */ +int32_t +pm_parser_start_line(const pm_parser_t *parser) { + return parser->start_line; +} + /** * Returns the name of the encoding that is being used to parse the source. */ @@ -9,3 +62,83 @@ const char * pm_parser_encoding_name(const pm_parser_t *parser) { return parser->encoding->name; } + +/** + * Returns the errors that are associated with the given parser. + */ +const pm_list_t * +pm_parser_errors(const pm_parser_t *parser) { + return &parser->error_list; +} + +/** + * Returns the warnings that are associated with the given parser. + */ +const pm_list_t * +pm_parser_warnings(const pm_parser_t *parser) { + return &parser->warning_list; +} + +/** + * Returns the comments that are associated with the given parser. + */ +const pm_list_t * +pm_parser_comments(const pm_parser_t *parser) { + return &parser->comment_list; +} + +/** + * Returns the magic comments that are associated with the given parser. + */ +const pm_list_t * +pm_parser_magic_comments(const pm_parser_t *parser) { + return &parser->magic_comment_list; +} + +/** + * Returns the line offsets that are associated with the given parser. + * + * @param parser the parser whose line offsets we want to get + * @return the line offsets that are associated with the given parser + */ +const pm_line_offset_list_t * +pm_parser_line_offsets(const pm_parser_t *parser) { + return &parser->line_offsets; +} + +/** + * Returns the constant pool associated with the given parser. + */ +const pm_constant_pool_t * +pm_parser_constant_pool(const pm_parser_t *parser) { + return &parser->constant_pool; +} + +/** + * Returns the location of the __DATA__ section that is associated with the + * given parser, if it exists. + */ +const pm_location_t * +pm_parser_data_loc(const pm_parser_t *parser) { + return &parser->data_loc; +} + +/** + * Returns whether the given parser is continuable, meaning that it could become + * valid if more input were appended, as opposed to being definitively invalid. + */ +bool +pm_parser_continuable(const pm_parser_t *parser) { + return parser->continuable; +} + +/** + * Returns the lex state of the parser. Note that this is an internal detail, + * and we are purposefully not returning an instance of the internal enum that + * we use to track this. This is only exposed because we need it for some very + * niche use cases. Most consumers should avoid this function. + */ +int +pm_parser_lex_state(const pm_parser_t *parser) { + return (int) parser->lex_state; +} diff --git a/src/prism.c b/src/prism.c index c0363afd9c..5814fa4fee 100644 --- a/src/prism.c +++ b/src/prism.c @@ -19,6 +19,7 @@ #include "prism/internal/memchr.h" #include "prism/internal/node.h" #include "prism/internal/options.h" +#include "prism/internal/parser.h" #include "prism/internal/regexp.h" #include "prism/internal/static_literals.h" #include "prism/internal/strings.h" @@ -9519,8 +9520,8 @@ lex_at_variable(pm_parser_t *parser) { */ static PRISM_INLINE void parser_lex_callback(pm_parser_t *parser) { - if (parser->lex_callback) { - parser->lex_callback->callback(parser->lex_callback->data, parser, &parser->current); + if (parser->lex_callback.callback) { + parser->lex_callback.callback(parser, &parser->current, parser->lex_callback.data); } } @@ -22491,15 +22492,6 @@ pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_op return parser; } -/** - * Register a callback that will be called whenever prism changes the encoding - * it is using to parse based on the magic comment. - */ -void -pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_changed_callback_t callback) { - parser->encoding_changed_callback = callback; -} - /** * Free any memory associated with the given parser. */ diff --git a/src/regexp.c b/src/regexp.c index 2ee2555686..05ef3b6b41 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -7,6 +7,7 @@ #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" #include "prism/internal/memchr.h" +#include "prism/internal/parser.h" #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" diff --git a/src/strpbrk.c b/src/strpbrk.c index 6db4fd31bf..41ab8eec3e 100644 --- a/src/strpbrk.c +++ b/src/strpbrk.c @@ -7,6 +7,7 @@ #include "prism/internal/bit.h" #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" +#include "prism/internal/parser.h" #include #include diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index be6bd113ad..fffb2bebb5 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -26,7 +26,7 @@ pm_location_new(const uint32_t start, const uint32_t length, VALUE source, bool VALUE pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source, bool freeze) { ID type = rb_intern(pm_token_type_name(token->type)); - VALUE location = pm_location_new((uint32_t) (token->start - parser->start), (uint32_t) (token->end - token->start), source, freeze); + VALUE location = pm_location_new((uint32_t) (token->start - pm_parser_start(parser)), (uint32_t) (token->end - token->start), source, freeze); VALUE slice = rb_enc_str_new((const char *) token->start, token->end - token->start, encoding); if (freeze) rb_obj_freeze(slice); @@ -75,11 +75,14 @@ pm_integer_new(const pm_integer_t *integer) { // Create a Prism::Source object from the given parser, after pm_parse() was called. VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) { - VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding); + const uint8_t *start = pm_parser_start(parser); + VALUE source_string = rb_enc_str_new((const char *) start, pm_parser_end(parser) - start, encoding); - VALUE offsets = rb_ary_new_capa(parser->line_offsets.size); - for (size_t index = 0; index < parser->line_offsets.size; index++) { - rb_ary_push(offsets, ULONG2NUM(parser->line_offsets.offsets[index])); + const pm_line_offset_list_t *line_offsets = pm_parser_line_offsets(parser); + VALUE offsets = rb_ary_new_capa(line_offsets->size); + + for (size_t index = 0; index < line_offsets->size; index++) { + rb_ary_push(offsets, ULONG2NUM(line_offsets->offsets[index])); } if (freeze) { @@ -87,7 +90,7 @@ pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) { rb_obj_freeze(offsets); } - VALUE source = rb_funcall(rb_cPrismSource, rb_intern("for"), 3, source_string, LONG2NUM(parser->start_line), offsets); + VALUE source = rb_funcall(rb_cPrismSource, rb_intern("for"), 3, source_string, LONG2NUM(pm_parser_start_line(parser)), offsets); if (freeze) rb_obj_freeze(source); return source; @@ -121,10 +124,11 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) { VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) { - VALUE constants = rb_ary_new_capa(parser->constant_pool.size); + const pm_constant_pool_t *constant_pool = pm_parser_constant_pool(parser); + VALUE constants = rb_ary_new_capa(constant_pool->size); - for (uint32_t index = 0; index < parser->constant_pool.size; index++) { - pm_constant_t *constant = &parser->constant_pool.constants[index]; + for (uint32_t index = 0; index < constant_pool->size; index++) { + pm_constant_t *constant = &constant_pool->constants[index]; int state = 0; VALUE string = rb_enc_str_new((const char *) constant->start, constant->length, encoding); diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index c0016647a8..da249141ed 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -4,7 +4,7 @@ #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" -#include "prism/parser.h" +#include "prism/internal/parser.h" #include #include diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 4af8155c47..ffe9b1f307 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -5,6 +5,8 @@ #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" +#include "prism/internal/parser.h" +#include "prism/line_offset_list.h" #include diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index b305a95d7e..cfd073b7e6 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -11,11 +11,12 @@ #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" +#include "prism/internal/parser.h" #include "prism.h" #include "prism/ast.h" #include "prism/diagnostic.h" -#include "prism/parser.h" +#include "prism/line_offset_list.h" #include #include @@ -312,7 +313,7 @@ pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) } static void -serialize_token(void *data, pm_parser_t *parser, pm_token_t *token) { +serialize_token(pm_parser_t *parser, pm_token_t *token, void *data) { pm_buffer_t *buffer = (pm_buffer_t *) data; pm_buffer_append_varuint(buffer, token->type); @@ -333,12 +334,7 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const pm_parser_t parser; pm_parser_init(&arena, &parser, source, size, &options); - pm_lex_callback_t lex_callback = (pm_lex_callback_t) { - .data = (void *) buffer, - .callback = serialize_token, - }; - - parser.lex_callback = &lex_callback; + pm_parser_lex_callback_set(&parser, serialize_token, buffer); pm_parse(&parser); // Append 0 to mark end of tokens. @@ -364,12 +360,7 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_parser_t parser; pm_parser_init(&arena, &parser, source, size, &options); - pm_lex_callback_t lex_callback = (pm_lex_callback_t) { - .data = (void *) buffer, - .callback = serialize_token, - }; - - parser.lex_callback = &lex_callback; + pm_parser_lex_callback_set(&parser, serialize_token, buffer); pm_node_t *node = pm_parse(&parser); pm_buffer_append_byte(buffer, 0); From 7cb8b59590f4351b6e3136c670c01136eb846b09 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 09:58:37 -0400 Subject: [PATCH 198/289] Move static literals entirely internal --- include/prism/internal/parser.h | 3 ++- include/prism/internal/static_literals.h | 5 ++--- include/prism/static_literals.h | 12 ------------ prism.gemspec | 1 - src/prism.c | 2 +- 5 files changed, 5 insertions(+), 18 deletions(-) delete mode 100644 include/prism/static_literals.h diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index f56dee8964..ad21044d3b 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -8,6 +8,8 @@ #include "prism/compiler/accel.h" +#include "prism/internal/static_literals.h" + #include "prism/arena.h" #include "prism/ast.h" #include "prism/encoding.h" @@ -15,7 +17,6 @@ #include "prism/list.h" #include "prism/options.h" #include "prism/parser.h" -#include "prism/static_literals.h" #include #include diff --git a/include/prism/internal/static_literals.h b/include/prism/internal/static_literals.h index f924dd9e6a..0512313259 100644 --- a/include/prism/internal/static_literals.h +++ b/include/prism/internal/static_literals.h @@ -9,7 +9,6 @@ #include "prism/ast.h" #include "prism/buffer.h" #include "prism/line_offset_list.h" -#include "prism/static_literals.h" /** * An internal hash table for a set of nodes. @@ -33,7 +32,7 @@ typedef struct { * We bucket the nodes based on their type to minimize the number of comparisons * that need to be performed. */ -struct pm_static_literals_t { +typedef struct { /** * This is the set of IntegerNode and SourceLineNode instances. */ @@ -84,7 +83,7 @@ struct pm_static_literals_t { * NULL. */ pm_node_t *source_encoding_node; -}; +} pm_static_literals_t; /** * Add a node to the set of static literals. diff --git a/include/prism/static_literals.h b/include/prism/static_literals.h deleted file mode 100644 index 4519510280..0000000000 --- a/include/prism/static_literals.h +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @file static_literals.h - * - * A set of static literal nodes that can be checked for duplicates. - */ -#ifndef PRISM_STATIC_LITERALS_H -#define PRISM_STATIC_LITERALS_H - -/** An opaque struct that holds the static literals. */ -typedef struct pm_static_literals_t pm_static_literals_t; - -#endif diff --git a/prism.gemspec b/prism.gemspec index 762ab7b590..2d0a0d43aa 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -92,7 +92,6 @@ Gem::Specification.new do |spec| "include/prism/options.h", "include/prism/parser.h", "include/prism/prettyprint.h", - "include/prism/static_literals.h", "include/prism/string_query.h", "include/prism/strings.h", "include/prism/version.h", diff --git a/src/prism.c b/src/prism.c index 5814fa4fee..eb1ab8a256 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22255,7 +22255,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si .encoding = PM_ENCODING_UTF_8_ENTRY, .encoding_changed_callback = NULL, .encoding_comment_start = source, - .lex_callback = NULL, + .lex_callback = { 0 }, .filepath = { 0 }, .constant_pool = { 0 }, .line_offsets = { 0 }, From 2b84d22051a494908d7ed366c28b2e1e43d6ec12 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 10:02:52 -0400 Subject: [PATCH 199/289] Move some serialize functions internal --- include/prism.h | 25 ---------------- include/prism/internal/serialize.h | 47 ++++++++++++++++++++++++++++++ src/prism.c | 1 + 3 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 include/prism/internal/serialize.h diff --git a/include/prism.h b/include/prism.h index 3a35b257d6..fd3b80a12f 100644 --- a/include/prism.h +++ b/include/prism.h @@ -138,31 +138,6 @@ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_are */ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data); -/** - * Serialize the given list of comments to the given buffer. - * - * @param list The list of comments to serialize. - * @param buffer The buffer to serialize to. - */ -void pm_serialize_comment_list(pm_list_t *list, pm_buffer_t *buffer); - -/** - * Serialize the name of the encoding to the buffer. - * - * @param encoding The encoding to serialize. - * @param buffer The buffer to serialize to. - */ -void pm_serialize_encoding(const pm_encoding_t *encoding, pm_buffer_t *buffer); - -/** - * Serialize the encoding, metadata, nodes, and constant pool. - * - * @param parser The parser to serialize. - * @param node The node to serialize. - * @param buffer The buffer to serialize to. - */ -void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer); - /** * Serialize the AST represented by the given node to the given buffer. * diff --git a/include/prism/internal/serialize.h b/include/prism/internal/serialize.h new file mode 100644 index 0000000000..a67ebd1a18 --- /dev/null +++ b/include/prism/internal/serialize.h @@ -0,0 +1,47 @@ +/** + * @file internal/serialize.h + */ +#ifndef PRISM_INTERNAL_SERIALIZE_H +#define PRISM_INTERNAL_SERIALIZE_H + +#include "prism/internal/encoding.h" + +#include "prism/ast.h" +#include "prism/buffer.h" +#include "prism/excludes.h" +#include "prism/list.h" +#include "prism/parser.h" + +/* We optionally support serializing to a binary string. For systems that do not + * want or need this functionality, it can be turned off with the + * PRISM_EXCLUDE_SERIALIZATION define. */ +#ifndef PRISM_EXCLUDE_SERIALIZATION + +/** + * Serialize the given list of comments to the given buffer. + * + * @param list The list of comments to serialize. + * @param buffer The buffer to serialize to. + */ +void pm_serialize_comment_list(pm_list_t *list, pm_buffer_t *buffer); + +/** + * Serialize the name of the encoding to the buffer. + * + * @param encoding The encoding to serialize. + * @param buffer The buffer to serialize to. + */ +void pm_serialize_encoding(const pm_encoding_t *encoding, pm_buffer_t *buffer); + +/** + * Serialize the encoding, metadata, nodes, and constant pool. + * + * @param parser The parser to serialize. + * @param node The node to serialize. + * @param buffer The buffer to serialize to. + */ +void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer); + +#endif + +#endif diff --git a/src/prism.c b/src/prism.c index eb1ab8a256..a5d91fe5bb 100644 --- a/src/prism.c +++ b/src/prism.c @@ -21,6 +21,7 @@ #include "prism/internal/options.h" #include "prism/internal/parser.h" #include "prism/internal/regexp.h" +#include "prism/internal/serialize.h" #include "prism/internal/static_literals.h" #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" From 10ebcaf9086ce16a5b53df37f3169d609524060e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 10:04:23 -0400 Subject: [PATCH 200/289] Move encoding entirely internal --- include/prism.h | 1 - include/prism/encoding.h | 13 ------------- include/prism/internal/encoding.h | 6 ++---- include/prism/internal/parser.h | 2 +- prism.gemspec | 1 - 5 files changed, 3 insertions(+), 20 deletions(-) delete mode 100644 include/prism/encoding.h diff --git a/include/prism.h b/include/prism.h index fd3b80a12f..9af3e6cf6c 100644 --- a/include/prism.h +++ b/include/prism.h @@ -13,7 +13,6 @@ extern "C" { #include "prism/arena.h" #include "prism/ast.h" #include "prism/diagnostic.h" -#include "prism/encoding.h" #include "prism/excludes.h" #include "prism/node.h" #include "prism/options.h" diff --git a/include/prism/encoding.h b/include/prism/encoding.h deleted file mode 100644 index a2061b65b6..0000000000 --- a/include/prism/encoding.h +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @file encoding.h - * - * The encoding interface and implementations used by the parser. - */ -#ifndef PRISM_ENCODING_H -#define PRISM_ENCODING_H - -/* The encoding that the parser uses to process the source code. An opaque - * struct that is defined in the implementation file. */ -typedef struct pm_encoding_t pm_encoding_t; - -#endif diff --git a/include/prism/internal/encoding.h b/include/prism/internal/encoding.h index a62c1fd548..eb68ad6250 100644 --- a/include/prism/internal/encoding.h +++ b/include/prism/internal/encoding.h @@ -6,8 +6,6 @@ #ifndef PRISM_INTERNAL_ENCODING_H #define PRISM_INTERNAL_ENCODING_H -#include "prism/encoding.h" - #include #include #include @@ -18,7 +16,7 @@ * Each callback should return the number of bytes, or 0 if the next bytes are * invalid for the encoding and type. */ -struct pm_encoding_t { +typedef struct { /** * Return the number of bytes that the next character takes if it is valid * in the encoding. Does not read more than n bytes. It is assumed that n is @@ -57,7 +55,7 @@ struct pm_encoding_t { * Return true if the encoding is a multibyte encoding. */ bool multibyte; -}; +} pm_encoding_t; /** * All of the lookup tables use the first bit of each embedded byte to indicate diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index ad21044d3b..86e577b314 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -8,11 +8,11 @@ #include "prism/compiler/accel.h" +#include "prism/internal/encoding.h" #include "prism/internal/static_literals.h" #include "prism/arena.h" #include "prism/ast.h" -#include "prism/encoding.h" #include "prism/line_offset_list.h" #include "prism/list.h" #include "prism/options.h" diff --git a/prism.gemspec b/prism.gemspec index 2d0a0d43aa..70e5aefe1b 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -82,7 +82,6 @@ Gem::Specification.new do |spec| "include/prism/buffer.h", "include/prism/constant_pool.h", "include/prism/diagnostic.h", - "include/prism/encoding.h", "include/prism/excludes.h", "include/prism/integer.h", "include/prism/line_offset_list.h", From da00377f7d4f9d7b07803155ce5b0470ac599850 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 10:06:45 -0400 Subject: [PATCH 201/289] Move some options internal metadata internal --- include/prism/internal/options.h | 31 +++++++++++++++++++++++++++++++ include/prism/internal/parser.h | 2 +- include/prism/options.h | 31 ------------------------------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/include/prism/internal/options.h b/include/prism/internal/options.h index 2dea2f9422..59606b09e6 100644 --- a/include/prism/internal/options.h +++ b/include/prism/internal/options.h @@ -22,6 +22,37 @@ struct pm_options_scope_t { uint8_t forwarding; }; +/** + * The version of Ruby syntax that we should be parsing with. This is used to + * allow consumers to specify which behavior they want in case they need to + * parse in the same way as a specific version of CRuby would have. + */ +typedef enum { + /** + * If an explicit version is not provided, the current version of prism will + * be used. + */ + PM_OPTIONS_VERSION_UNSET = 0, + + /** The vendored version of prism in CRuby 3.3.x. */ + PM_OPTIONS_VERSION_CRUBY_3_3 = 1, + + /** The vendored version of prism in CRuby 3.4.x. */ + PM_OPTIONS_VERSION_CRUBY_3_4 = 2, + + /** The vendored version of prism in CRuby 4.0.x. */ + PM_OPTIONS_VERSION_CRUBY_3_5 = 3, + + /** The vendored version of prism in CRuby 4.0.x. */ + PM_OPTIONS_VERSION_CRUBY_4_0 = 3, + + /** The vendored version of prism in CRuby 4.1.x. */ + PM_OPTIONS_VERSION_CRUBY_4_1 = 4, + + /** The current version of prism. */ + PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_4_1 +} pm_options_version_t; + /** * The options that can be passed to the parser. */ diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index 86e577b314..f8baf49cdb 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -9,13 +9,13 @@ #include "prism/compiler/accel.h" #include "prism/internal/encoding.h" +#include "prism/internal/options.h" #include "prism/internal/static_literals.h" #include "prism/arena.h" #include "prism/ast.h" #include "prism/line_offset_list.h" #include "prism/list.h" -#include "prism/options.h" #include "prism/parser.h" #include diff --git a/include/prism/options.h b/include/prism/options.h index 477b593b2a..aba122f705 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -66,37 +66,6 @@ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_ALL = 0x8; */ typedef void (*pm_options_shebang_callback_t)(pm_options_t *options, const uint8_t *source, size_t length, void *shebang_callback_data); -/** - * The version of Ruby syntax that we should be parsing with. This is used to - * allow consumers to specify which behavior they want in case they need to - * parse in the same way as a specific version of CRuby would have. - */ -typedef enum { - /** - * If an explicit version is not provided, the current version of prism will - * be used. - */ - PM_OPTIONS_VERSION_UNSET = 0, - - /** The vendored version of prism in CRuby 3.3.x. */ - PM_OPTIONS_VERSION_CRUBY_3_3 = 1, - - /** The vendored version of prism in CRuby 3.4.x. */ - PM_OPTIONS_VERSION_CRUBY_3_4 = 2, - - /** The vendored version of prism in CRuby 4.0.x. */ - PM_OPTIONS_VERSION_CRUBY_3_5 = 3, - - /** The vendored version of prism in CRuby 4.0.x. */ - PM_OPTIONS_VERSION_CRUBY_4_0 = 3, - - /** The vendored version of prism in CRuby 4.1.x. */ - PM_OPTIONS_VERSION_CRUBY_4_1 = 4, - - /** The current version of prism. */ - PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_4_1 -} pm_options_version_t; - /** * A bit representing whether or not the command line -a option was set. -a * splits the input line $_ into $F. From a29aab41797a7baec3b5613d3e37e73e89af9438 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 10:16:46 -0400 Subject: [PATCH 202/289] Consistency in naming --- ext/prism/extension.c | 4 ++-- templates/include/prism/diagnostic.h.erb | 2 +- templates/src/diagnostic.c.erb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 9b03387fc9..70f7fd0eb0 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -566,7 +566,7 @@ parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bo error != NULL; error = (const pm_diagnostic_t *) error->node.next ) { - VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_human(error->diag_id))); + VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_str(error->diag_id))); VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(error->message, encoding)); VALUE location = PARSER_LOCATION(source, freeze, error->location); @@ -607,7 +607,7 @@ parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, warning != NULL; warning = (const pm_diagnostic_t *) warning->node.next ) { - VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_human(warning->diag_id))); + VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_str(warning->diag_id))); VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(warning->message, encoding)); VALUE location = PARSER_LOCATION(source, freeze, warning->location); diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb index dceb21cf65..89ef49a2d4 100644 --- a/templates/include/prism/diagnostic.h.erb +++ b/templates/include/prism/diagnostic.h.erb @@ -83,6 +83,6 @@ typedef enum { * @param diag_id The diagnostic ID to get the name of. * @returns The human-readable name of the given diagnostic ID. */ -PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_id_human(pm_diagnostic_id_t diag_id); +PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_id_str(pm_diagnostic_id_t diag_id); #endif diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 15b2a776a7..996599b0e5 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -426,7 +426,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { * Get the human-readable name of the given diagnostic ID. */ const char * -pm_diagnostic_id_human(pm_diagnostic_id_t diag_id) { +pm_diagnostic_id_str(pm_diagnostic_id_t diag_id) { switch (diag_id) { <%- errors.each do |error| -%> case PM_ERR_<%= error.name %>: return "<%= error.name.downcase %>"; From 0b17e49b8b023cde13e33a6fa6b0efbcc4588e5e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 10:38:03 -0400 Subject: [PATCH 203/289] Make pm_comment_t opaque --- ext/prism/extension.c | 14 ++-- include/prism/internal/parser.h | 26 ++++++++ include/prism/parser.h | 109 +++++++++++++++++++++++--------- src/parser.c | 59 +++++++++++++++-- 4 files changed, 168 insertions(+), 40 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 70f7fd0eb0..241419135d 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -480,8 +480,8 @@ parser_location(VALUE source, bool freeze, uint32_t start, uint32_t length) { */ static inline VALUE parser_comment(VALUE source, bool freeze, const pm_comment_t *comment) { - VALUE argv[] = { PARSER_LOCATION(source, freeze, comment->location) }; - VALUE type = (comment->type == PM_COMMENT_EMBDOC) ? rb_cPrismEmbDocComment : rb_cPrismInlineComment; + VALUE argv[] = { PARSER_LOCATION(source, freeze, pm_comment_location(comment)) }; + VALUE type = (pm_comment_type(comment) == PM_COMMENT_EMBDOC) ? rb_cPrismEmbDocComment : rb_cPrismInlineComment; return rb_class_new_instance_freeze(1, argv, type, freeze); } @@ -490,19 +490,21 @@ parser_comment(VALUE source, bool freeze, const pm_comment_t *comment) { */ static VALUE parser_comments(const pm_parser_t *parser, VALUE source, bool freeze) { - const pm_list_t *comments_list = pm_parser_comments(parser); - VALUE comments = rb_ary_new_capa(comments_list->size); + pm_comments_iter_t *comments_iter = pm_comments_iter(parser); + VALUE comments = rb_ary_new_capa(pm_comments_iter_size(comments_iter)); for ( - const pm_comment_t *comment = (const pm_comment_t *) comments_list->head; + const pm_comment_t *comment = pm_comments_iter_next(comments_iter); comment != NULL; - comment = (const pm_comment_t *) comment->node.next + comment = pm_comments_iter_next(comments_iter) ) { VALUE value = parser_comment(source, freeze, comment); rb_ary_push(comments, value); } + pm_comments_iter_free(comments_iter); if (freeze) rb_obj_freeze(comments); + return comments; } diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index f8baf49cdb..ed696b1221 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -933,4 +933,30 @@ struct pm_parser_t { #endif }; +/** + * A comment found while parsing. + */ +struct pm_comment_t { + /** The embedded base node. */ + pm_list_node_t node; + + /** The location of the comment in the source. */ + pm_location_t location; + + /** The type of the comment. */ + pm_comment_type_t type; +}; + +/** + * A struct used as an opaque pointer for the client to iterate through the + * comments found while parsing. + */ +struct pm_comments_iter_t { + /** The number of comments in the list. */ + size_t size; + + /** The current node in the list. */ + const pm_list_node_t *current; +}; + #endif diff --git a/include/prism/parser.h b/include/prism/parser.h index 047999142c..b13e9e8190 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -15,28 +15,6 @@ */ typedef struct pm_parser_t pm_parser_t; -/** This is the type of a comment that we've found while parsing. */ -typedef enum { - PM_COMMENT_INLINE, - PM_COMMENT_EMBDOC -} pm_comment_type_t; - -/** - * This is a node in the linked list of comments that we've found while parsing. - * - * @extends pm_list_node_t - */ -typedef struct pm_comment { - /** The embedded base node. */ - pm_list_node_t node; - - /** The location of the comment in the source. */ - pm_location_t location; - - /** The type of comment that we've found. */ - pm_comment_type_t type; -} pm_comment_t; - /** * This is a node in the linked list of magic comments that we've found while * parsing. @@ -144,14 +122,6 @@ PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_errors(const pm_parser_t *pa */ PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_warnings(const pm_parser_t *parser); -/** - * Returns the comments that are associated with the given parser. - * - * @param parser the parser whose comments we want to get - * @return the comments that are associated with the given parser - */ -PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_comments(const pm_parser_t *parser); - /** * Returns the magic comments that are associated with the given parser. * @@ -206,4 +176,83 @@ PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); +/******************************************************************************/ +/* Comments */ +/******************************************************************************/ + +/** This is the type of a comment that we've found while parsing. */ +typedef enum { + PM_COMMENT_INLINE, + PM_COMMENT_EMBDOC +} pm_comment_type_t; + +/** An opaque pointer to a comment found while parsing. */ +typedef struct pm_comment_t pm_comment_t; + +/** + * Returns the location associated with the given comment. + * + * @param comment the comment whose location we want to get + * @return the location associated with the given comment + */ +PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *comment); + +/** + * Returns the type associated with the given comment. + * + * @param comment the comment whose type we want to get + * @return the type associated with the given comment. This can either be + * PM_COMMENT_INLINE or PM_COMMENT_EMBDOC. + */ +PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *comment); + +/* An opaque pointer to an iterator that can be used to iterate over the + * comments associated with a parser. */ +typedef struct pm_comments_iter_t pm_comments_iter_t; + +/** + * Returns an iterator that knows how to iterate over the comments that are + * associated with the given parser. + * + * @param parser the parser whose comments we want to get + * @return the iterator that knows how to iterate over the comments that are + * associated with the given parser. It is the responsibility of the caller + * to free the memory associated with the iterator through + * pm_comments_iter_free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_comments_iter(const pm_parser_t *parser); + +/** + * Returns the number of comments associated with the comment iterator. + * + * @param iter the iterator to get the number of comments from + * @return the number of comments associated with the comment iterator + * + * \public \memberof pm_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION size_t pm_comments_iter_size(const pm_comments_iter_t *iter); + +/** + * Returns the next comment in the iteration, or NULL if there are no more + * comments. + * + * @param iter the iterator to get the next comment from + * @return the next comment in the iteration, or NULL if there are no more + * comments. + * + * \public \memberof pm_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION const pm_comment_t * pm_comments_iter_next(pm_comments_iter_t *iter); + +/** + * Frees the memory associated with the given comments iterator. + * + * @param iter the iterator to free + * + * \public \memberof pm_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION void pm_comments_iter_free(pm_comments_iter_t *iter); + #endif diff --git a/src/parser.c b/src/parser.c index 209f748ff2..401ae3a386 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,7 +1,10 @@ #include "prism/internal/parser.h" +#include "prism/internal/allocator.h" #include "prism/internal/encoding.h" +#include + /** * Register a callback that will be called whenever prism changes the encoding * it is using to parse based on the magic comment. @@ -80,11 +83,59 @@ pm_parser_warnings(const pm_parser_t *parser) { } /** - * Returns the comments that are associated with the given parser. + * Returns the location associated with the given comment. */ -const pm_list_t * -pm_parser_comments(const pm_parser_t *parser) { - return &parser->comment_list; +pm_location_t +pm_comment_location(const pm_comment_t *comment) { + return comment->location; +} + +/** + * Returns the type associated with the given comment. + */ +pm_comment_type_t +pm_comment_type(const pm_comment_t *comment) { + return comment->type; +} + +/** + * Returns an iterator that knows how to iterate over the comments that are + * associated with the given parser. + */ +pm_comments_iter_t * +pm_comments_iter(const pm_parser_t *parser) { + pm_comments_iter_t *iter = (pm_comments_iter_t *) xmalloc(sizeof(pm_comments_iter_t)); + iter->size = parser->comment_list.size; + iter->current = parser->comment_list.head; + return iter; +} + +/** + * Returns the number of comments associated with the comment iterator. + */ +size_t +pm_comments_iter_size(const pm_comments_iter_t *iter) { + return iter->size; +} + +/** + * Returns the next comment in the iteration, or NULL if there are no more + * comments. + */ +const pm_comment_t * +pm_comments_iter_next(pm_comments_iter_t *iter) { + if (iter->current == NULL) return NULL; + const pm_comment_t *comment = (const pm_comment_t *) iter->current; + iter->current = iter->current->next; + return comment; +} + +/** + * Frees the memory associated with the given comments iterator. + */ +void +pm_comments_iter_free(pm_comments_iter_t *iter) { + xfree(iter); } /** From 1ddff36b54905d7c5bdd56928b4384f52d6f816d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 10:44:19 -0400 Subject: [PATCH 204/289] Move comment into its own section --- include/prism.h | 1 + include/prism/comment.h | 91 ++++++++++++++++++++++++++++++++ include/prism/internal/comment.h | 35 ++++++++++++ include/prism/internal/parser.h | 26 --------- include/prism/parser.h | 79 --------------------------- src/comment.c | 62 ++++++++++++++++++++++ src/parser.c | 56 -------------------- src/prism.c | 1 + templates/src/serialize.c.erb | 1 + 9 files changed, 191 insertions(+), 161 deletions(-) create mode 100644 include/prism/comment.h create mode 100644 include/prism/internal/comment.h create mode 100644 src/comment.c diff --git a/include/prism.h b/include/prism.h index 9af3e6cf6c..9dcfe9a6ec 100644 --- a/include/prism.h +++ b/include/prism.h @@ -12,6 +12,7 @@ extern "C" { #include "prism/arena.h" #include "prism/ast.h" +#include "prism/comment.h" #include "prism/diagnostic.h" #include "prism/excludes.h" #include "prism/node.h" diff --git a/include/prism/comment.h b/include/prism/comment.h new file mode 100644 index 0000000000..22b3f2d2fb --- /dev/null +++ b/include/prism/comment.h @@ -0,0 +1,91 @@ +/** + * @file comment.h + * + * The comment module used to handle comments in Ruby source. + */ +#ifndef PRISM_COMMENT_H +#define PRISM_COMMENT_H + +#include "prism/compiler/exported.h" + +#include "prism/ast.h" +#include "prism/parser.h" + +#include + +/** This is the type of a comment that we've found while parsing. */ +typedef enum { + PM_COMMENT_INLINE, + PM_COMMENT_EMBDOC +} pm_comment_type_t; + +/** An opaque pointer to a comment found while parsing. */ +typedef struct pm_comment_t pm_comment_t; + +/** + * Returns the location associated with the given comment. + * + * @param comment the comment whose location we want to get + * @return the location associated with the given comment + */ +PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *comment); + +/** + * Returns the type associated with the given comment. + * + * @param comment the comment whose type we want to get + * @return the type associated with the given comment. This can either be + * PM_COMMENT_INLINE or PM_COMMENT_EMBDOC. + */ +PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *comment); + +/* An opaque pointer to an iterator that can be used to iterate over the + * comments associated with a parser. */ +typedef struct pm_comments_iter_t pm_comments_iter_t; + +/** + * Returns an iterator that knows how to iterate over the comments that are + * associated with the given parser. + * + * @param parser the parser whose comments we want to get + * @return the iterator that knows how to iterate over the comments that are + * associated with the given parser. It is the responsibility of the caller + * to free the memory associated with the iterator through + * pm_comments_iter_free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_comments_iter(const pm_parser_t *parser); + +/** + * Returns the number of comments associated with the comment iterator. + * + * @param iter the iterator to get the number of comments from + * @return the number of comments associated with the comment iterator + * + * \public \memberof pm_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION size_t pm_comments_iter_size(const pm_comments_iter_t *iter); + +/** + * Returns the next comment in the iteration, or NULL if there are no more + * comments. + * + * @param iter the iterator to get the next comment from + * @return the next comment in the iteration, or NULL if there are no more + * comments. + * + * \public \memberof pm_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION const pm_comment_t * pm_comments_iter_next(pm_comments_iter_t *iter); + +/** + * Frees the memory associated with the given comments iterator. + * + * @param iter the iterator to free + * + * \public \memberof pm_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION void pm_comments_iter_free(pm_comments_iter_t *iter); + +#endif diff --git a/include/prism/internal/comment.h b/include/prism/internal/comment.h new file mode 100644 index 0000000000..c717432075 --- /dev/null +++ b/include/prism/internal/comment.h @@ -0,0 +1,35 @@ +/** + * @file internal/comment.h + */ +#ifndef PRISM_INTERNAL_COMMENT_H +#define PRISM_INTERNAL_COMMENT_H + +#include "prism/comment.h" + +/** + * A comment found while parsing. + */ +struct pm_comment_t { + /** The embedded base node. */ + pm_list_node_t node; + + /** The location of the comment in the source. */ + pm_location_t location; + + /** The type of the comment. */ + pm_comment_type_t type; +}; + +/** + * A struct used as an opaque pointer for the client to iterate through the + * comments found while parsing. + */ +struct pm_comments_iter_t { + /** The number of comments in the list. */ + size_t size; + + /** The current node in the list. */ + const pm_list_node_t *current; +}; + +#endif diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index ed696b1221..f8baf49cdb 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -933,30 +933,4 @@ struct pm_parser_t { #endif }; -/** - * A comment found while parsing. - */ -struct pm_comment_t { - /** The embedded base node. */ - pm_list_node_t node; - - /** The location of the comment in the source. */ - pm_location_t location; - - /** The type of the comment. */ - pm_comment_type_t type; -}; - -/** - * A struct used as an opaque pointer for the client to iterate through the - * comments found while parsing. - */ -struct pm_comments_iter_t { - /** The number of comments in the list. */ - size_t size; - - /** The current node in the list. */ - const pm_list_node_t *current; -}; - #endif diff --git a/include/prism/parser.h b/include/prism/parser.h index b13e9e8190..d1cb5b8827 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -176,83 +176,4 @@ PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); -/******************************************************************************/ -/* Comments */ -/******************************************************************************/ - -/** This is the type of a comment that we've found while parsing. */ -typedef enum { - PM_COMMENT_INLINE, - PM_COMMENT_EMBDOC -} pm_comment_type_t; - -/** An opaque pointer to a comment found while parsing. */ -typedef struct pm_comment_t pm_comment_t; - -/** - * Returns the location associated with the given comment. - * - * @param comment the comment whose location we want to get - * @return the location associated with the given comment - */ -PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *comment); - -/** - * Returns the type associated with the given comment. - * - * @param comment the comment whose type we want to get - * @return the type associated with the given comment. This can either be - * PM_COMMENT_INLINE or PM_COMMENT_EMBDOC. - */ -PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *comment); - -/* An opaque pointer to an iterator that can be used to iterate over the - * comments associated with a parser. */ -typedef struct pm_comments_iter_t pm_comments_iter_t; - -/** - * Returns an iterator that knows how to iterate over the comments that are - * associated with the given parser. - * - * @param parser the parser whose comments we want to get - * @return the iterator that knows how to iterate over the comments that are - * associated with the given parser. It is the responsibility of the caller - * to free the memory associated with the iterator through - * pm_comments_iter_free. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_comments_iter(const pm_parser_t *parser); - -/** - * Returns the number of comments associated with the comment iterator. - * - * @param iter the iterator to get the number of comments from - * @return the number of comments associated with the comment iterator - * - * \public \memberof pm_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION size_t pm_comments_iter_size(const pm_comments_iter_t *iter); - -/** - * Returns the next comment in the iteration, or NULL if there are no more - * comments. - * - * @param iter the iterator to get the next comment from - * @return the next comment in the iteration, or NULL if there are no more - * comments. - * - * \public \memberof pm_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION const pm_comment_t * pm_comments_iter_next(pm_comments_iter_t *iter); - -/** - * Frees the memory associated with the given comments iterator. - * - * @param iter the iterator to free - * - * \public \memberof pm_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION void pm_comments_iter_free(pm_comments_iter_t *iter); - #endif diff --git a/src/comment.c b/src/comment.c new file mode 100644 index 0000000000..a087a4c135 --- /dev/null +++ b/src/comment.c @@ -0,0 +1,62 @@ +#include "prism/internal/comment.h" + +#include "prism/internal/allocator.h" +#include "prism/internal/parser.h" + +#include + +/** + * Returns the location associated with the given comment. + */ +pm_location_t +pm_comment_location(const pm_comment_t *comment) { + return comment->location; +} + +/** + * Returns the type associated with the given comment. + */ +pm_comment_type_t +pm_comment_type(const pm_comment_t *comment) { + return comment->type; +} + +/** + * Returns an iterator that knows how to iterate over the comments that are + * associated with the given parser. + */ +pm_comments_iter_t * +pm_comments_iter(const pm_parser_t *parser) { + pm_comments_iter_t *iter = (pm_comments_iter_t *) xmalloc(sizeof(pm_comments_iter_t)); + iter->size = parser->comment_list.size; + iter->current = parser->comment_list.head; + return iter; +} + +/** + * Returns the number of comments associated with the comment iterator. + */ +size_t +pm_comments_iter_size(const pm_comments_iter_t *iter) { + return iter->size; +} + +/** + * Returns the next comment in the iteration, or NULL if there are no more + * comments. + */ +const pm_comment_t * +pm_comments_iter_next(pm_comments_iter_t *iter) { + if (iter->current == NULL) return NULL; + const pm_comment_t *comment = (const pm_comment_t *) iter->current; + iter->current = iter->current->next; + return comment; +} + +/** + * Frees the memory associated with the given comments iterator. + */ +void +pm_comments_iter_free(pm_comments_iter_t *iter) { + xfree(iter); +} diff --git a/src/parser.c b/src/parser.c index 401ae3a386..c4784c27ea 100644 --- a/src/parser.c +++ b/src/parser.c @@ -82,62 +82,6 @@ pm_parser_warnings(const pm_parser_t *parser) { return &parser->warning_list; } -/** - * Returns the location associated with the given comment. - */ -pm_location_t -pm_comment_location(const pm_comment_t *comment) { - return comment->location; -} - -/** - * Returns the type associated with the given comment. - */ -pm_comment_type_t -pm_comment_type(const pm_comment_t *comment) { - return comment->type; -} - -/** - * Returns an iterator that knows how to iterate over the comments that are - * associated with the given parser. - */ -pm_comments_iter_t * -pm_comments_iter(const pm_parser_t *parser) { - pm_comments_iter_t *iter = (pm_comments_iter_t *) xmalloc(sizeof(pm_comments_iter_t)); - iter->size = parser->comment_list.size; - iter->current = parser->comment_list.head; - return iter; -} - -/** - * Returns the number of comments associated with the comment iterator. - */ -size_t -pm_comments_iter_size(const pm_comments_iter_t *iter) { - return iter->size; -} - -/** - * Returns the next comment in the iteration, or NULL if there are no more - * comments. - */ -const pm_comment_t * -pm_comments_iter_next(pm_comments_iter_t *iter) { - if (iter->current == NULL) return NULL; - const pm_comment_t *comment = (const pm_comment_t *) iter->current; - iter->current = iter->current->next; - return comment; -} - -/** - * Frees the memory associated with the given comments iterator. - */ -void -pm_comments_iter_free(pm_comments_iter_t *iter) { - xfree(iter); -} - /** * Returns the magic comments that are associated with the given parser. */ diff --git a/src/prism.c b/src/prism.c index a5d91fe5bb..421e081ace 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9,6 +9,7 @@ #include "prism/internal/bit.h" #include "prism/internal/buffer.h" #include "prism/internal/char.h" +#include "prism/internal/comment.h" #include "prism/internal/constant_pool.h" #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index cfd073b7e6..a8c2daa532 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -8,6 +8,7 @@ #include "prism/compiler/inline.h" #include "prism/internal/buffer.h" +#include "prism/internal/comment.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" From 84b08e23d65b7c59a5782d428b93b18c68911f74 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 10:46:29 -0400 Subject: [PATCH 205/289] Move more constants internal --- ext/prism/extension.c | 2 +- include/prism.h | 1 - include/prism/{comment.h => comments.h} | 23 +++---------------- include/prism/constant_pool.h | 7 ------ .../prism/internal/{comment.h => comments.h} | 10 ++++---- include/prism/internal/constant_pool.h | 9 ++++++++ include/prism/parser.h | 15 ++++++++++++ src/{comment.c => comments.c} | 14 +---------- src/constant_pool.c | 2 +- src/parser.c | 13 +++++++++++ src/prism.c | 2 +- templates/src/serialize.c.erb | 2 +- 12 files changed, 51 insertions(+), 49 deletions(-) rename include/prism/{comment.h => comments.h} (74%) rename include/prism/internal/{comment.h => comments.h} (79%) rename src/{comment.c => comments.c} (71%) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 241419135d..0c98b988d0 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -490,7 +490,7 @@ parser_comment(VALUE source, bool freeze, const pm_comment_t *comment) { */ static VALUE parser_comments(const pm_parser_t *parser, VALUE source, bool freeze) { - pm_comments_iter_t *comments_iter = pm_comments_iter(parser); + pm_comments_iter_t *comments_iter = pm_parser_comments(parser); VALUE comments = rb_ary_new_capa(pm_comments_iter_size(comments_iter)); for ( diff --git a/include/prism.h b/include/prism.h index 9dcfe9a6ec..9af3e6cf6c 100644 --- a/include/prism.h +++ b/include/prism.h @@ -12,7 +12,6 @@ extern "C" { #include "prism/arena.h" #include "prism/ast.h" -#include "prism/comment.h" #include "prism/diagnostic.h" #include "prism/excludes.h" #include "prism/node.h" diff --git a/include/prism/comment.h b/include/prism/comments.h similarity index 74% rename from include/prism/comment.h rename to include/prism/comments.h index 22b3f2d2fb..7c95d0ca72 100644 --- a/include/prism/comment.h +++ b/include/prism/comments.h @@ -1,15 +1,12 @@ /** - * @file comment.h - * - * The comment module used to handle comments in Ruby source. + * @file comments.h */ -#ifndef PRISM_COMMENT_H -#define PRISM_COMMENT_H +#ifndef PRISM_COMMENTS_H +#define PRISM_COMMENTS_H #include "prism/compiler/exported.h" #include "prism/ast.h" -#include "prism/parser.h" #include @@ -43,20 +40,6 @@ PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *co * comments associated with a parser. */ typedef struct pm_comments_iter_t pm_comments_iter_t; -/** - * Returns an iterator that knows how to iterate over the comments that are - * associated with the given parser. - * - * @param parser the parser whose comments we want to get - * @return the iterator that knows how to iterate over the comments that are - * associated with the given parser. It is the responsibility of the caller - * to free the memory associated with the iterator through - * pm_comments_iter_free. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_comments_iter(const pm_parser_t *parser); - /** * Returns the number of comments associated with the comment iterator. * diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index cc426bb0ab..b1db33f8e3 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -13,13 +13,6 @@ #include #include -/** - * When we allocate constants into the pool, we reserve 0 to mean that the slot - * is not yet filled. This constant is reused in other places to indicate the - * lack of a constant id. - */ -#define PM_CONSTANT_ID_UNSET 0 - /** * A constant id is a unique identifier for a constant in the constant pool. */ diff --git a/include/prism/internal/comment.h b/include/prism/internal/comments.h similarity index 79% rename from include/prism/internal/comment.h rename to include/prism/internal/comments.h index c717432075..c7adf52464 100644 --- a/include/prism/internal/comment.h +++ b/include/prism/internal/comments.h @@ -1,10 +1,12 @@ /** - * @file internal/comment.h + * @file internal/comments.h */ -#ifndef PRISM_INTERNAL_COMMENT_H -#define PRISM_INTERNAL_COMMENT_H +#ifndef PRISM_INTERNAL_COMMENTS_H +#define PRISM_INTERNAL_COMMENTS_H -#include "prism/comment.h" +#include "prism/comments.h" + +#include "prism/list.h" /** * A comment found while parsing. diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h index 03671938a6..9e7d3cd74b 100644 --- a/include/prism/internal/constant_pool.h +++ b/include/prism/internal/constant_pool.h @@ -14,6 +14,15 @@ #include "prism/arena.h" +#include + +/** + * When we allocate constants into the pool, we reserve 0 to mean that the slot + * is not yet filled. This constant is reused in other places to indicate the + * lack of a constant id. + */ +#define PM_CONSTANT_ID_UNSET 0 + /** * Initialize a list of constant ids. * diff --git a/include/prism/parser.h b/include/prism/parser.h index d1cb5b8827..b1726b4975 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -7,6 +7,7 @@ #define PRISM_PARSER_H #include "prism/ast.h" +#include "prism/comments.h" #include "prism/line_offset_list.h" #include "prism/list.h" @@ -176,4 +177,18 @@ PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); +/** + * Returns an iterator that knows how to iterate over the comments that are + * associated with the given parser. + * + * @param parser the parser whose comments we want to get + * @return the iterator that knows how to iterate over the comments that are + * associated with the given parser. It is the responsibility of the caller + * to free the memory associated with the iterator through + * pm_comments_iter_free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_parser_comments(const pm_parser_t *parser); + #endif diff --git a/src/comment.c b/src/comments.c similarity index 71% rename from src/comment.c rename to src/comments.c index a087a4c135..7e2f1e2f10 100644 --- a/src/comment.c +++ b/src/comments.c @@ -1,4 +1,4 @@ -#include "prism/internal/comment.h" +#include "prism/internal/comments.h" #include "prism/internal/allocator.h" #include "prism/internal/parser.h" @@ -21,18 +21,6 @@ pm_comment_type(const pm_comment_t *comment) { return comment->type; } -/** - * Returns an iterator that knows how to iterate over the comments that are - * associated with the given parser. - */ -pm_comments_iter_t * -pm_comments_iter(const pm_parser_t *parser) { - pm_comments_iter_t *iter = (pm_comments_iter_t *) xmalloc(sizeof(pm_comments_iter_t)); - iter->size = parser->comment_list.size; - iter->current = parser->comment_list.head; - return iter; -} - /** * Returns the number of comments associated with the comment iterator. */ diff --git a/src/constant_pool.c b/src/constant_pool.c index 0baab71997..3f0baac702 100644 --- a/src/constant_pool.c +++ b/src/constant_pool.c @@ -1,4 +1,4 @@ -#include "prism/constant_pool.h" +#include "prism/internal/constant_pool.h" #include "prism/compiler/align.h" #include "prism/compiler/inline.h" diff --git a/src/parser.c b/src/parser.c index c4784c27ea..7447b00f24 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,6 +1,7 @@ #include "prism/internal/parser.h" #include "prism/internal/allocator.h" +#include "prism/internal/comments.h" #include "prism/internal/encoding.h" #include @@ -137,3 +138,15 @@ int pm_parser_lex_state(const pm_parser_t *parser) { return (int) parser->lex_state; } + +/** + * Returns an iterator that knows how to iterate over the comments that are + * associated with the given parser. + */ +pm_comments_iter_t * +pm_parser_comments(const pm_parser_t *parser) { + pm_comments_iter_t *iter = (pm_comments_iter_t *) xmalloc(sizeof(pm_comments_iter_t)); + iter->size = parser->comment_list.size; + iter->current = parser->comment_list.head; + return iter; +} diff --git a/src/prism.c b/src/prism.c index 421e081ace..f948473db8 100644 --- a/src/prism.c +++ b/src/prism.c @@ -9,7 +9,7 @@ #include "prism/internal/bit.h" #include "prism/internal/buffer.h" #include "prism/internal/char.h" -#include "prism/internal/comment.h" +#include "prism/internal/comments.h" #include "prism/internal/constant_pool.h" #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index a8c2daa532..7edb297501 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -8,7 +8,7 @@ #include "prism/compiler/inline.h" #include "prism/internal/buffer.h" -#include "prism/internal/comment.h" +#include "prism/internal/comments.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" From 6f40516041af14166bc97cf2976dc6c5725d8b7c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 11:17:01 -0400 Subject: [PATCH 206/289] Move diagnostics entirely internal --- .gitignore | 2 +- ext/prism/extension.c | 46 +++--- include/prism/diagnostic.h | 134 ++++++++++++++++++ include/prism/internal/diagnostic.h | 37 ----- include/prism/parser.h | 45 +++--- src/parser.c | 41 +++--- templates/include/prism/diagnostic.h.erb | 88 ------------ .../include/prism/internal/diagnostic.h.erb | 89 ++++++++++++ templates/src/diagnostic.c.erb | 88 ++++++++++-- templates/src/serialize.c.erb | 2 +- templates/template.rb | 2 +- 11 files changed, 386 insertions(+), 188 deletions(-) create mode 100644 include/prism/diagnostic.h delete mode 100644 include/prism/internal/diagnostic.h delete mode 100644 templates/include/prism/diagnostic.h.erb create mode 100644 templates/include/prism/internal/diagnostic.h.erb diff --git a/.gitignore b/.gitignore index b914ce4cd9..a8370790b2 100644 --- a/.gitignore +++ b/.gitignore @@ -31,8 +31,8 @@ out.svg /fuzz/output/ /gemfiles/typecheck/bin/ /include/prism/ast.h -/include/prism/diagnostic.h /include/prism/node_new.h +/include/prism/internal/diagnostic.h /javascript/node_modules/ /javascript/package-lock.json /javascript/src/deserialize.js diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 0c98b988d0..1980e44d89 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -560,20 +560,22 @@ parser_data_loc(const pm_parser_t *parser, VALUE source, bool freeze) { */ static VALUE parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) { - const pm_list_t *error_list = pm_parser_errors(parser); - VALUE errors = rb_ary_new_capa(error_list->size); + pm_diagnostics_iter_t *iter = pm_parser_errors(parser); + VALUE errors = rb_ary_new_capa(pm_diagnostics_iter_size(iter)); for ( - const pm_diagnostic_t *error = (const pm_diagnostic_t *) error_list->head; + const pm_diagnostic_t *error = pm_diagnostics_iter_next(iter); error != NULL; - error = (const pm_diagnostic_t *) error->node.next + error = pm_diagnostics_iter_next(iter) ) { - VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_str(error->diag_id))); - VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(error->message, encoding)); - VALUE location = PARSER_LOCATION(source, freeze, error->location); + VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(error))); + VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(error), encoding)); + VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(error)); + pm_error_level_t error_level = pm_diagnostic_error_level(error); VALUE level = Qnil; - switch (error->level) { + + switch (error_level) { case PM_ERROR_LEVEL_SYNTAX: level = ID2SYM(rb_intern("syntax")); break; @@ -584,7 +586,7 @@ parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bo level = ID2SYM(rb_intern("load")); break; default: - rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, error->level); + rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, error_level); } VALUE argv[] = { type, message, location, level }; @@ -592,7 +594,9 @@ parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bo rb_ary_push(errors, value); } + pm_diagnostics_iter_free(iter); if (freeze) rb_obj_freeze(errors); + return errors; } @@ -601,20 +605,22 @@ parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bo */ static VALUE parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) { - const pm_list_t *warning_list = pm_parser_warnings(parser); - VALUE warnings = rb_ary_new_capa(warning_list->size); + pm_diagnostics_iter_t *iter = pm_parser_warnings(parser); + VALUE warnings = rb_ary_new_capa(pm_diagnostics_iter_size(iter)); for ( - const pm_diagnostic_t *warning = (const pm_diagnostic_t *) warning_list->head; + const pm_diagnostic_t *warning = pm_diagnostics_iter_next(iter); warning != NULL; - warning = (const pm_diagnostic_t *) warning->node.next + warning = pm_diagnostics_iter_next(iter) ) { - VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_str(warning->diag_id))); - VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(warning->message, encoding)); - VALUE location = PARSER_LOCATION(source, freeze, warning->location); + VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(warning))); + VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(warning), encoding)); + VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(warning)); + pm_warning_level_t warning_level = pm_diagnostic_warning_level(warning); VALUE level = Qnil; - switch (warning->level) { + + switch (warning_level) { case PM_WARNING_LEVEL_DEFAULT: level = ID2SYM(rb_intern("default")); break; @@ -622,7 +628,7 @@ parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, level = ID2SYM(rb_intern("verbose")); break; default: - rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, warning->level); + rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, warning_level); } VALUE argv[] = { type, message, location, level }; @@ -630,7 +636,9 @@ parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, rb_ary_push(warnings, value); } + pm_diagnostics_iter_free(iter); if (freeze) rb_obj_freeze(warnings); + return warnings; } @@ -1221,7 +1229,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { pm_parse(parser); - VALUE result = pm_parser_errors(parser)->size == 0 ? Qtrue : Qfalse; + VALUE result = pm_diagnostics_iter_size(pm_parser_errors(parser)) == 0 ? Qtrue : Qfalse; pm_parser_free(parser); pm_arena_free(&arena); diff --git a/include/prism/diagnostic.h b/include/prism/diagnostic.h new file mode 100644 index 0000000000..0619c274ef --- /dev/null +++ b/include/prism/diagnostic.h @@ -0,0 +1,134 @@ +/*----------------------------------------------------------------------------*/ +/* This file is generated by the templates/template.rb script and should not */ +/* be modified manually. See */ +/* templates/include/prism/diagnostic.h.erb */ +/* if you are looking to modify the */ +/* template */ +/*----------------------------------------------------------------------------*/ + +/** + * @file diagnostic.h + * + * A list of diagnostics generated during parsing. + */ +#ifndef PRISM_DIAGNOSTIC_H +#define PRISM_DIAGNOSTIC_H + +#include "prism/compiler/exported.h" + +#include "prism/ast.h" + +/** + * An opaque pointer to a diagnostic generated during parsing. + */ +typedef struct pm_diagnostic_t pm_diagnostic_t; + +/** + * The levels of errors generated during parsing. + */ +typedef enum { + /** For errors that should raise a syntax error. */ + PM_ERROR_LEVEL_SYNTAX = 0, + + /** For errors that should raise an argument error. */ + PM_ERROR_LEVEL_ARGUMENT = 1, + + /** For errors that should raise a load error. */ + PM_ERROR_LEVEL_LOAD = 2 +} pm_error_level_t; + +/** + * The levels of warnings generated during parsing. + */ +typedef enum { + /** For warnings which should be emitted if $VERBOSE != nil. */ + PM_WARNING_LEVEL_DEFAULT = 0, + + /** For warnings which should be emitted if $VERBOSE == true. */ + PM_WARNING_LEVEL_VERBOSE = 1 +} pm_warning_level_t; + +/** + * Get the type of the given diagnostic. + * + * @param diagnostic The diagnostic to get the type of. + * @returns The type of the given diagnostic. Note that this is a string + * representation of an internal ID, and is not meant to be relied upon as a + * stable identifier for the diagnostic. We do not guarantee that these will + * not change in the future. This is meant to be used for debugging and + * error reporting purposes, and not for programmatic checks. + */ +PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_type(const pm_diagnostic_t *diagnostic); + +/** + * Get the location of the given diagnostic. + * + * @param diagnostic The diagnostic to get the location of. + * @returns The location of the given diagnostic. + */ +PRISM_EXPORTED_FUNCTION pm_location_t pm_diagnostic_location(const pm_diagnostic_t *diagnostic); + +/** + * Get the message of the given diagnostic. + * + * @param diagnostic The diagnostic to get the message of. + * @returns The message of the given diagnostic. + */ +PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_message(const pm_diagnostic_t *diagnostic); + +/** + * Get the error level associated with the given diagnostic. + * + * @param diagnostic The diagnostic to get the error level of. + * @returns The error level of the given diagnostic. If the diagnostic was a + * warning, or is in any way not an error, then the return value is + * undefined and should not be relied upon. + */ +PRISM_EXPORTED_FUNCTION pm_error_level_t pm_diagnostic_error_level(const pm_diagnostic_t *diagnostic); + +/** + * Get the warning level associated with the given diagnostic. + * + * @param diagnostic The diagnostic to get the warning level of. + * @returns The warning level of the given diagnostic. If the diagnostic was an + * error, or is in any way not a warning, then the return value is + * undefined and should not be relied upon. + */ +PRISM_EXPORTED_FUNCTION pm_warning_level_t pm_diagnostic_warning_level(const pm_diagnostic_t *diagnostic); + +/* An opaque pointer to an iterator that can be used to iterate over a set of + * diagnostics associated with a parser. */ +typedef struct pm_diagnostics_iter_t pm_diagnostics_iter_t; + +/** + * Returns the number of diagnostics associated with the diagnostics iterator. + * + * @param iter the iterator to get the number of diagnostics from + * @return the number of diagnostics associated with the diagnostics iterator + * + * \public \memberof pm_diagnostics_iter_t + */ +PRISM_EXPORTED_FUNCTION size_t pm_diagnostics_iter_size(const pm_diagnostics_iter_t *iter); + +/** + * Returns the next diagnostic in the iteration, or NULL if there are no more + * diagnostics. + * + * @param iter the iterator to get the next diagnostic from + * @return the next diagnostic in the iteration, or NULL if there are no more + * diagnostics. + * + * \public \memberof pm_diagnostics_iter_t + */ +PRISM_EXPORTED_FUNCTION const pm_diagnostic_t * pm_diagnostics_iter_next(pm_diagnostics_iter_t *iter); + +/** + * Frees the memory associated with the given diagnostics iterator. + * + * @param iter the iterator to free + * + * \public \memberof pm_diagnostics_iter_t + */ +PRISM_EXPORTED_FUNCTION void pm_diagnostics_iter_free(pm_diagnostics_iter_t *iter); + +#endif diff --git a/include/prism/internal/diagnostic.h b/include/prism/internal/diagnostic.h deleted file mode 100644 index 3e58c2ad2e..0000000000 --- a/include/prism/internal/diagnostic.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @file internal/diagnostic.h - * - * A list of diagnostics generated during parsing. - */ -#ifndef PRISM_INTERNAL_DIAGNOSTIC_H -#define PRISM_INTERNAL_DIAGNOSTIC_H - -#include "prism/arena.h" -#include "prism/diagnostic.h" - -/** - * Append a diagnostic to the given list of diagnostics that is using shared - * memory for its message. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param start The source offset of the start of the diagnostic. - * @param length The length of the diagnostic. - * @param diag_id The diagnostic ID. - */ -void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id); - -/** - * Append a diagnostic to the given list of diagnostics that is using a format - * string for its message. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param start The source offset of the start of the diagnostic. - * @param length The length of the diagnostic. - * @param diag_id The diagnostic ID. - * @param ... The arguments to the format string for the message. - */ -void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); - -#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index b1726b4975..c00743cbe1 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -8,6 +8,7 @@ #include "prism/ast.h" #include "prism/comments.h" +#include "prism/diagnostic.h" #include "prism/line_offset_list.h" #include "prism/list.h" @@ -107,22 +108,6 @@ PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser); -/** - * Returns the errors that are associated with the given parser. - * - * @param parser the parser whose errors we want to get - * @return the errors that are associated with the given parser - */ -PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_errors(const pm_parser_t *parser); - -/** - * Returns the warnings that are associated with the given parser. - * - * @param parser the parser whose warnings we want to get - * @return the warnings that are associated with the given parser - */ -PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_warnings(const pm_parser_t *parser); - /** * Returns the magic comments that are associated with the given parser. * @@ -191,4 +176,32 @@ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_parser_comments(const pm_parser_t *parser); +/** + * Returns an iterator that knows how to iterate over the errors that are + * associated with the given parser. + * + * @param parser the parser whose errors we want to get + * @return the iterator that knows how to iterate over the errors that are + * associated with the given parser. It is the responsibility of the caller + * to free the memory associated with the iterator through + * pm_diagnostics_iter_free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_diagnostics_iter_t * pm_parser_errors(const pm_parser_t *parser); + +/** + * Returns an iterator that knows how to iterate over the warnings that are + * associated with the given parser. + * + * @param parser the parser whose warnings we want to get + * @return the iterator that knows how to iterate over the warnings that are + * associated with the given parser. It is the responsibility of the caller + * to free the memory associated with the iterator through + * pm_diagnostics_iter_free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_diagnostics_iter_t * pm_parser_warnings(const pm_parser_t *parser); + #endif diff --git a/src/parser.c b/src/parser.c index 7447b00f24..6900b228e7 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2,6 +2,7 @@ #include "prism/internal/allocator.h" #include "prism/internal/comments.h" +#include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" #include @@ -67,22 +68,6 @@ pm_parser_encoding_name(const pm_parser_t *parser) { return parser->encoding->name; } -/** - * Returns the errors that are associated with the given parser. - */ -const pm_list_t * -pm_parser_errors(const pm_parser_t *parser) { - return &parser->error_list; -} - -/** - * Returns the warnings that are associated with the given parser. - */ -const pm_list_t * -pm_parser_warnings(const pm_parser_t *parser) { - return &parser->warning_list; -} - /** * Returns the magic comments that are associated with the given parser. */ @@ -150,3 +135,27 @@ pm_parser_comments(const pm_parser_t *parser) { iter->current = parser->comment_list.head; return iter; } + +/** + * Returns an iterator that knows how to iterate over the errors that are + * associated with the given parser. + */ +pm_diagnostics_iter_t * +pm_parser_errors(const pm_parser_t *parser) { + pm_diagnostics_iter_t *iter = (pm_diagnostics_iter_t *) xmalloc(sizeof(pm_diagnostics_iter_t)); + iter->size = parser->error_list.size; + iter->current = parser->error_list.head; + return iter; +} + +/** + * Returns an iterator that knows how to iterate over the warnings that are + * associated with the given parser. + */ +pm_diagnostics_iter_t * +pm_parser_warnings(const pm_parser_t *parser) { + pm_diagnostics_iter_t *iter = (pm_diagnostics_iter_t *) xmalloc(sizeof(pm_diagnostics_iter_t)); + iter->size = parser->warning_list.size; + iter->current = parser->warning_list.head; + return iter; +} diff --git a/templates/include/prism/diagnostic.h.erb b/templates/include/prism/diagnostic.h.erb deleted file mode 100644 index 89ef49a2d4..0000000000 --- a/templates/include/prism/diagnostic.h.erb +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file diagnostic.h - * - * A list of diagnostics generated during parsing. - */ -#ifndef PRISM_DIAGNOSTIC_H -#define PRISM_DIAGNOSTIC_H - -#include "prism/compiler/exported.h" - -#include "prism/ast.h" -#include "prism/list.h" - -/** - * The diagnostic IDs of all of the diagnostics, used to communicate the types - * of errors between the parser and the user. - */ -typedef enum { - // These are the error diagnostics. - <%- errors.each do |error| -%> - PM_ERR_<%= error.name %>, - <%- end -%> - - // These are the warning diagnostics. - <%- warnings.each do |warning| -%> - PM_WARN_<%= warning.name %>, - <%- end -%> -} pm_diagnostic_id_t; - -/** - * This struct represents a diagnostic generated during parsing. - * - * @extends pm_list_node_t - */ -typedef struct { - /** The embedded base node. */ - pm_list_node_t node; - - /** The location of the diagnostic in the source. */ - pm_location_t location; - - /** The ID of the diagnostic. */ - pm_diagnostic_id_t diag_id; - - /** The message associated with the diagnostic. */ - const char *message; - - /** - * The level of the diagnostic, see `pm_error_level_t` and - * `pm_warning_level_t` for possible values. - */ - uint8_t level; -} pm_diagnostic_t; - -/** - * The levels of errors generated during parsing. - */ -typedef enum { - /** For errors that should raise a syntax error. */ - PM_ERROR_LEVEL_SYNTAX = 0, - - /** For errors that should raise an argument error. */ - PM_ERROR_LEVEL_ARGUMENT = 1, - - /** For errors that should raise a load error. */ - PM_ERROR_LEVEL_LOAD = 2 -} pm_error_level_t; - -/** - * The levels of warnings generated during parsing. - */ -typedef enum { - /** For warnings which should be emitted if $VERBOSE != nil. */ - PM_WARNING_LEVEL_DEFAULT = 0, - - /** For warnings which should be emitted if $VERBOSE == true. */ - PM_WARNING_LEVEL_VERBOSE = 1 -} pm_warning_level_t; - -/** - * Get the human-readable name of the given diagnostic ID. - * - * @param diag_id The diagnostic ID to get the name of. - * @returns The human-readable name of the given diagnostic ID. - */ -PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_id_str(pm_diagnostic_id_t diag_id); - -#endif diff --git a/templates/include/prism/internal/diagnostic.h.erb b/templates/include/prism/internal/diagnostic.h.erb new file mode 100644 index 0000000000..f15e3936a1 --- /dev/null +++ b/templates/include/prism/internal/diagnostic.h.erb @@ -0,0 +1,89 @@ +/** + * @file internal/diagnostic.h + * + * A list of diagnostics generated during parsing. + */ +#ifndef PRISM_INTERNAL_DIAGNOSTIC_H +#define PRISM_INTERNAL_DIAGNOSTIC_H + +#include "prism/arena.h" +#include "prism/diagnostic.h" +#include "prism/list.h" + +/** + * The diagnostic IDs of all of the diagnostics, used to communicate the types + * of errors between the parser and the user. + */ +typedef enum { + /* These are the error diagnostics. */ + <%- errors.each do |error| -%> + PM_ERR_<%= error.name %>, + <%- end -%> + + /* These are the warning diagnostics. */ + <%- warnings.each do |warning| -%> + PM_WARN_<%= warning.name %>, + <%- end -%> +} pm_diagnostic_id_t; + +/** + * This struct represents a diagnostic generated during parsing. + */ +struct pm_diagnostic_t { + /** The embedded base node. */ + pm_list_node_t node; + + /** The location of the diagnostic in the source. */ + pm_location_t location; + + /** The ID of the diagnostic. */ + pm_diagnostic_id_t diag_id; + + /** The message associated with the diagnostic. */ + const char *message; + + /** + * The level of the diagnostic, see `pm_error_level_t` and + * `pm_warning_level_t` for possible values. + */ + uint8_t level; +}; + +/** + * Append a diagnostic to the given list of diagnostics that is using shared + * memory for its message. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param start The source offset of the start of the diagnostic. + * @param length The length of the diagnostic. + * @param diag_id The diagnostic ID. + */ +void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id); + +/** + * Append a diagnostic to the given list of diagnostics that is using a format + * string for its message. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param start The source offset of the start of the diagnostic. + * @param length The length of the diagnostic. + * @param diag_id The diagnostic ID. + * @param ... The arguments to the format string for the message. + */ +void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); + +/** + * A struct used as an opaque pointer for the client to iterate through the + * diagnostics found while parsing. + */ +struct pm_diagnostics_iter_t { + /** The number of diagnostics in the list. */ + size_t size; + + /** The current node in the list. */ + const pm_list_node_t *current; +}; + +#endif diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index 996599b0e5..a4aba2e586 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -1,6 +1,8 @@ -#include "prism/diagnostic.h" +#include "prism/internal/diagnostic.h" #include "prism/compiler/inline.h" + +#include "prism/internal/allocator.h" #include "prism/internal/arena.h" #include "prism/internal/list.h" @@ -8,6 +10,7 @@ #include #include #include +#include #define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %> @@ -425,8 +428,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { /** * Get the human-readable name of the given diagnostic ID. */ -const char * -pm_diagnostic_id_str(pm_diagnostic_id_t diag_id) { +static const char * +pm_diagnostic_id_name(pm_diagnostic_id_t diag_id) { switch (diag_id) { <%- errors.each do |error| -%> case PM_ERR_<%= error.name %>: return "<%= error.name.downcase %>"; @@ -441,7 +444,7 @@ pm_diagnostic_id_str(pm_diagnostic_id_t diag_id) { } static PRISM_INLINE const char * -pm_diagnostic_message(pm_diagnostic_id_t diag_id) { +pm_diagnostic_id_message(pm_diagnostic_id_t diag_id) { assert(diag_id < PM_DIAGNOSTIC_ID_MAX); const char *message = diagnostic_messages[diag_id].message; @@ -451,12 +454,52 @@ pm_diagnostic_message(pm_diagnostic_id_t diag_id) { } static PRISM_INLINE uint8_t -pm_diagnostic_level(pm_diagnostic_id_t diag_id) { +pm_diagnostic_id_level(pm_diagnostic_id_t diag_id) { assert(diag_id < PM_DIAGNOSTIC_ID_MAX); return (uint8_t) diagnostic_messages[diag_id].level; } +/** + * Get the type of the given diagnostic. + */ +const char * +pm_diagnostic_type(const pm_diagnostic_t *diagnostic) { + return pm_diagnostic_id_name(diagnostic->diag_id); +} + +/** + * Get the location of the given diagnostic. + */ +pm_location_t +pm_diagnostic_location(const pm_diagnostic_t *diagnostic) { + return diagnostic->location; +} + +/** + * Get the message of the given diagnostic. + */ +const char * +pm_diagnostic_message(const pm_diagnostic_t *diagnostic) { + return diagnostic->message; +} + +/** + * Get the error level associated with the given diagnostic. + */ +pm_error_level_t +pm_diagnostic_error_level(const pm_diagnostic_t *diagnostic) { + return (pm_error_level_t) pm_diagnostic_id_level(diagnostic->diag_id); +} + +/** + * Get the warning level associated with the given diagnostic. + */ +pm_warning_level_t +pm_diagnostic_warning_level(const pm_diagnostic_t *diagnostic) { + return (pm_warning_level_t) pm_diagnostic_id_level(diagnostic->diag_id); +} + /** * Append an error to the given list of diagnostic. */ @@ -467,8 +510,8 @@ pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, ui *diagnostic = (pm_diagnostic_t) { .location = { .start = start, .length = length }, .diag_id = diag_id, - .message = pm_diagnostic_message(diag_id), - .level = pm_diagnostic_level(diag_id) + .message = pm_diagnostic_id_message(diag_id), + .level = pm_diagnostic_id_level(diag_id) }; pm_list_append(list, (pm_list_node_t *) diagnostic); @@ -483,7 +526,7 @@ pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t st va_list arguments; va_start(arguments, diag_id); - const char *format = pm_diagnostic_message(diag_id); + const char *format = pm_diagnostic_id_message(diag_id); int result = vsnprintf(NULL, 0, format, arguments); va_end(arguments); @@ -504,9 +547,36 @@ pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t st .location = { .start = start, .length = length }, .diag_id = diag_id, .message = message, - .level = pm_diagnostic_level(diag_id) + .level = pm_diagnostic_id_level(diag_id) }; pm_list_append(list, (pm_list_node_t *) diagnostic); } +/** + * Returns the number of diagnostics associated with the diagnostics iterator. + */ +size_t +pm_diagnostics_iter_size(const pm_diagnostics_iter_t *iter) { + return iter->size; +} + +/** + * Returns the next diagnostic in the iteration, or NULL if there are no more + * diagnostics. + */ +const pm_diagnostic_t * +pm_diagnostics_iter_next(pm_diagnostics_iter_t *iter) { + if (iter->current == NULL) return NULL; + const pm_diagnostic_t *diagnostic = (const pm_diagnostic_t *) iter->current; + iter->current = iter->current->next; + return diagnostic; +} + +/** + * Frees the memory associated with the given diagnostics iterator. + */ +void +pm_diagnostics_iter_free(pm_diagnostics_iter_t *iter) { + xfree(iter); +} diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 7edb297501..782e09219d 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -9,6 +9,7 @@ #include "prism/internal/buffer.h" #include "prism/internal/comments.h" +#include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" @@ -16,7 +17,6 @@ #include "prism.h" #include "prism/ast.h" -#include "prism/diagnostic.h" #include "prism/line_offset_list.h" #include diff --git a/templates/template.rb b/templates/template.rb index 70fa17c83d..b3ccf373d3 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -684,8 +684,8 @@ def locals TEMPLATES = [ "ext/prism/api_node.c", "include/prism/ast.h", - "include/prism/diagnostic.h", "include/prism/node_new.h", + "include/prism/internal/diagnostic.h", "javascript/src/deserialize.js", "javascript/src/nodes.js", "javascript/src/visitor.js", From f2e8648522b099e1eefbb59e639b9f5885424378 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 11:31:44 -0400 Subject: [PATCH 207/289] Move magic comments entirely internal --- ext/prism/extension.c | 17 ++++--- include/prism/internal/magic_comments.h | 40 +++++++++++++++ include/prism/magic_comments.h | 67 +++++++++++++++++++++++++ include/prism/parser.h | 40 ++++++--------- src/magic_comments.c | 51 +++++++++++++++++++ src/parser.c | 21 +++++--- src/prism.c | 1 + templates/src/serialize.c.erb | 1 + 8 files changed, 199 insertions(+), 39 deletions(-) create mode 100644 include/prism/internal/magic_comments.h create mode 100644 include/prism/magic_comments.h create mode 100644 src/magic_comments.c diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 1980e44d89..af67bee388 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -513,8 +513,12 @@ parser_comments(const pm_parser_t *parser, VALUE source, bool freeze) { */ static inline VALUE parser_magic_comment(VALUE source, bool freeze, const pm_magic_comment_t *magic_comment) { - VALUE key_loc = parser_location(source, freeze, magic_comment->key.start, magic_comment->key.length); - VALUE value_loc = parser_location(source, freeze, magic_comment->value.start, magic_comment->value.length); + pm_location_t key = pm_magic_comment_key(magic_comment); + pm_location_t value = pm_magic_comment_value(magic_comment); + + VALUE key_loc = parser_location(source, freeze, key.start, key.length); + VALUE value_loc = parser_location(source, freeze, value.start, value.length); + VALUE argv[] = { key_loc, value_loc }; return rb_class_new_instance_freeze(2, argv, rb_cPrismMagicComment, freeze); } @@ -524,18 +528,19 @@ parser_magic_comment(VALUE source, bool freeze, const pm_magic_comment_t *magic_ */ static VALUE parser_magic_comments(const pm_parser_t *parser, VALUE source, bool freeze) { - const pm_list_t *magic_comments_list = pm_parser_magic_comments(parser); - VALUE magic_comments = rb_ary_new_capa(magic_comments_list->size); + pm_magic_comments_iter_t *iter = pm_parser_magic_comments(parser); + VALUE magic_comments = rb_ary_new_capa(pm_magic_comments_iter_size(iter)); for ( - const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) magic_comments_list->head; + const pm_magic_comment_t *magic_comment = pm_magic_comments_iter_next(iter); magic_comment != NULL; - magic_comment = (const pm_magic_comment_t *) magic_comment->node.next + magic_comment = pm_magic_comments_iter_next(iter) ) { VALUE value = parser_magic_comment(source, freeze, magic_comment); rb_ary_push(magic_comments, value); } + pm_magic_comments_iter_free(iter); if (freeze) rb_obj_freeze(magic_comments); return magic_comments; } diff --git a/include/prism/internal/magic_comments.h b/include/prism/internal/magic_comments.h new file mode 100644 index 0000000000..499f8e5e09 --- /dev/null +++ b/include/prism/internal/magic_comments.h @@ -0,0 +1,40 @@ +/** + * @file internal/magic_comments.h + */ +#ifndef PRISM_INTERNAL_MAGIC_COMMENTS_H +#define PRISM_INTERNAL_MAGIC_COMMENTS_H + +#include "prism/magic_comments.h" + +#include "prism/list.h" + +/** + * This is a node in the linked list of magic comments that we've found while + * parsing. + * + * @extends pm_list_node_t + */ +struct pm_magic_comment_t { + /** The embedded base node. */ + pm_list_node_t node; + + /** The key of the magic comment. */ + pm_location_t key; + + /** The value of the magic comment. */ + pm_location_t value; +}; + +/** + * A struct used as an opaque pointer for the client to iterate through the + * magic comments found while parsing. + */ +struct pm_magic_comments_iter_t { + /** The number of magic comments in the list. */ + size_t size; + + /** The current node in the list. */ + const pm_list_node_t *current; +}; + +#endif diff --git a/include/prism/magic_comments.h b/include/prism/magic_comments.h new file mode 100644 index 0000000000..10f9cfa32d --- /dev/null +++ b/include/prism/magic_comments.h @@ -0,0 +1,67 @@ +/** + * @file magic_comments.h + */ +#ifndef PRISM_MAGIC_COMMENTS_H +#define PRISM_MAGIC_COMMENTS_H + +#include "prism/compiler/exported.h" + +#include "prism/ast.h" + +#include + +/** An opaque pointer to a magic comment found while parsing. */ +typedef struct pm_magic_comment_t pm_magic_comment_t; + +/** + * Returns the location of the key associated with the given magic comment. + * + * @param comment the magic comment whose key location we want to get + * @return the location of the key associated with the given magic comment + */ +PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_key(const pm_magic_comment_t *comment); + +/** + * Returns the location of the value associated with the given magic comment. + * + * @param comment the magic comment whose value location we want to get + * @return the location of the value associated with the given magic comment + */ +PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_value(const pm_magic_comment_t *comment); + +/* An opaque pointer to an iterator that can be used to iterate over the + * magic comments associated with a parser. */ +typedef struct pm_magic_comments_iter_t pm_magic_comments_iter_t; + +/** + * Returns the number of magic comments associated with the magic comments iterator. + * + * @param iter the iterator to get the number of magic comments from + * @return the number of magic comments associated with the magic comments iterator + * + * \public \memberof pm_magic_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION size_t pm_magic_comments_iter_size(const pm_magic_comments_iter_t *iter); + +/** + * Returns the next magic comment in the iteration, or NULL if there are no more + * magic comments. + * + * @param iter the iterator to get the next magic comment from + * @return the next magic comment in the iteration, or NULL if there are no more + * magic comments. + * + * \public \memberof pm_magic_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION const pm_magic_comment_t * pm_magic_comments_iter_next(pm_magic_comments_iter_t *iter); + +/** + * Frees the memory associated with the given magic comments iterator. + * + * @param iter the iterator to free + * + * \public \memberof pm_magic_comments_iter_t + */ +PRISM_EXPORTED_FUNCTION void pm_magic_comments_iter_free(pm_magic_comments_iter_t *iter); + +#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index c00743cbe1..bc1191797d 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -11,29 +11,13 @@ #include "prism/diagnostic.h" #include "prism/line_offset_list.h" #include "prism/list.h" +#include "prism/magic_comments.h" /** * The parser used to parse Ruby source. */ typedef struct pm_parser_t pm_parser_t; -/** - * This is a node in the linked list of magic comments that we've found while - * parsing. - * - * @extends pm_list_node_t - */ -typedef struct { - /** The embedded base node. */ - pm_list_node_t node; - - /** The key of the magic comment. */ - pm_location_t key; - - /** The value of the magic comment. */ - pm_location_t value; -} pm_magic_comment_t; - /** * When the encoding that is being used to parse the source is changed by prism, * we provide the ability here to call out to a user-defined function. @@ -108,14 +92,6 @@ PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser); -/** - * Returns the magic comments that are associated with the given parser. - * - * @param parser the parser whose magic comments we want to get - * @return the magic comments that are associated with the given parser - */ -PRISM_EXPORTED_FUNCTION const pm_list_t * pm_parser_magic_comments(const pm_parser_t *parser); - /** * Returns the line offsets that are associated with the given parser. * @@ -176,6 +152,20 @@ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_parser_comments(const pm_parser_t *parser); +/** + * Returns an iterator that knows how to iterate over the magic comments that + * are associated with the given parser. + * + * @param parser the parser whose magic comments we want to get + * @return the iterator that knows how to iterate over the magic comments that are + * associated with the given parser. It is the responsibility of the caller + * to free the memory associated with the iterator through + * pm_magic_comments_iter_free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_magic_comments_iter_t * pm_parser_magic_comments(const pm_parser_t *parser); + /** * Returns an iterator that knows how to iterate over the errors that are * associated with the given parser. diff --git a/src/magic_comments.c b/src/magic_comments.c new file mode 100644 index 0000000000..fc570868a6 --- /dev/null +++ b/src/magic_comments.c @@ -0,0 +1,51 @@ +#include "prism/internal/magic_comments.h" + +#include "prism/internal/allocator.h" +#include "prism/internal/parser.h" + +#include + +/** + * Returns the location associated with the given magic comment key. + */ +pm_location_t +pm_magic_comment_key(const pm_magic_comment_t *magic_comment) { + return magic_comment->key; +} + +/** + * Returns the location associated with the given magic comment value. + */ +pm_location_t +pm_magic_comment_value(const pm_magic_comment_t *magic_comment) { + return magic_comment->value; +} + +/** + * Returns the number of magic comments associated with the magic comment + * iterator. + */ +size_t +pm_magic_comments_iter_size(const pm_magic_comments_iter_t *iter) { + return iter->size; +} + +/** + * Returns the next magic comment in the iteration, or NULL if there are no more + * magic comments. + */ +const pm_magic_comment_t * +pm_magic_comments_iter_next(pm_magic_comments_iter_t *iter) { + if (iter->current == NULL) return NULL; + const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) iter->current; + iter->current = iter->current->next; + return magic_comment; +} + +/** + * Frees the memory associated with the given magic comments iterator. + */ +void +pm_magic_comments_iter_free(pm_magic_comments_iter_t *iter) { + xfree(iter); +} diff --git a/src/parser.c b/src/parser.c index 6900b228e7..84d8dff992 100644 --- a/src/parser.c +++ b/src/parser.c @@ -4,6 +4,7 @@ #include "prism/internal/comments.h" #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" +#include "prism/internal/magic_comments.h" #include @@ -68,14 +69,6 @@ pm_parser_encoding_name(const pm_parser_t *parser) { return parser->encoding->name; } -/** - * Returns the magic comments that are associated with the given parser. - */ -const pm_list_t * -pm_parser_magic_comments(const pm_parser_t *parser) { - return &parser->magic_comment_list; -} - /** * Returns the line offsets that are associated with the given parser. * @@ -136,6 +129,18 @@ pm_parser_comments(const pm_parser_t *parser) { return iter; } +/** + * Returns an iterator that knows how to iterate over the magic comments that + * are associated with the given parser. + */ +pm_magic_comments_iter_t * +pm_parser_magic_comments(const pm_parser_t *parser) { + pm_magic_comments_iter_t *iter = (pm_magic_comments_iter_t *) xmalloc(sizeof(pm_magic_comments_iter_t)); + iter->size = parser->magic_comment_list.size; + iter->current = parser->magic_comment_list.head; + return iter; +} + /** * Returns an iterator that knows how to iterate over the errors that are * associated with the given parser. diff --git a/src/prism.c b/src/prism.c index f948473db8..47cfdf6ea4 100644 --- a/src/prism.c +++ b/src/prism.c @@ -17,6 +17,7 @@ #include "prism/internal/isinf.h" #include "prism/internal/line_offset_list.h" #include "prism/internal/list.h" +#include "prism/internal/magic_comments.h" #include "prism/internal/memchr.h" #include "prism/internal/node.h" #include "prism/internal/options.h" diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 782e09219d..2d7bbfcb93 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -12,6 +12,7 @@ #include "prism/internal/diagnostic.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" +#include "prism/internal/magic_comments.h" #include "prism/internal/options.h" #include "prism/internal/parser.h" From bbc2023d0bfa001cc75e6a537dba954bcb35bcf4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 11:37:42 -0400 Subject: [PATCH 208/289] Fix up build --- include/prism/internal/comments.h | 2 +- include/prism/internal/list.h | 52 +++++++++++++++- include/prism/internal/magic_comments.h | 2 +- include/prism/internal/parser.h | 2 +- include/prism/internal/serialize.h | 2 +- include/prism/list.h | 61 ------------------- include/prism/parser.h | 1 - prism.gemspec | 9 ++- src/prism.c | 1 + .../include/prism/internal/diagnostic.h.erb | 3 +- templates/src/serialize.c.erb | 6 +- 11 files changed, 69 insertions(+), 72 deletions(-) delete mode 100644 include/prism/list.h diff --git a/include/prism/internal/comments.h b/include/prism/internal/comments.h index c7adf52464..8b1009daf6 100644 --- a/include/prism/internal/comments.h +++ b/include/prism/internal/comments.h @@ -6,7 +6,7 @@ #include "prism/comments.h" -#include "prism/list.h" +#include "prism/internal/list.h" /** * A comment found while parsing. diff --git a/include/prism/internal/list.h b/include/prism/internal/list.h index f770b1dd2d..9a73e6bd3f 100644 --- a/include/prism/internal/list.h +++ b/include/prism/internal/list.h @@ -6,7 +6,57 @@ #ifndef PRISM_INTERNAL_LIST_H #define PRISM_INTERNAL_LIST_H -#include "prism/list.h" +#include + +/** + * This struct represents an abstract linked list that provides common + * functionality. It is meant to be used any time a linked list is necessary to + * store data. + * + * The linked list itself operates off a set of pointers. Because the pointers + * are not necessarily sequential, they can be of any size. We use this fact to + * allow the consumer of this linked list to extend the node struct to include + * any data they want. This is done by using the pm_list_node_t as the first + * member of the struct. + * + * For example, if we want to store a list of integers, we can do the following: + * + * ```c + * typedef struct { + * pm_list_node_t node; + * int value; + * } pm_int_node_t; + * + * pm_list_t list = { 0 }; + * pm_int_node_t *node = xmalloc(sizeof(pm_int_node_t)); + * node->value = 5; + * + * pm_list_append(&list, &node->node); + * ``` + * + * The pm_list_t struct is used to represent the overall linked list. It + * contains a pointer to the head and tail of the list. This allows for easy + * iteration and appending of new nodes. + */ +typedef struct pm_list_node { + /** A pointer to the next node in the list. */ + struct pm_list_node *next; +} pm_list_node_t; + +/** + * This represents the overall linked list. It keeps a pointer to the head and + * tail so that iteration is easy and pushing new nodes is easy. + */ +typedef struct { + /** The size of the list. */ + size_t size; + + /** A pointer to the head of the list. */ + pm_list_node_t *head; + + /** A pointer to the tail of the list. */ + pm_list_node_t *tail; +} pm_list_t; /** * Returns the size of the list. diff --git a/include/prism/internal/magic_comments.h b/include/prism/internal/magic_comments.h index 499f8e5e09..eb4154928d 100644 --- a/include/prism/internal/magic_comments.h +++ b/include/prism/internal/magic_comments.h @@ -6,7 +6,7 @@ #include "prism/magic_comments.h" -#include "prism/list.h" +#include "prism/internal/list.h" /** * This is a node in the linked list of magic comments that we've found while diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index f8baf49cdb..f6618f67ed 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -9,13 +9,13 @@ #include "prism/compiler/accel.h" #include "prism/internal/encoding.h" +#include "prism/internal/list.h" #include "prism/internal/options.h" #include "prism/internal/static_literals.h" #include "prism/arena.h" #include "prism/ast.h" #include "prism/line_offset_list.h" -#include "prism/list.h" #include "prism/parser.h" #include diff --git a/include/prism/internal/serialize.h b/include/prism/internal/serialize.h index a67ebd1a18..c691a1fed9 100644 --- a/include/prism/internal/serialize.h +++ b/include/prism/internal/serialize.h @@ -5,11 +5,11 @@ #define PRISM_INTERNAL_SERIALIZE_H #include "prism/internal/encoding.h" +#include "prism/internal/list.h" #include "prism/ast.h" #include "prism/buffer.h" #include "prism/excludes.h" -#include "prism/list.h" #include "prism/parser.h" /* We optionally support serializing to a binary string. For systems that do not diff --git a/include/prism/list.h b/include/prism/list.h deleted file mode 100644 index c9fb18278c..0000000000 --- a/include/prism/list.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file list.h - * - * An abstract linked list. - */ -#ifndef PRISM_LIST_H -#define PRISM_LIST_H - -#include - -/** - * This struct represents an abstract linked list that provides common - * functionality. It is meant to be used any time a linked list is necessary to - * store data. - * - * The linked list itself operates off a set of pointers. Because the pointers - * are not necessarily sequential, they can be of any size. We use this fact to - * allow the consumer of this linked list to extend the node struct to include - * any data they want. This is done by using the pm_list_node_t as the first - * member of the struct. - * - * For example, if we want to store a list of integers, we can do the following: - * - * ```c - * typedef struct { - * pm_list_node_t node; - * int value; - * } pm_int_node_t; - * - * pm_list_t list = { 0 }; - * pm_int_node_t *node = xmalloc(sizeof(pm_int_node_t)); - * node->value = 5; - * - * pm_list_append(&list, &node->node); - * ``` - * - * The pm_list_t struct is used to represent the overall linked list. It - * contains a pointer to the head and tail of the list. This allows for easy - * iteration and appending of new nodes. - */ -typedef struct pm_list_node { - /** A pointer to the next node in the list. */ - struct pm_list_node *next; -} pm_list_node_t; - -/** - * This represents the overall linked list. It keeps a pointer to the head and - * tail so that iteration is easy and pushing new nodes is easy. - */ -typedef struct { - /** The size of the list. */ - size_t size; - - /** A pointer to the head of the list. */ - pm_list_node_t *head; - - /** A pointer to the tail of the list. */ - pm_list_node_t *tail; -} pm_list_t; - -#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index bc1191797d..9e94ad1631 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -10,7 +10,6 @@ #include "prism/comments.h" #include "prism/diagnostic.h" #include "prism/line_offset_list.h" -#include "prism/list.h" #include "prism/magic_comments.h" /** diff --git a/prism.gemspec b/prism.gemspec index 70e5aefe1b..ca21b792cc 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -62,6 +62,7 @@ Gem::Specification.new do |spec| "include/prism/internal/bit.h", "include/prism/internal/buffer.h", "include/prism/internal/char.h", + "include/prism/internal/comments.h", "include/prism/internal/constant_pool.h", "include/prism/internal/diagnostic.h", "include/prism/internal/encoding.h", @@ -69,10 +70,13 @@ Gem::Specification.new do |spec| "include/prism/internal/isinf.h", "include/prism/internal/line_offset_list.h", "include/prism/internal/list.h", + "include/prism/internal/magic_comments.h", "include/prism/internal/memchr.h", "include/prism/internal/node.h", "include/prism/internal/options.h", + "include/prism/internal/parser.h", "include/prism/internal/regexp.h", + "include/prism/internal/serialize.h", "include/prism/internal/static_literals.h", "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", @@ -80,12 +84,13 @@ Gem::Specification.new do |spec| "include/prism/arena.h", "include/prism/ast.h", "include/prism/buffer.h", + "include/prism/comments.h", "include/prism/constant_pool.h", "include/prism/diagnostic.h", "include/prism/excludes.h", "include/prism/integer.h", "include/prism/line_offset_list.h", - "include/prism/list.h", + "include/prism/magic_comments.h", "include/prism/node.h", "include/prism/node_new.h", "include/prism/options.h", @@ -185,12 +190,14 @@ Gem::Specification.new do |spec| "src/arena.c", "src/buffer.c", "src/char.c", + "src/comments.c", "src/constant_pool.c", "src/diagnostic.c", "src/encoding.c", "src/integer.c", "src/line_offset_list.c", "src/list.c", + "src/magic_comments.c", "src/memchr.c", "src/node.c", "src/options.c", diff --git a/src/prism.c b/src/prism.c index 47cfdf6ea4..06d3dc42b9 100644 --- a/src/prism.c +++ b/src/prism.c @@ -29,6 +29,7 @@ #include "prism/internal/strncasecmp.h" #include "prism/internal/strpbrk.h" +#include "prism/excludes.h" #include "prism/node_new.h" #include diff --git a/templates/include/prism/internal/diagnostic.h.erb b/templates/include/prism/internal/diagnostic.h.erb index f15e3936a1..ca294e3972 100644 --- a/templates/include/prism/internal/diagnostic.h.erb +++ b/templates/include/prism/internal/diagnostic.h.erb @@ -6,9 +6,10 @@ #ifndef PRISM_INTERNAL_DIAGNOSTIC_H #define PRISM_INTERNAL_DIAGNOSTIC_H +#include "prism/internal/list.h" + #include "prism/arena.h" #include "prism/diagnostic.h" -#include "prism/list.h" /** * The diagnostic IDs of all of the diagnostics, used to communicate the types diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 2d7bbfcb93..405332e339 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -1,8 +1,8 @@ #include "prism/excludes.h" -// We optionally support serializing to a binary string. For systems that don't -// want or need this functionality, it can be turned off with the -// PRISM_EXCLUDE_SERIALIZATION define. +/* We optionally support serializing to a binary string. For systems that do not + * want or need this functionality, it can be turned off with the + * PRISM_EXCLUDE_SERIALIZATION define. */ #ifndef PRISM_EXCLUDE_SERIALIZATION #include "prism/compiler/inline.h" From e8606f7022b366b1c093abb5193bfd6c2a7fa017 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 11:39:17 -0400 Subject: [PATCH 209/289] Do not define a shim if the define is set --- include/prism/prettyprint.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/prism/prettyprint.h b/include/prism/prettyprint.h index b59cfe1460..0c81618e7f 100644 --- a/include/prism/prettyprint.h +++ b/include/prism/prettyprint.h @@ -8,11 +8,7 @@ #include "prism/excludes.h" -#ifdef PRISM_EXCLUDE_PRETTYPRINT - -#define pm_prettyprint(output_buffer_, parser_, node_) - -#else +#ifndef PRISM_EXCLUDE_PRETTYPRINT #include "prism/compiler/exported.h" From e0d17eb9e787036c91690962332f35a08b2d3a3e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 12:02:52 -0400 Subject: [PATCH 210/289] Remove iterators, just use callbacks --- ext/prism/extension.c | 203 ++++++++++-------- include/prism/comments.h | 35 --- include/prism/internal/comments.h | 12 -- include/prism/internal/magic_comments.h | 12 -- include/prism/parser.h | 116 ++++++---- src/comments.c | 28 --- src/magic_comments.c | 29 --- src/parser.c | 104 ++++++--- .../include/prism/internal/diagnostic.h.erb | 12 -- 9 files changed, 264 insertions(+), 287 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index af67bee388..27cc3839ed 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -485,26 +485,30 @@ parser_comment(VALUE source, bool freeze, const pm_comment_t *comment) { return rb_class_new_instance_freeze(1, argv, type, freeze); } +typedef struct { + VALUE comments; + VALUE source; + bool freeze; +} parser_comments_each_data_t; + +static void +parser_comments_each(const pm_comment_t *comment, void *data) { + parser_comments_each_data_t *each_data = (parser_comments_each_data_t *) data; + VALUE value = parser_comment(each_data->source, each_data->freeze, comment); + rb_ary_push(each_data->comments, value); +} + /** * Extract the comments out of the parser into an array. */ static VALUE parser_comments(const pm_parser_t *parser, VALUE source, bool freeze) { - pm_comments_iter_t *comments_iter = pm_parser_comments(parser); - VALUE comments = rb_ary_new_capa(pm_comments_iter_size(comments_iter)); - - for ( - const pm_comment_t *comment = pm_comments_iter_next(comments_iter); - comment != NULL; - comment = pm_comments_iter_next(comments_iter) - ) { - VALUE value = parser_comment(source, freeze, comment); - rb_ary_push(comments, value); - } + VALUE comments = rb_ary_new_capa(pm_parser_comments_size(parser)); - pm_comments_iter_free(comments_iter); - if (freeze) rb_obj_freeze(comments); + parser_comments_each_data_t each_data = { comments, source, freeze }; + pm_parser_comments_each(parser, parser_comments_each, &each_data); + if (freeze) rb_obj_freeze(comments); return comments; } @@ -523,24 +527,29 @@ parser_magic_comment(VALUE source, bool freeze, const pm_magic_comment_t *magic_ return rb_class_new_instance_freeze(2, argv, rb_cPrismMagicComment, freeze); } +typedef struct { + VALUE magic_comments; + VALUE source; + bool freeze; +} parser_magic_comments_each_data_t; + +static void +parser_magic_comments_each(const pm_magic_comment_t *magic_comment, void *data) { + parser_magic_comments_each_data_t *each_data = (parser_magic_comments_each_data_t *) data; + VALUE value = parser_magic_comment(each_data->source, each_data->freeze, magic_comment); + rb_ary_push(each_data->magic_comments, value); +} + /** * Extract the magic comments out of the parser into an array. */ static VALUE parser_magic_comments(const pm_parser_t *parser, VALUE source, bool freeze) { - pm_magic_comments_iter_t *iter = pm_parser_magic_comments(parser); - VALUE magic_comments = rb_ary_new_capa(pm_magic_comments_iter_size(iter)); - - for ( - const pm_magic_comment_t *magic_comment = pm_magic_comments_iter_next(iter); - magic_comment != NULL; - magic_comment = pm_magic_comments_iter_next(iter) - ) { - VALUE value = parser_magic_comment(source, freeze, magic_comment); - rb_ary_push(magic_comments, value); - } + VALUE magic_comments = rb_ary_new_capa(pm_parser_magic_comments_size(parser)); + + parser_magic_comments_each_data_t each_data = { magic_comments, source, freeze }; + pm_parser_magic_comments_each(parser, parser_magic_comments_each, &each_data); - pm_magic_comments_iter_free(iter); if (freeze) rb_obj_freeze(magic_comments); return magic_comments; } @@ -560,90 +569,102 @@ parser_data_loc(const pm_parser_t *parser, VALUE source, bool freeze) { } } +typedef struct { + VALUE errors; + rb_encoding *encoding; + VALUE source; + bool freeze; +} parser_errors_each_data_t; + +static void +parser_errors_each(const pm_diagnostic_t *diagnostic, void *data) { + parser_errors_each_data_t *each_data = (parser_errors_each_data_t *) data; + + VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(diagnostic))); + VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(diagnostic), each_data->encoding)); + VALUE location = PARSER_LOCATION(each_data->source, each_data->freeze, pm_diagnostic_location(diagnostic)); + + pm_error_level_t error_level = pm_diagnostic_error_level(diagnostic); + VALUE level = Qnil; + + switch (error_level) { + case PM_ERROR_LEVEL_SYNTAX: + level = ID2SYM(rb_intern("syntax")); + break; + case PM_ERROR_LEVEL_ARGUMENT: + level = ID2SYM(rb_intern("argument")); + break; + case PM_ERROR_LEVEL_LOAD: + level = ID2SYM(rb_intern("load")); + break; + default: + rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, error_level); + } + + VALUE argv[] = { type, message, location, level }; + VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseError, each_data->freeze); + rb_ary_push(each_data->errors, value); +} + /** * Extract the errors out of the parser into an array. */ static VALUE parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) { - pm_diagnostics_iter_t *iter = pm_parser_errors(parser); - VALUE errors = rb_ary_new_capa(pm_diagnostics_iter_size(iter)); - - for ( - const pm_diagnostic_t *error = pm_diagnostics_iter_next(iter); - error != NULL; - error = pm_diagnostics_iter_next(iter) - ) { - VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(error))); - VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(error), encoding)); - VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(error)); - - pm_error_level_t error_level = pm_diagnostic_error_level(error); - VALUE level = Qnil; - - switch (error_level) { - case PM_ERROR_LEVEL_SYNTAX: - level = ID2SYM(rb_intern("syntax")); - break; - case PM_ERROR_LEVEL_ARGUMENT: - level = ID2SYM(rb_intern("argument")); - break; - case PM_ERROR_LEVEL_LOAD: - level = ID2SYM(rb_intern("load")); - break; - default: - rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, error_level); - } + VALUE errors = rb_ary_new_capa(pm_parser_errors_size(parser)); - VALUE argv[] = { type, message, location, level }; - VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseError, freeze); - rb_ary_push(errors, value); - } + parser_errors_each_data_t each_data = { errors, encoding, source, freeze }; + pm_parser_errors_each(parser, parser_errors_each, &each_data); - pm_diagnostics_iter_free(iter); if (freeze) rb_obj_freeze(errors); - return errors; } +typedef struct { + VALUE warnings; + rb_encoding *encoding; + VALUE source; + bool freeze; +} parser_warnings_each_data_t; + +static void +parser_warnings_each(const pm_diagnostic_t *diagnostic, void *data) { + parser_warnings_each_data_t *each_data = (parser_warnings_each_data_t *) data; + + VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(diagnostic))); + VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(diagnostic), each_data->encoding)); + VALUE location = PARSER_LOCATION(each_data->source, each_data->freeze, pm_diagnostic_location(diagnostic)); + + pm_warning_level_t warning_level = pm_diagnostic_warning_level(diagnostic); + VALUE level = Qnil; + + switch (warning_level) { + case PM_WARNING_LEVEL_DEFAULT: + level = ID2SYM(rb_intern("default")); + break; + case PM_WARNING_LEVEL_VERBOSE: + level = ID2SYM(rb_intern("verbose")); + break; + default: + rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, warning_level); + } + + VALUE argv[] = { type, message, location, level }; + VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseWarning, each_data->freeze); + rb_ary_push(each_data->warnings, value); +} + /** * Extract the warnings out of the parser into an array. */ static VALUE parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) { - pm_diagnostics_iter_t *iter = pm_parser_warnings(parser); - VALUE warnings = rb_ary_new_capa(pm_diagnostics_iter_size(iter)); - - for ( - const pm_diagnostic_t *warning = pm_diagnostics_iter_next(iter); - warning != NULL; - warning = pm_diagnostics_iter_next(iter) - ) { - VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(warning))); - VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(warning), encoding)); - VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(warning)); - - pm_warning_level_t warning_level = pm_diagnostic_warning_level(warning); - VALUE level = Qnil; - - switch (warning_level) { - case PM_WARNING_LEVEL_DEFAULT: - level = ID2SYM(rb_intern("default")); - break; - case PM_WARNING_LEVEL_VERBOSE: - level = ID2SYM(rb_intern("verbose")); - break; - default: - rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, warning_level); - } + VALUE warnings = rb_ary_new_capa(pm_parser_warnings_size(parser)); - VALUE argv[] = { type, message, location, level }; - VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseWarning, freeze); - rb_ary_push(warnings, value); - } + parser_warnings_each_data_t each_data = { warnings, encoding, source, freeze }; + pm_parser_warnings_each(parser, parser_warnings_each, &each_data); - pm_diagnostics_iter_free(iter); if (freeze) rb_obj_freeze(warnings); - return warnings; } @@ -1234,7 +1255,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { pm_parse(parser); - VALUE result = pm_diagnostics_iter_size(pm_parser_errors(parser)) == 0 ? Qtrue : Qfalse; + VALUE result = pm_parser_errors_size(parser) == 0 ? Qtrue : Qfalse; pm_parser_free(parser); pm_arena_free(&arena); diff --git a/include/prism/comments.h b/include/prism/comments.h index 7c95d0ca72..91792897d9 100644 --- a/include/prism/comments.h +++ b/include/prism/comments.h @@ -36,39 +36,4 @@ PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *co */ PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *comment); -/* An opaque pointer to an iterator that can be used to iterate over the - * comments associated with a parser. */ -typedef struct pm_comments_iter_t pm_comments_iter_t; - -/** - * Returns the number of comments associated with the comment iterator. - * - * @param iter the iterator to get the number of comments from - * @return the number of comments associated with the comment iterator - * - * \public \memberof pm_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION size_t pm_comments_iter_size(const pm_comments_iter_t *iter); - -/** - * Returns the next comment in the iteration, or NULL if there are no more - * comments. - * - * @param iter the iterator to get the next comment from - * @return the next comment in the iteration, or NULL if there are no more - * comments. - * - * \public \memberof pm_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION const pm_comment_t * pm_comments_iter_next(pm_comments_iter_t *iter); - -/** - * Frees the memory associated with the given comments iterator. - * - * @param iter the iterator to free - * - * \public \memberof pm_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION void pm_comments_iter_free(pm_comments_iter_t *iter); - #endif diff --git a/include/prism/internal/comments.h b/include/prism/internal/comments.h index 8b1009daf6..e8fbb0e6aa 100644 --- a/include/prism/internal/comments.h +++ b/include/prism/internal/comments.h @@ -22,16 +22,4 @@ struct pm_comment_t { pm_comment_type_t type; }; -/** - * A struct used as an opaque pointer for the client to iterate through the - * comments found while parsing. - */ -struct pm_comments_iter_t { - /** The number of comments in the list. */ - size_t size; - - /** The current node in the list. */ - const pm_list_node_t *current; -}; - #endif diff --git a/include/prism/internal/magic_comments.h b/include/prism/internal/magic_comments.h index eb4154928d..57c964bf4e 100644 --- a/include/prism/internal/magic_comments.h +++ b/include/prism/internal/magic_comments.h @@ -25,16 +25,4 @@ struct pm_magic_comment_t { pm_location_t value; }; -/** - * A struct used as an opaque pointer for the client to iterate through the - * magic comments found while parsing. - */ -struct pm_magic_comments_iter_t { - /** The number of magic comments in the list. */ - size_t size; - - /** The current node in the list. */ - const pm_list_node_t *current; -}; - #endif diff --git a/include/prism/parser.h b/include/prism/parser.h index 9e94ad1631..395dbe37be 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -138,59 +138,103 @@ PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser); PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); /** - * Returns an iterator that knows how to iterate over the comments that are - * associated with the given parser. + * Returns the number of comments associated with the given parser. * - * @param parser the parser whose comments we want to get - * @return the iterator that knows how to iterate over the comments that are - * associated with the given parser. It is the responsibility of the caller - * to free the memory associated with the iterator through - * pm_comments_iter_free. + * @param parser the parser whose comments we want to get the size of + * @return the number of comments associated with the given parser + */ +PRISM_EXPORTED_FUNCTION size_t pm_parser_comments_size(const pm_parser_t *parser); + +/** + * A callback function that can be used to process comments found while parsing. + */ +typedef void (*pm_comment_callback_t)(const pm_comment_t *comment, void *data); + +/** + * Iterates over the comments associated with the given parser and calls the + * given callback for each comment. * - * \public \memberof pm_parser + * @param parser the parser whose comments we want to iterate over + * @param callback the callback function to call for each comment. This function + * will be passed a pointer to the comment and the data parameter passed to + * this function. + * @param data the data to pass to the callback function for each comment. This + * can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION pm_comments_iter_t * pm_parser_comments(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION void pm_parser_comments_each(const pm_parser_t *parser, pm_comment_callback_t callback, void *data); /** - * Returns an iterator that knows how to iterate over the magic comments that - * are associated with the given parser. + * Returns the number of magic comments associated with the given parser. * - * @param parser the parser whose magic comments we want to get - * @return the iterator that knows how to iterate over the magic comments that are - * associated with the given parser. It is the responsibility of the caller - * to free the memory associated with the iterator through - * pm_magic_comments_iter_free. + * @param parser the parser whose magic comments we want to get the size of + * @return the number of magic comments associated with the given parser + */ +PRISM_EXPORTED_FUNCTION size_t pm_parser_magic_comments_size(const pm_parser_t *parser); + +/** + * A callback function that can be used to process magic comments found while parsing. + */ +typedef void (*pm_magic_comment_callback_t)(const pm_magic_comment_t *magic_comment, void *data); + +/** + * Iterates over the magic comments associated with the given parser and calls the + * given callback for each magic comment. * - * \public \memberof pm_parser + * @param parser the parser whose magic comments we want to iterate over + * @param callback the callback function to call for each magic comment. This + * function will be passed a pointer to the magic comment and the data + * parameter passed to this function. + * @param data the data to pass to the callback function for each magic comment. + * This can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION pm_magic_comments_iter_t * pm_parser_magic_comments(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION void pm_parser_magic_comments_each(const pm_parser_t *parser, pm_magic_comment_callback_t callback, void *data); /** - * Returns an iterator that knows how to iterate over the errors that are - * associated with the given parser. + * Returns the number of errors associated with the given parser. * - * @param parser the parser whose errors we want to get - * @return the iterator that knows how to iterate over the errors that are - * associated with the given parser. It is the responsibility of the caller - * to free the memory associated with the iterator through - * pm_diagnostics_iter_free. + * @param parser the parser whose errors we want to get the size of + * @return the number of errors associated with the given parser + */ +PRISM_EXPORTED_FUNCTION size_t pm_parser_errors_size(const pm_parser_t *parser); + +/** + * Returns the number of warnings associated with the given parser. * - * \public \memberof pm_parser + * @param parser the parser whose warnings we want to get the size of + * @return the number of warnings associated with the given parser + */ +PRISM_EXPORTED_FUNCTION size_t pm_parser_warnings_size(const pm_parser_t *parser); + +/** + * A callback function that can be used to process diagnostics found while + * parsing. */ -PRISM_EXPORTED_FUNCTION pm_diagnostics_iter_t * pm_parser_errors(const pm_parser_t *parser); +typedef void (*pm_diagnostic_callback_t)(const pm_diagnostic_t *diagnostic, void *data); /** - * Returns an iterator that knows how to iterate over the warnings that are - * associated with the given parser. + * Iterates over the errors associated with the given parser and calls the + * given callback for each error. * - * @param parser the parser whose warnings we want to get - * @return the iterator that knows how to iterate over the warnings that are - * associated with the given parser. It is the responsibility of the caller - * to free the memory associated with the iterator through - * pm_diagnostics_iter_free. + * @param parser the parser whose errors we want to iterate over + * @param callback the callback function to call for each error. This function + * will be passed a pointer to the error and the data parameter passed to + * this function. + * @param data the data to pass to the callback function for each error. This + * can be NULL if no data needs to be passed to the callback function. + */ +PRISM_EXPORTED_FUNCTION void pm_parser_errors_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data); + +/** + * Iterates over the warnings associated with the given parser and calls the + * given callback for each warning. * - * \public \memberof pm_parser + * @param parser the parser whose warnings we want to iterate over + * @param callback the callback function to call for each warning. This function + * will be passed a pointer to the warning and the data parameter passed to + * this function. + * @param data the data to pass to the callback function for each warning. This + * can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION pm_diagnostics_iter_t * pm_parser_warnings(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION void pm_parser_warnings_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data); #endif diff --git a/src/comments.c b/src/comments.c index 7e2f1e2f10..be535d2f7a 100644 --- a/src/comments.c +++ b/src/comments.c @@ -20,31 +20,3 @@ pm_comment_type_t pm_comment_type(const pm_comment_t *comment) { return comment->type; } - -/** - * Returns the number of comments associated with the comment iterator. - */ -size_t -pm_comments_iter_size(const pm_comments_iter_t *iter) { - return iter->size; -} - -/** - * Returns the next comment in the iteration, or NULL if there are no more - * comments. - */ -const pm_comment_t * -pm_comments_iter_next(pm_comments_iter_t *iter) { - if (iter->current == NULL) return NULL; - const pm_comment_t *comment = (const pm_comment_t *) iter->current; - iter->current = iter->current->next; - return comment; -} - -/** - * Frees the memory associated with the given comments iterator. - */ -void -pm_comments_iter_free(pm_comments_iter_t *iter) { - xfree(iter); -} diff --git a/src/magic_comments.c b/src/magic_comments.c index fc570868a6..6648010061 100644 --- a/src/magic_comments.c +++ b/src/magic_comments.c @@ -20,32 +20,3 @@ pm_location_t pm_magic_comment_value(const pm_magic_comment_t *magic_comment) { return magic_comment->value; } - -/** - * Returns the number of magic comments associated with the magic comment - * iterator. - */ -size_t -pm_magic_comments_iter_size(const pm_magic_comments_iter_t *iter) { - return iter->size; -} - -/** - * Returns the next magic comment in the iteration, or NULL if there are no more - * magic comments. - */ -const pm_magic_comment_t * -pm_magic_comments_iter_next(pm_magic_comments_iter_t *iter) { - if (iter->current == NULL) return NULL; - const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) iter->current; - iter->current = iter->current->next; - return magic_comment; -} - -/** - * Frees the memory associated with the given magic comments iterator. - */ -void -pm_magic_comments_iter_free(pm_magic_comments_iter_t *iter) { - xfree(iter); -} diff --git a/src/parser.c b/src/parser.c index 84d8dff992..c2814e1637 100644 --- a/src/parser.c +++ b/src/parser.c @@ -118,49 +118,89 @@ pm_parser_lex_state(const pm_parser_t *parser) { } /** - * Returns an iterator that knows how to iterate over the comments that are - * associated with the given parser. + * Returns the number of comments associated with the given parser. */ -pm_comments_iter_t * -pm_parser_comments(const pm_parser_t *parser) { - pm_comments_iter_t *iter = (pm_comments_iter_t *) xmalloc(sizeof(pm_comments_iter_t)); - iter->size = parser->comment_list.size; - iter->current = parser->comment_list.head; - return iter; +size_t +pm_parser_comments_size(const pm_parser_t *parser) { + return parser->comment_list.size; } /** - * Returns an iterator that knows how to iterate over the magic comments that - * are associated with the given parser. + * Iterates over the comments associated with the given parser and calls the + * given callback for each comment. */ -pm_magic_comments_iter_t * -pm_parser_magic_comments(const pm_parser_t *parser) { - pm_magic_comments_iter_t *iter = (pm_magic_comments_iter_t *) xmalloc(sizeof(pm_magic_comments_iter_t)); - iter->size = parser->magic_comment_list.size; - iter->current = parser->magic_comment_list.head; - return iter; +void +pm_parser_comments_each(const pm_parser_t *parser, pm_comment_callback_t callback, void *data) { + const pm_list_node_t *current = parser->comment_list.head; + while (current != NULL) { + const pm_comment_t *comment = (const pm_comment_t *) current; + callback(comment, data); + current = current->next; + } +} + +/** + * Returns the number of magic comments associated with the given parser. + */ +size_t +pm_parser_magic_comments_size(const pm_parser_t *parser) { + return parser->magic_comment_list.size; +} + +/** + * Iterates over the magic comments associated with the given parser and calls + * the given callback for each magic comment. + */ +void +pm_parser_magic_comments_each(const pm_parser_t *parser, pm_magic_comment_callback_t callback, void *data) { + const pm_list_node_t *current = parser->magic_comment_list.head; + while (current != NULL) { + const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) current; + callback(magic_comment, data); + current = current->next; + } +} + +/** + * Returns the number of errors associated with the given parser. + */ +size_t +pm_parser_errors_size(const pm_parser_t *parser) { + return parser->error_list.size; } /** - * Returns an iterator that knows how to iterate over the errors that are - * associated with the given parser. + * Returns the number of warnings associated with the given parser. */ -pm_diagnostics_iter_t * -pm_parser_errors(const pm_parser_t *parser) { - pm_diagnostics_iter_t *iter = (pm_diagnostics_iter_t *) xmalloc(sizeof(pm_diagnostics_iter_t)); - iter->size = parser->error_list.size; - iter->current = parser->error_list.head; - return iter; +size_t +pm_parser_warnings_size(const pm_parser_t *parser) { + return parser->warning_list.size; +} + +static inline void +pm_parser_diagnostics_each(const pm_list_t *list, pm_diagnostic_callback_t callback, void *data) { + const pm_list_node_t *current = list->head; + while (current != NULL) { + const pm_diagnostic_t *diagnostic = (const pm_diagnostic_t *) current; + callback(diagnostic, data); + current = current->next; + } } /** - * Returns an iterator that knows how to iterate over the warnings that are - * associated with the given parser. + * Iterates over the errors associated with the given parser and calls the + * given callback for each error. */ -pm_diagnostics_iter_t * -pm_parser_warnings(const pm_parser_t *parser) { - pm_diagnostics_iter_t *iter = (pm_diagnostics_iter_t *) xmalloc(sizeof(pm_diagnostics_iter_t)); - iter->size = parser->warning_list.size; - iter->current = parser->warning_list.head; - return iter; +void +pm_parser_errors_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data) { + pm_parser_diagnostics_each(&parser->error_list, callback, data); +} + +/** + * Iterates over the warnings associated with the given parser and calls the + * given callback for each warning. + */ +void +pm_parser_warnings_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data) { + pm_parser_diagnostics_each(&parser->warning_list, callback, data); } diff --git a/templates/include/prism/internal/diagnostic.h.erb b/templates/include/prism/internal/diagnostic.h.erb index ca294e3972..fcbc2b6a70 100644 --- a/templates/include/prism/internal/diagnostic.h.erb +++ b/templates/include/prism/internal/diagnostic.h.erb @@ -75,16 +75,4 @@ void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t star */ void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); -/** - * A struct used as an opaque pointer for the client to iterate through the - * diagnostics found while parsing. - */ -struct pm_diagnostics_iter_t { - /** The number of diagnostics in the list. */ - size_t size; - - /** The current node in the list. */ - const pm_list_node_t *current; -}; - #endif From 1f4bf83b5364bf1150a978f44594f7be492123c0 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 12:09:46 -0400 Subject: [PATCH 211/289] Code review --- include/prism/options.h | 2 +- include/prism/parser.h | 2 +- src/options.c | 8 ++++---- src/parser.c | 2 +- src/string_query.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/prism/options.h b/include/prism/options.h index aba122f705..61afc0df92 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -143,7 +143,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *optio * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_filepath_get(pm_options_t *options); +PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath_get(const pm_options_t *options); /** * Set the filepath option on the given options struct. diff --git a/include/prism/parser.h b/include/prism/parser.h index 395dbe37be..f15ddd8901 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -57,7 +57,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_lex_callback_set(pm_parser_t *parser, pm_ * @param parser The parser whose lex callback data we want to get. * @return The opaque data that is passed to the lex callback when it is called. */ -PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(const pm_parser_t *parser); /** * Returns the raw pointer to the start of the source that is being parsed. diff --git a/src/options.c b/src/options.c index ecdeba58f3..9dbafdf63c 100644 --- a/src/options.c +++ b/src/options.c @@ -63,8 +63,8 @@ pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callba /** * Get the filepath option on the given options struct. */ -pm_string_t * -pm_options_filepath_get(pm_options_t *options) { +const pm_string_t * +pm_options_filepath_get(const pm_options_t *options) { return &options->filepath; } @@ -182,8 +182,8 @@ pm_options_version_set(pm_options_t *options, const char *version, size_t length } } - if (length >= 6) { - if (strncmp(version, "latest", 7) == 0) { // 7 to compare the \0 as well + if (length == 6) { + if (strncmp(version, "latest", 6) == 0) { options->version = PM_OPTIONS_VERSION_LATEST; return true; } diff --git a/src/parser.c b/src/parser.c index c2814e1637..27c9641f83 100644 --- a/src/parser.c +++ b/src/parser.c @@ -30,7 +30,7 @@ pm_parser_lex_callback_set(pm_parser_t *parser, pm_lex_callback_t callback, void * Returns the opaque data that is passed to the lex callback when it is called. */ void * -pm_parser_lex_callback_data(pm_parser_t *parser) { +pm_parser_lex_callback_data(const pm_parser_t *parser) { return parser->lex_callback.data; } diff --git a/src/string_query.c b/src/string_query.c index a3be418b75..ccedaf9c00 100644 --- a/src/string_query.c +++ b/src/string_query.c @@ -27,7 +27,7 @@ typedef enum { /** * Check that the slice is a valid local variable name or constant. */ -pm_slice_type_t +static pm_slice_type_t pm_slice_type(const uint8_t *source, size_t length, const char *encoding_name) { // first, get the right encoding object const pm_encoding_t *encoding = pm_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))); From 2867c529a3366477189d876dde68b36fab4f421e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 12:35:33 -0400 Subject: [PATCH 212/289] Move node list append internal --- include/prism/internal/node.h | 31 ++++++++++++++++++++++++++++++- include/prism/node.h | 27 --------------------------- templates/src/node.c.erb | 2 +- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/include/prism/internal/node.h b/include/prism/internal/node.h index 2399b5a72a..075dc33e0a 100644 --- a/include/prism/internal/node.h +++ b/include/prism/internal/node.h @@ -4,8 +4,37 @@ #ifndef PRISM_INTERNAL_NODE_H #define PRISM_INTERNAL_NODE_H +#include "prism/node.h" + +#include "prism/compiler/force_inline.h" + #include "prism/arena.h" -#include "prism/ast.h" + +/** + * Slow path for pm_node_list_append: grow the list and append the node. + * Do not call directly — use pm_node_list_append instead. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param node The node to append. + */ +void pm_node_list_append_slow(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); + +/** + * Append a new node onto the end of the node list. + * + * @param arena The arena to allocate from. + * @param list The list to append to. + * @param node The node to append. + */ +static PRISM_FORCE_INLINE void +pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { + if (list->size < list->capacity) { + list->nodes[list->size++] = node; + } else { + pm_node_list_append_slow(arena, list, node); + } +} /** * Prepend a new node onto the beginning of the node list. diff --git a/include/prism/node.h b/include/prism/node.h index ac7c337ad9..3d2ff3170a 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -8,7 +8,6 @@ #include "prism/compiler/exported.h" -#include "prism/arena.h" #include "prism/ast.h" /** @@ -18,32 +17,6 @@ #define PM_NODE_LIST_FOREACH(list, index, node) \ for (size_t index = 0; index < (list)->size && ((node) = (list)->nodes[index]); index++) -/** - * Slow path for pm_node_list_append: grow the list and append the node. - * Do not call directly — use pm_node_list_append instead. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param node The node to append. - */ -void pm_node_list_append_slow(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); - -/** - * Append a new node onto the end of the node list. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param node The node to append. - */ -static PRISM_FORCE_INLINE void -pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { - if (list->size < list->capacity) { - list->nodes[list->size++] = node; - } else { - pm_node_list_append_slow(arena, list, node); - } -} - /** * Returns a string representation of the given node type. * diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index da249141ed..3db5239b6f 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -1,5 +1,5 @@ #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" -#include "prism/node.h" +#include "prism/internal/node.h" #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" From 9498322c7cb5774b3ab89236899a8c0a82950906 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 12:49:31 -0400 Subject: [PATCH 213/289] Fix up diagnostic templates --- include/prism/diagnostic.h | 35 ----------------------------- templates/src/diagnostic.c.erb | 40 +++++----------------------------- 2 files changed, 6 insertions(+), 69 deletions(-) diff --git a/include/prism/diagnostic.h b/include/prism/diagnostic.h index 0619c274ef..6c098c55ef 100644 --- a/include/prism/diagnostic.h +++ b/include/prism/diagnostic.h @@ -96,39 +96,4 @@ PRISM_EXPORTED_FUNCTION pm_error_level_t pm_diagnostic_error_level(const pm_diag */ PRISM_EXPORTED_FUNCTION pm_warning_level_t pm_diagnostic_warning_level(const pm_diagnostic_t *diagnostic); -/* An opaque pointer to an iterator that can be used to iterate over a set of - * diagnostics associated with a parser. */ -typedef struct pm_diagnostics_iter_t pm_diagnostics_iter_t; - -/** - * Returns the number of diagnostics associated with the diagnostics iterator. - * - * @param iter the iterator to get the number of diagnostics from - * @return the number of diagnostics associated with the diagnostics iterator - * - * \public \memberof pm_diagnostics_iter_t - */ -PRISM_EXPORTED_FUNCTION size_t pm_diagnostics_iter_size(const pm_diagnostics_iter_t *iter); - -/** - * Returns the next diagnostic in the iteration, or NULL if there are no more - * diagnostics. - * - * @param iter the iterator to get the next diagnostic from - * @return the next diagnostic in the iteration, or NULL if there are no more - * diagnostics. - * - * \public \memberof pm_diagnostics_iter_t - */ -PRISM_EXPORTED_FUNCTION const pm_diagnostic_t * pm_diagnostics_iter_next(pm_diagnostics_iter_t *iter); - -/** - * Frees the memory associated with the given diagnostics iterator. - * - * @param iter the iterator to free - * - * \public \memberof pm_diagnostics_iter_t - */ -PRISM_EXPORTED_FUNCTION void pm_diagnostics_iter_free(pm_diagnostics_iter_t *iter); - #endif diff --git a/templates/src/diagnostic.c.erb b/templates/src/diagnostic.c.erb index a4aba2e586..0dea732869 100644 --- a/templates/src/diagnostic.c.erb +++ b/templates/src/diagnostic.c.erb @@ -87,16 +87,16 @@ typedef struct { * * `PM_WARNING_LEVEL_VERBOSE` - Warnings that appear with `-w`, as in `ruby -w -c -e 'code'`. */ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { - // Special error that can be replaced + /* Special error that can be replaced */ [PM_ERR_CANNOT_PARSE_EXPRESSION] = { "cannot parse the expression", PM_ERROR_LEVEL_SYNTAX }, - // Errors that should raise argument errors + /* Errors that should raise argument errors */ [PM_ERR_INVALID_ENCODING_MAGIC_COMMENT] = { "unknown or invalid encoding in the magic comment", PM_ERROR_LEVEL_ARGUMENT }, - // Errors that should raise load errors + /* Errors that should raise load errors */ [PM_ERR_SCRIPT_NOT_FOUND] = { "no Ruby script found in input", PM_ERROR_LEVEL_LOAD }, - // Errors that should raise syntax errors + /* Errors that should raise syntax errors */ [PM_ERR_ALIAS_ARGUMENT] = { "invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ALIAS_ARGUMENT_NUMBERED_REFERENCE] = { "invalid argument being passed to `alias`; can't make alias for the number variables", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = { "unexpected `&&=` in a multiple assignment", PM_ERROR_LEVEL_SYNTAX }, @@ -365,7 +365,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_STRING_INTERPOLATED_TERM] = { "unterminated string; expected a closing delimiter for the interpolated string", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_LITERAL_EOF] = { "unterminated string meets end of file", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_LITERAL_TERM] = { "unexpected %s, expected a string literal terminator", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_LEVEL_SYNTAX }, // TODO expected symbol? prism.c ~9719 + [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_LEVEL_SYNTAX }, /* TODO expected symbol? prism.c ~9719 */ [PM_ERR_SYMBOL_TERM_DYNAMIC] = { "unterminated quoted string; expected a closing delimiter for the dynamic symbol", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "unterminated symbol; expected a closing delimiter for the interpolated symbol", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_LEVEL_SYNTAX }, @@ -392,7 +392,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_WRITE_TARGET_UNEXPECTED] = { "unexpected write target", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_XSTRING_TERM] = { "expected a closing delimiter for the `%x` or backtick string", PM_ERROR_LEVEL_SYNTAX }, - // Warnings + /* Warnings */ [PM_WARN_AMBIGUOUS_BINARY_OPERATOR] = { "'%s' after local variable or literal is interpreted as binary operator even though it seems like %s", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = { "ambiguous first argument; put parentheses or a space even after `-` operator", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = { "ambiguous first argument; put parentheses or a space even after `+` operator", PM_WARNING_LEVEL_VERBOSE }, @@ -552,31 +552,3 @@ pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t st pm_list_append(list, (pm_list_node_t *) diagnostic); } - -/** - * Returns the number of diagnostics associated with the diagnostics iterator. - */ -size_t -pm_diagnostics_iter_size(const pm_diagnostics_iter_t *iter) { - return iter->size; -} - -/** - * Returns the next diagnostic in the iteration, or NULL if there are no more - * diagnostics. - */ -const pm_diagnostic_t * -pm_diagnostics_iter_next(pm_diagnostics_iter_t *iter) { - if (iter->current == NULL) return NULL; - const pm_diagnostic_t *diagnostic = (const pm_diagnostic_t *) iter->current; - iter->current = iter->current->next; - return diagnostic; -} - -/** - * Frees the memory associated with the given diagnostics iterator. - */ -void -pm_diagnostics_iter_free(pm_diagnostics_iter_t *iter) { - xfree(iter); -} From 2fcab5eeb838dbd692c129d53da45b5e65eb9be4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 12:58:35 -0400 Subject: [PATCH 214/289] Do not inline node_new functions --- .gitignore | 1 + templates/include/prism/node_new.h.erb | 21 +++++---------------- templates/src/node_new.c.erb | 24 ++++++++++++++++++++++++ templates/template.rb | 1 + 4 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 templates/src/node_new.c.erb diff --git a/.gitignore b/.gitignore index a8370790b2..edcf62a959 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ out.svg /sorbet/ /src/diagnostic.c /src/node.c +/src/node_new.c /src/prettyprint.c /src/serialize.c /src/token_type.c diff --git a/templates/include/prism/node_new.h.erb b/templates/include/prism/node_new.h.erb index 4a253fc02e..d3d4ebd773 100644 --- a/templates/include/prism/node_new.h.erb +++ b/templates/include/prism/node_new.h.erb @@ -1,16 +1,17 @@ /** * @file node_new.h * - * Static inline functions for allocating and initializing AST nodes. + * Functions for allocating and initializing AST nodes. * * -- */ #ifndef PRISM_NODE_NEW_H #define PRISM_NODE_NEW_H -#include "prism/compiler/inline.h" +#include "prism/compiler/exported.h" -#include "prism/node.h" +#include "prism/arena.h" +#include "prism/ast.h" <%- nodes.each do |node| -%> <%- params = node.fields.map(&:c_param) -%> @@ -26,19 +27,7 @@ <%- end -%> * @return The newly allocated and initialized node. */ -static PRISM_INLINE pm_<%= node.human %>_t * -pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { - pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); - - *node = (pm_<%= node.human %>_t) { - .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %> -<%- node.fields.each_with_index do |field, index| -%> - .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %> -<%- end -%> - }; - - return node; -} +PRISM_EXPORTED_FUNCTION pm_<%= node.human %>_t * pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>); <%- end -%> #endif diff --git a/templates/src/node_new.c.erb b/templates/src/node_new.c.erb new file mode 100644 index 0000000000..f40a823472 --- /dev/null +++ b/templates/src/node_new.c.erb @@ -0,0 +1,24 @@ +#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" +#include "prism/internal/arena.h" +#include "prism/ast.h" + +<%- nodes.each do |node| -%> +<%- params = node.fields.map(&:c_param) -%> +/** + * Allocate and initialize a new <%= node.name %> node. + */ +pm_<%= node.human %>_t * +pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { + pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); + + *node = (pm_<%= node.human %>_t) { + .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %> +<%- node.fields.each_with_index do |field, index| -%> + .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %> +<%- end -%> + }; + + return node; +} + +<%- end -%> diff --git a/templates/template.rb b/templates/template.rb index b3ccf373d3..0838181d26 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -704,6 +704,7 @@ def locals "lib/prism/visitor.rb", "src/diagnostic.c", "src/node.c", + "src/node_new.c", "src/prettyprint.c", "src/serialize.c", "src/token_type.c" From ee6f32068912c13e3a94afc63431072d44e1ed49 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:03:39 -0400 Subject: [PATCH 215/289] Fold node_new into node/ast --- .gitignore | 2 -- prism.gemspec | 1 - src/prism.c | 1 - templates/include/prism/ast.h.erb | 19 +++++++++++++++ templates/include/prism/node_new.h.erb | 33 -------------------------- templates/src/node.c.erb | 21 ++++++++++++++++ templates/src/node_new.c.erb | 24 ------------------- templates/template.rb | 2 -- 8 files changed, 40 insertions(+), 63 deletions(-) delete mode 100644 templates/include/prism/node_new.h.erb delete mode 100644 templates/src/node_new.c.erb diff --git a/.gitignore b/.gitignore index edcf62a959..7df40e7ba6 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,6 @@ out.svg /fuzz/output/ /gemfiles/typecheck/bin/ /include/prism/ast.h -/include/prism/node_new.h /include/prism/internal/diagnostic.h /javascript/node_modules/ /javascript/package-lock.json @@ -56,7 +55,6 @@ out.svg /sorbet/ /src/diagnostic.c /src/node.c -/src/node_new.c /src/prettyprint.c /src/serialize.c /src/token_type.c diff --git a/prism.gemspec b/prism.gemspec index ca21b792cc..41eb9888ca 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -92,7 +92,6 @@ Gem::Specification.new do |spec| "include/prism/line_offset_list.h", "include/prism/magic_comments.h", "include/prism/node.h", - "include/prism/node_new.h", "include/prism/options.h", "include/prism/parser.h", "include/prism/prettyprint.h", diff --git a/src/prism.c b/src/prism.c index 06d3dc42b9..4c497d74b6 100644 --- a/src/prism.c +++ b/src/prism.c @@ -30,7 +30,6 @@ #include "prism/internal/strpbrk.h" #include "prism/excludes.h" -#include "prism/node_new.h" #include #include diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 754d05a216..3a949f1000 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -9,7 +9,9 @@ #define PRISM_AST_H #include "prism/compiler/align.h" +#include "prism/compiler/exported.h" +#include "prism/arena.h" #include "prism/constant_pool.h" #include "prism/integer.h" #include "prism/strings.h" @@ -238,6 +240,23 @@ typedef enum pm_<%= flag.human %> { PM_<%= flag.human.upcase %>_LAST, } pm_<%= flag.human %>_t; <%- end -%> +<%- nodes.each do |node| -%> + +<%- params = node.fields.map(&:c_param) -%> +/** + * Allocate and initialize a new <%= node.name %> node. + * + * @param arena The arena to allocate from. + * @param node_id The unique identifier for this node. + * @param flags The flags for this node. + * @param location The location of this node in the source. +<%- node.fields.each do |field| -%> + * @param <%= field.name %> <%= field.comment ? Prism::Template::Doxygen.verbatim(field.comment.lines.first.strip) : "The #{field.name} field." %> +<%- end -%> + * @return The newly allocated and initialized node. + */ +PRISM_EXPORTED_FUNCTION pm_<%= node.human %>_t * pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>); +<%- end -%> /** * When we're serializing to Java, we want to skip serializing the location diff --git a/templates/include/prism/node_new.h.erb b/templates/include/prism/node_new.h.erb deleted file mode 100644 index d3d4ebd773..0000000000 --- a/templates/include/prism/node_new.h.erb +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file node_new.h - * - * Functions for allocating and initializing AST nodes. - * - * -- - */ -#ifndef PRISM_NODE_NEW_H -#define PRISM_NODE_NEW_H - -#include "prism/compiler/exported.h" - -#include "prism/arena.h" -#include "prism/ast.h" - -<%- nodes.each do |node| -%> -<%- params = node.fields.map(&:c_param) -%> -/** - * Allocate and initialize a new <%= node.name %> node. - * - * @param arena The arena to allocate from. - * @param node_id The unique identifier for this node. - * @param flags The flags for this node. - * @param location The location of this node in the source. -<%- node.fields.each do |field| -%> - * @param <%= field.name %> <%= field.comment ? Prism::Template::Doxygen.verbatim(field.comment.lines.first.strip) : "The #{field.name} field." %> -<%- end -%> - * @return The newly allocated and initialized node. - */ -PRISM_EXPORTED_FUNCTION pm_<%= node.human %>_t * pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>); - -<%- end -%> -#endif diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 3db5239b6f..695175d7c8 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -1,6 +1,7 @@ #line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" #include "prism/internal/node.h" +#include "prism/internal/arena.h" #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" #include "prism/internal/integer.h" @@ -270,3 +271,23 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no } #endif +<%- nodes.each do |node| -%> + +<%- params = node.fields.map(&:c_param) -%> +/** + * Allocate and initialize a new <%= node.name %> node. + */ +pm_<%= node.human %>_t * +pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { + pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); + + *node = (pm_<%= node.human %>_t) { + .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %> +<%- node.fields.each_with_index do |field, index| -%> + .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %> +<%- end -%> + }; + + return node; +} +<%- end -%> diff --git a/templates/src/node_new.c.erb b/templates/src/node_new.c.erb deleted file mode 100644 index f40a823472..0000000000 --- a/templates/src/node_new.c.erb +++ /dev/null @@ -1,24 +0,0 @@ -#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>" -#include "prism/internal/arena.h" -#include "prism/ast.h" - -<%- nodes.each do |node| -%> -<%- params = node.fields.map(&:c_param) -%> -/** - * Allocate and initialize a new <%= node.name %> node. - */ -pm_<%= node.human %>_t * -pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>) { - pm_<%= node.human %>_t *node = (pm_<%= node.human %>_t *) pm_arena_alloc(arena, sizeof(pm_<%= node.human %>_t), PRISM_ALIGNOF(pm_<%= node.human %>_t)); - - *node = (pm_<%= node.human %>_t) { - .base = { .type = <%= node.type %>, .flags = flags, .node_id = node_id, .location = location }<%= node.fields.empty? ? "" : "," %> -<%- node.fields.each_with_index do |field, index| -%> - .<%= field.name %> = <%= field.name %><%= index < node.fields.size - 1 ? "," : "" %> -<%- end -%> - }; - - return node; -} - -<%- end -%> diff --git a/templates/template.rb b/templates/template.rb index 0838181d26..fb778871b4 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -684,7 +684,6 @@ def locals TEMPLATES = [ "ext/prism/api_node.c", "include/prism/ast.h", - "include/prism/node_new.h", "include/prism/internal/diagnostic.h", "javascript/src/deserialize.js", "javascript/src/nodes.js", @@ -704,7 +703,6 @@ def locals "lib/prism/visitor.rb", "src/diagnostic.c", "src/node.c", - "src/node_new.c", "src/prettyprint.c", "src/serialize.c", "src/token_type.c" From 639da14de555349b6031ba177a17cf92b31aff45 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:05:57 -0400 Subject: [PATCH 216/289] Move some of arena internal --- cpp/test.cpp | 2 +- ext/prism/extension.c | 14 ++++---- include/prism.h | 6 ++-- include/prism/arena.h | 41 ++--------------------- include/prism/internal/arena.h | 37 ++++++++++++++++++++ include/prism/node.h | 2 +- rust/ruby-prism-sys/build/main.rs | 2 +- rust/ruby-prism-sys/tests/node_tests.rs | 4 +-- rust/ruby-prism-sys/tests/parser_tests.rs | 8 ++--- rust/ruby-prism/src/parse_result/mod.rs | 4 +-- src/arena.c | 2 +- src/prism.c | 12 +++---- templates/src/serialize.c.erb | 4 +-- 13 files changed, 69 insertions(+), 69 deletions(-) diff --git a/cpp/test.cpp b/cpp/test.cpp index 8ef742d957..916d10381d 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -18,7 +18,7 @@ int main() { pm_buffer_free(buffer); pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); return 0; } diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 27cc3839ed..0606b9b238 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -381,7 +381,7 @@ dump_input(pm_string_t *input, const pm_options_t *options) { VALUE result = rb_str_new(pm_buffer_value(buffer), pm_buffer_length(buffer)); pm_buffer_free(buffer); pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); return result; } @@ -828,7 +828,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod } pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); return result; } @@ -902,7 +902,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) { } pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); return result; } @@ -1009,7 +1009,7 @@ profile_input(pm_string_t *input, const pm_options_t *options) { pm_parse(parser); pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); } /** @@ -1117,7 +1117,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_buffer_free(buffer); pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); pm_options_free(options); return result; @@ -1138,7 +1138,7 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { VALUE comments = parser_comments(parser, source, pm_options_freeze_get(options)); pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); return comments; } @@ -1257,7 +1257,7 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { VALUE result = pm_parser_errors_size(parser) == 0 ? Qtrue : Qfalse; pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); return result; } diff --git a/include/prism.h b/include/prism.h index 9af3e6cf6c..5a8b835978 100644 --- a/include/prism.h +++ b/include/prism.h @@ -260,7 +260,7 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * * `pm_parser_new()` - allocate and initialize a new parser * * `pm_parse()` - parse and return the root node * * `pm_parser_free()` - free the parser and its internal memory - * * `pm_arena_free()` - free all AST-lifetime memory + * * `pm_arena_cleanup()` - free all AST-lifetime memory * * Putting all of this together would look something like: * @@ -273,7 +273,7 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * printf("PARSED!\n"); * * pm_parser_free(parser); - * pm_arena_free(&arena); + * pm_arena_cleanup(&arena); * } * ``` * @@ -326,7 +326,7 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * * pm_buffer_free(buffer); * pm_parser_free(parser); - * pm_arena_free(&arena); + * pm_arena_cleanup(&arena); * } * ``` */ diff --git a/include/prism/arena.h b/include/prism/arena.h index 73f2fab900..303ccc554b 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -43,49 +43,12 @@ typedef struct { size_t block_count; } pm_arena_t; -/** - * Slow path for pm_arena_alloc: allocate a new block and return a pointer to - * the first `size` bytes. Do not call directly — use pm_arena_alloc instead. - * - * @param arena The arena to allocate from. - * @param size The number of bytes to allocate. - * @returns A pointer to the allocated memory. - */ -void * pm_arena_alloc_slow(pm_arena_t *arena, size_t size); - -/** - * Allocate memory from the arena. The returned memory is NOT zeroed. This - * function is infallible — it aborts on allocation failure. - * - * The fast path (bump pointer within the current block) is inlined at each - * call site. The slow path (new block allocation) is out-of-line. - * - * @param arena The arena to allocate from. - * @param size The number of bytes to allocate. - * @param alignment The required alignment (must be a power of 2). - * @returns A pointer to the allocated memory. - */ -static PRISM_FORCE_INLINE void * -pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { - if (arena->current != NULL) { - size_t used_aligned = (arena->current->used + alignment - 1) & ~(alignment - 1); - size_t needed = used_aligned + size; - - if (used_aligned >= arena->current->used && needed >= used_aligned && needed <= arena->current->capacity) { - arena->current->used = needed; - return arena->current->data + used_aligned; - } - } - - return pm_arena_alloc_slow(arena, size); -} - /** * Free all blocks in the arena. After this call, all pointers returned by * pm_arena_alloc and pm_arena_zalloc are invalid. * - * @param arena The arena to free. + * @param arena The arena whose held memory should be freed. */ -PRISM_EXPORTED_FUNCTION void pm_arena_free(pm_arena_t *arena); +PRISM_EXPORTED_FUNCTION void pm_arena_cleanup(pm_arena_t *arena); #endif diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h index 747484fa2f..1a393f7bcb 100644 --- a/include/prism/internal/arena.h +++ b/include/prism/internal/arena.h @@ -24,6 +24,43 @@ */ void pm_arena_reserve(pm_arena_t *arena, size_t capacity); +/** + * Slow path for pm_arena_alloc: allocate a new block and return a pointer to + * the first `size` bytes. Do not call directly — use pm_arena_alloc instead. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @returns A pointer to the allocated memory. + */ +void * pm_arena_alloc_slow(pm_arena_t *arena, size_t size); + +/** + * Allocate memory from the arena. The returned memory is NOT zeroed. This + * function is infallible — it aborts on allocation failure. + * + * The fast path (bump pointer within the current block) is inlined at each + * call site. The slow path (new block allocation) is out-of-line. + * + * @param arena The arena to allocate from. + * @param size The number of bytes to allocate. + * @param alignment The required alignment (must be a power of 2). + * @returns A pointer to the allocated memory. + */ +static PRISM_FORCE_INLINE void * +pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { + if (arena->current != NULL) { + size_t used_aligned = (arena->current->used + alignment - 1) & ~(alignment - 1); + size_t needed = used_aligned + size; + + if (used_aligned >= arena->current->used && needed >= used_aligned && needed <= arena->current->capacity) { + arena->current->used = needed; + return arena->current->data + used_aligned; + } + } + + return pm_arena_alloc_slow(arena, size); +} + /** * Allocate zero-initialized memory from the arena. This function is infallible * — it aborts on allocation failure. diff --git a/include/prism/node.h b/include/prism/node.h index 3d2ff3170a..bfda2a6a52 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -67,7 +67,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * * pm_parser_free(parser); * pm_options_free(options); - * pm_arena_free(&arena); + * pm_arena_cleanup(&arena); * * return EXIT_SUCCESS; * } diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 4cf5add131..9c4d807030 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -144,7 +144,7 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .rustified_non_exhaustive_enum(r"pm_\w+_flags") .rustified_non_exhaustive_enum("pm_node_type") // Functions - .allowlist_function("pm_arena_free") + .allowlist_function("pm_arena_cleanup") .allowlist_function("pm_line_offset_list_line_column") .allowlist_function("pm_options_command_line_set") .allowlist_function("pm_options_encoding_locked_set") diff --git a/rust/ruby-prism-sys/tests/node_tests.rs b/rust/ruby-prism-sys/tests/node_tests.rs index 0de0eabe49..73c8c04d30 100644 --- a/rust/ruby-prism-sys/tests/node_tests.rs +++ b/rust/ruby-prism-sys/tests/node_tests.rs @@ -1,6 +1,6 @@ use std::{ffi::CString, mem::MaybeUninit}; -use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_node_type}; +use ruby_prism_sys::{pm_arena_cleanup, pm_arena_t, pm_node_type}; use ruby_prism_sys::{pm_parse, pm_parser_cleanup, pm_parser_init, pm_parser_t}; #[test] @@ -24,6 +24,6 @@ fn node_test() { assert_eq!((*parsed_node).type_, pm_node_type::PM_PROGRAM_NODE as u16); pm_parser_cleanup(parser); - pm_arena_free(arena.as_mut_ptr()); + pm_arena_cleanup(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism-sys/tests/parser_tests.rs b/rust/ruby-prism-sys/tests/parser_tests.rs index 3d85ef06de..7efb374ae8 100644 --- a/rust/ruby-prism-sys/tests/parser_tests.rs +++ b/rust/ruby-prism-sys/tests/parser_tests.rs @@ -5,7 +5,7 @@ use std::{ }; use ruby_prism_sys::{ - pm_arena_free, pm_arena_t, pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_parse, pm_parser_cleanup, + pm_arena_cleanup, pm_arena_t, pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_parse, pm_parser_cleanup, pm_parser_init, pm_parser_t, }; @@ -30,7 +30,7 @@ fn init_test() { let parser = parser.assume_init_mut(); pm_parser_cleanup(parser); - pm_arena_free(arena.as_mut_ptr()); + pm_arena_cleanup(arena.as_mut_ptr()); } } @@ -63,7 +63,7 @@ fn comments_test() { assert_eq!(location, 0..7); pm_parser_cleanup(parser); - pm_arena_free(arena.as_mut_ptr()); + pm_arena_cleanup(arena.as_mut_ptr()); } } @@ -102,6 +102,6 @@ fn diagnostics_test() { assert_eq!(location, 10..10); pm_parser_cleanup(parser); - pm_arena_free(arena.as_mut_ptr()); + pm_arena_cleanup(arena.as_mut_ptr()); } } diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index 4ac843661e..5e071b515b 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -8,7 +8,7 @@ mod diagnostics; use std::ptr::NonNull; -use ruby_prism_sys::{pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_cleanup, pm_parser_t}; +use ruby_prism_sys::{pm_arena_cleanup, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_cleanup, pm_parser_t}; pub use self::comments::{Comment, CommentType, Comments, MagicComment, MagicComments}; pub use self::diagnostics::{Diagnostic, Diagnostics}; @@ -262,7 +262,7 @@ impl Drop for ParseResult<'_> { unsafe { pm_parser_cleanup(self.parser.as_ptr()); drop(Box::from_raw(self.parser.as_ptr())); - pm_arena_free(self.arena.as_mut()); + pm_arena_cleanup(self.arena.as_mut()); } } } diff --git a/src/arena.c b/src/arena.c index d0bd6f139c..393725c90f 100644 --- a/src/arena.c +++ b/src/arena.c @@ -85,7 +85,7 @@ pm_arena_alloc_slow(pm_arena_t *arena, size_t size) { * Free all blocks in the arena. */ void -pm_arena_free(pm_arena_t *arena) { +pm_arena_cleanup(pm_arena_t *arena) { pm_arena_block_t *block = arena->current; while (block != NULL) { diff --git a/src/prism.c b/src/prism.c index 4c497d74b6..fb2b67a779 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22501,7 +22501,7 @@ pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_op void pm_parser_cleanup(pm_parser_t *parser) { pm_string_cleanup(&parser->filepath); - pm_arena_free(&parser->metadata_arena); + pm_arena_cleanup(&parser->metadata_arena); while (parser->current_scope != NULL) { // Normally, popping the scope doesn't free the locals since it is @@ -22768,7 +22768,7 @@ pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, vo eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); pm_parser_free(tmp); - pm_arena_free(arena); + pm_arena_cleanup(arena); tmp = pm_parser_new(arena, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); node = pm_parse(tmp); @@ -22794,7 +22794,7 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { bool result = parser.error_list.size == 0; pm_parser_cleanup(&parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); pm_options_cleanup(&options); return result; @@ -22849,7 +22849,7 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons pm_buffer_append_byte(buffer, '\0'); pm_parser_cleanup(&parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); pm_options_cleanup(&options); } @@ -22872,7 +22872,7 @@ pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fge pm_buffer_free(parser_buffer); pm_parser_free(parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); pm_options_cleanup(&options); } @@ -22895,7 +22895,7 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s pm_serialize_comment_list(&parser.comment_list, buffer); pm_parser_cleanup(&parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); pm_options_cleanup(&options); } diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 405332e339..c92300b33d 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -345,7 +345,7 @@ pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const pm_serialize_metadata(&parser, buffer); pm_parser_cleanup(&parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); pm_options_cleanup(&options); } @@ -369,7 +369,7 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_serialize(&parser, node, buffer); pm_parser_cleanup(&parser); - pm_arena_free(&arena); + pm_arena_cleanup(&arena); pm_options_cleanup(&options); } From 93085a52d999d2e67168d0560f89ba5f75336c08 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:12:15 -0400 Subject: [PATCH 217/289] Make arena fully opaque --- ext/prism/extension.c | 42 ++++++++++++++++---------------- include/prism/arena.h | 43 +++++++++------------------------ include/prism/internal/arena.h | 41 +++++++++++++++++++++++++++++++ include/prism/internal/parser.h | 2 +- src/arena.c | 21 +++++++++++++++- 5 files changed, 95 insertions(+), 54 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 0606b9b238..2c64ff14ed 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -372,8 +372,8 @@ dump_input(pm_string_t *input, const pm_options_t *options) { rb_raise(rb_eNoMemError, "failed to allocate memory"); } - pm_arena_t arena = { 0 }; - pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); + pm_arena_t *arena = pm_arena_new(); + pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(parser); pm_serialize(parser, node, buffer); @@ -381,7 +381,7 @@ dump_input(pm_string_t *input, const pm_options_t *options) { VALUE result = rb_str_new(pm_buffer_value(buffer), pm_buffer_length(buffer)); pm_buffer_free(buffer); pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); return result; } @@ -777,8 +777,8 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) { */ static VALUE parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nodes) { - pm_arena_t arena = { 0 }; - pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); + pm_arena_t *arena = pm_arena_new(); + pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); pm_parser_encoding_changed_callback_set(parser, parse_lex_encoding_changed_callback); VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input)); @@ -828,7 +828,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod } pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); return result; } @@ -886,8 +886,8 @@ lex_file(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input(pm_string_t *input, const pm_options_t *options) { - pm_arena_t arena = { 0 }; - pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); + pm_arena_t *arena = pm_arena_new(); + pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); pm_node_t *node = pm_parse(parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); @@ -902,7 +902,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) { } pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); return result; } @@ -1004,12 +1004,12 @@ parse_file(int argc, VALUE *argv, VALUE self) { */ static void profile_input(pm_string_t *input, const pm_options_t *options) { - pm_arena_t arena = { 0 }; - pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); + pm_arena_t *arena = pm_arena_new(); + pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); pm_parse(parser); pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); } /** @@ -1104,11 +1104,11 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_options_t *options = pm_options_new(); extract_options(options, Qnil, keywords); - pm_arena_t arena = { 0 }; + pm_arena_t *arena = pm_arena_new(); pm_parser_t *parser; pm_buffer_t *buffer = pm_buffer_new(); - pm_node_t *node = pm_parse_stream(&parser, &arena, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, options); + pm_node_t *node = pm_parse_stream(&parser, arena, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, options); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); VALUE source = pm_source_new(parser, encoding, pm_options_freeze_get(options)); @@ -1117,7 +1117,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_buffer_free(buffer); pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); pm_options_free(options); return result; @@ -1128,8 +1128,8 @@ parse_stream(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input_comments(pm_string_t *input, const pm_options_t *options) { - pm_arena_t arena = { 0 }; - pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); + pm_arena_t *arena = pm_arena_new(); + pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); pm_parse(parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); @@ -1138,7 +1138,7 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { VALUE comments = parser_comments(parser, source, pm_options_freeze_get(options)); pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); return comments; } @@ -1250,14 +1250,14 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_input_success_p(pm_string_t *input, const pm_options_t *options) { - pm_arena_t arena = { 0 }; - pm_parser_t *parser = pm_parser_new(&arena, pm_string_source(input), pm_string_length(input), options); + pm_arena_t *arena = pm_arena_new(); + pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); pm_parse(parser); VALUE result = pm_parser_errors_size(parser) == 0 ? Qtrue : Qfalse; pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); return result; } diff --git a/include/prism/arena.h b/include/prism/arena.h index 303ccc554b..1b1729bb24 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -7,48 +7,29 @@ #define PRISM_ARENA_H #include "prism/compiler/exported.h" -#include "prism/compiler/flex_array.h" -#include "prism/compiler/force_inline.h" #include /** - * A single block of memory in the arena. Blocks are linked via prev pointers so - * they can be freed by walking the chain. + * An opaque pointer to an arena that is used for allocations. */ -typedef struct pm_arena_block { - /** The previous block in the chain (for freeing). */ - struct pm_arena_block *prev; - - /** The total usable bytes in data[]. */ - size_t capacity; - - /** The number of bytes consumed so far. */ - size_t used; - - /** The block's data. */ - char data[PM_FLEX_ARRAY_LENGTH]; -} pm_arena_block_t; +typedef struct pm_arena_t pm_arena_t; /** - * A bump allocator. Allocations are made by bumping a pointer within the - * current block. When a block is full, a new block is allocated and linked to - * the previous one. All blocks are freed at once by walking the chain. + * Returns a newly allocated and initialized arena. If the arena cannot be + * allocated, this function aborts the process. + * + * @return A pointer to the newly allocated arena. It is the responsibility of + * the caller to free the arena using pm_arena_free when it is no longer + * needed. */ -typedef struct { - /** The active block (allocate from here). */ - pm_arena_block_t *current; - - /** The number of blocks allocated. */ - size_t block_count; -} pm_arena_t; +PRISM_EXPORTED_FUNCTION pm_arena_t * pm_arena_new(void); /** - * Free all blocks in the arena. After this call, all pointers returned by - * pm_arena_alloc and pm_arena_zalloc are invalid. + * Frees both the held memory and the arena itself. * - * @param arena The arena whose held memory should be freed. + * @param arena The arena to free. */ -PRISM_EXPORTED_FUNCTION void pm_arena_cleanup(pm_arena_t *arena); +PRISM_EXPORTED_FUNCTION void pm_arena_free(pm_arena_t *arena); #endif diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h index 1a393f7bcb..54bbead6bd 100644 --- a/include/prism/internal/arena.h +++ b/include/prism/internal/arena.h @@ -7,6 +7,8 @@ #define PRISM_INTERNAL_ARENA_H #include "prism/compiler/exported.h" +#include "prism/compiler/flex_array.h" +#include "prism/compiler/force_inline.h" #include "prism/compiler/inline.h" #include "prism/arena.h" @@ -14,6 +16,45 @@ #include #include +/** + * A single block of memory in the arena. Blocks are linked via prev pointers so + * they can be freed by walking the chain. + */ +typedef struct pm_arena_block { + /** The previous block in the chain (for freeing). */ + struct pm_arena_block *prev; + + /** The total usable bytes in data[]. */ + size_t capacity; + + /** The number of bytes consumed so far. */ + size_t used; + + /** The block's data. */ + char data[PM_FLEX_ARRAY_LENGTH]; +} pm_arena_block_t; + +/** + * A bump allocator. Allocations are made by bumping a pointer within the + * current block. When a block is full, a new block is allocated and linked to + * the previous one. All blocks are freed at once by walking the chain. + */ +struct pm_arena_t { + /** The active block (allocate from here). */ + pm_arena_block_t *current; + + /** The number of blocks allocated. */ + size_t block_count; +}; + +/** + * Free all blocks in the arena. After this call, all pointers returned by + * pm_arena_alloc and pm_arena_zalloc are invalid. + * + * @param arena The arena whose held memory should be freed. + */ +void pm_arena_cleanup(pm_arena_t *arena); + /** * Ensure the arena has at least `capacity` bytes available in its current * block, allocating a new block if necessary. This allows callers to diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index f6618f67ed..7ea8e9c9cf 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -8,12 +8,12 @@ #include "prism/compiler/accel.h" +#include "prism/internal/arena.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" #include "prism/internal/static_literals.h" -#include "prism/arena.h" #include "prism/ast.h" #include "prism/line_offset_list.h" #include "prism/parser.h" diff --git a/src/arena.c b/src/arena.c index 393725c90f..dd998402f3 100644 --- a/src/arena.c +++ b/src/arena.c @@ -1,4 +1,4 @@ -#include "prism/arena.h" +#include "prism/internal/arena.h" #include "prism/internal/allocator.h" @@ -81,6 +81,16 @@ pm_arena_alloc_slow(pm_arena_t *arena, size_t size) { return block->data; } +/** + * Returns a newly allocated and initialized arena. + */ +pm_arena_t * +pm_arena_new(void) { + pm_arena_t *arena = (pm_arena_t *) xcalloc(1, sizeof(pm_arena_t)); + if (arena == NULL) abort(); + return arena; +} + /** * Free all blocks in the arena. */ @@ -96,3 +106,12 @@ pm_arena_cleanup(pm_arena_t *arena) { *arena = (pm_arena_t) { 0 }; } + +/** + * Frees both the held memory and the arena itself. + */ +void +pm_arena_free(pm_arena_t *arena) { + pm_arena_cleanup(arena); + xfree(arena); +} From 250b2c9ac523a0d04ccaec9a81c0ddb4a85155c9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:30:51 -0400 Subject: [PATCH 218/289] Make the constant pool fully opaque --- include/prism/constant_pool.h | 72 +++++++------------------- include/prism/internal/constant_pool.h | 60 +++++++++++++++++++++ include/prism/internal/parser.h | 1 + include/prism/parser.h | 38 +++++++++++--- src/comments.c | 3 -- src/constant_pool.c | 14 +++++ src/magic_comments.c | 3 -- src/parser.c | 29 ++++++++--- templates/ext/prism/api_node.c.erb | 37 +++++++------ 9 files changed, 166 insertions(+), 91 deletions(-) diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index b1db33f8e3..08a06d1612 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -10,6 +10,8 @@ #ifndef PRISM_CONSTANT_POOL_H #define PRISM_CONSTANT_POOL_H +#include "prism/compiler/exported.h" + #include #include @@ -32,64 +34,26 @@ typedef struct { pm_constant_id_t *ids; } pm_constant_id_list_t; -/** - * The type of bucket in the constant pool hash map. This determines how the - * bucket should be freed. - */ -typedef unsigned int pm_constant_pool_bucket_type_t; - -/** By default, each constant is a slice of the source. */ -static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_DEFAULT = 0; - -/** An owned constant is one for which memory has been allocated. */ -static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_OWNED = 1; - -/** A constant constant is known at compile time. */ -static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_CONSTANT = 2; - -/** A bucket in the hash map. */ -typedef struct { - /** The incremental ID used for indexing back into the pool. */ - unsigned int id: 30; - - /** The type of the bucket, which determines how to free it. */ - pm_constant_pool_bucket_type_t type: 2; - - /** The hash of the bucket. */ - uint32_t hash; - - /** - * A pointer to the start of the string, stored directly in the bucket to - * avoid a pointer chase to the constants array during probing. - */ - const uint8_t *start; - - /** The length of the string. */ - size_t length; -} pm_constant_pool_bucket_t; - /** A constant in the pool which effectively stores a string. */ -typedef struct { - /** A pointer to the start of the string. */ - const uint8_t *start; - - /** The length of the string. */ - size_t length; -} pm_constant_t; +typedef struct pm_constant_t pm_constant_t; /** The overall constant pool, which stores constants found while parsing. */ -typedef struct { - /** The buckets in the hash map. */ - pm_constant_pool_bucket_t *buckets; - - /** The constants that are stored in the buckets. */ - pm_constant_t *constants; +typedef struct pm_constant_pool_t pm_constant_pool_t; - /** The number of buckets in the hash map. */ - uint32_t size; +/** + * Return a raw pointer to the start of a constant. + * + * @param constant The constant to get the start of. + * @return A raw pointer to the start of the constant. + */ +PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *constant); - /** The number of buckets that have been allocated in the hash map. */ - uint32_t capacity; -} pm_constant_pool_t; +/** + * Return the length of a constant. + * + * @param constant The constant to get the length of. + * @return The length of the constant. + */ +PRISM_EXPORTED_FUNCTION size_t pm_constant_length(const pm_constant_t *constant); #endif diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h index 9e7d3cd74b..68d7d63203 100644 --- a/include/prism/internal/constant_pool.h +++ b/include/prism/internal/constant_pool.h @@ -16,6 +16,66 @@ #include +/** A constant in the pool which effectively stores a string. */ +struct pm_constant_t { + /** A pointer to the start of the string. */ + const uint8_t *start; + + /** The length of the string. */ + size_t length; +}; + +/** + * The type of bucket in the constant pool hash map. This determines how the + * bucket should be freed. + */ +typedef unsigned int pm_constant_pool_bucket_type_t; + +/** By default, each constant is a slice of the source. */ +static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_DEFAULT = 0; + +/** An owned constant is one for which memory has been allocated. */ +static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_OWNED = 1; + +/** A constant constant is known at compile time. */ +static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_CONSTANT = 2; + +/** A bucket in the hash map. */ +typedef struct { + /** The incremental ID used for indexing back into the pool. */ + unsigned int id: 30; + + /** The type of the bucket, which determines how to free it. */ + pm_constant_pool_bucket_type_t type: 2; + + /** The hash of the bucket. */ + uint32_t hash; + + /** + * A pointer to the start of the string, stored directly in the bucket to + * avoid a pointer chase to the constants array during probing. + */ + const uint8_t *start; + + /** The length of the string. */ + size_t length; +} pm_constant_pool_bucket_t; + +/** The overall constant pool, which stores constants found while parsing. */ +struct pm_constant_pool_t { + /** The buckets in the hash map. */ + pm_constant_pool_bucket_t *buckets; + + /** The constants that are stored in the buckets. */ + pm_constant_t *constants; + + /** The number of buckets in the hash map. */ + uint32_t size; + + /** The number of buckets that have been allocated in the hash map. */ + uint32_t capacity; +}; + /** * When we allocate constants into the pool, we reserve 0 to mean that the slot * is not yet filled. This constant is reused in other places to indicate the diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index 7ea8e9c9cf..354b5adef4 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -9,6 +9,7 @@ #include "prism/compiler/accel.h" #include "prism/internal/arena.h" +#include "prism/internal/constant_pool.h" #include "prism/internal/encoding.h" #include "prism/internal/list.h" #include "prism/internal/options.h" diff --git a/include/prism/parser.h b/include/prism/parser.h index f15ddd8901..1f0b7fc0f3 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -99,14 +99,6 @@ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t * */ PRISM_EXPORTED_FUNCTION const pm_line_offset_list_t * pm_parser_line_offsets(const pm_parser_t *parser); -/** - * Returns the constant pool associated with the given parser. - * - * @param parser the parser whose constant pool we want to get - * @return the constant pool associated with the given parser - */ -PRISM_EXPORTED_FUNCTION const pm_constant_pool_t * pm_parser_constant_pool(const pm_parser_t *parser); - /** * Returns the location of the __DATA__ section that is associated with the * given parser. @@ -237,4 +229,34 @@ PRISM_EXPORTED_FUNCTION void pm_parser_errors_each(const pm_parser_t *parser, pm */ PRISM_EXPORTED_FUNCTION void pm_parser_warnings_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data); +/** + * Returns the number of constants in the constant pool associated with the + * given parser. + * + * @param parser the parser whose constant pool constants we want to get the + * size of + * @return the number of constants in the constant pool associated with the + * given parser + */ +PRISM_EXPORTED_FUNCTION size_t pm_parser_constants_size(const pm_parser_t *parser); + +/** + * A callback function that can be used to process constants found while + * parsing. + */ +typedef void (*pm_constant_callback_t)(const pm_constant_t *constant, void *data); + +/** + * Iterates over the constants in the constant pool associated with the given + * parser and calls the given callback for each constant. + * + * @param parser the parser whose constants we want to iterate over + * @param callback the callback function to call for each constant. This function + * will be passed a pointer to the constant and the data parameter passed to + * this function. + * @param data the data to pass to the callback function for each constant. This + * can be NULL if no data needs to be passed to the callback function. + */ +PRISM_EXPORTED_FUNCTION void pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callback, void *data); + #endif diff --git a/src/comments.c b/src/comments.c index be535d2f7a..5c2898a43f 100644 --- a/src/comments.c +++ b/src/comments.c @@ -1,10 +1,7 @@ #include "prism/internal/comments.h" -#include "prism/internal/allocator.h" #include "prism/internal/parser.h" -#include - /** * Returns the location associated with the given comment. */ diff --git a/src/constant_pool.c b/src/constant_pool.c index 3f0baac702..90201ebb8e 100644 --- a/src/constant_pool.c +++ b/src/constant_pool.c @@ -344,3 +344,17 @@ pm_constant_pool_insert_constant(pm_arena_t *arena, pm_constant_pool_t *pool, co return pm_constant_pool_insert(arena, pool, start, length, PM_CONSTANT_POOL_BUCKET_CONSTANT); } +/** + * Return a raw pointer to the start of a constant. + */ +const uint8_t * +pm_constant_start(const pm_constant_t *constant) { + return constant->start; +} + +/** + * Return the length of a constant. + */ +size_t pm_constant_length(const pm_constant_t *constant) { + return constant->length; +} diff --git a/src/magic_comments.c b/src/magic_comments.c index 6648010061..0b2e1d3049 100644 --- a/src/magic_comments.c +++ b/src/magic_comments.c @@ -1,10 +1,7 @@ #include "prism/internal/magic_comments.h" -#include "prism/internal/allocator.h" #include "prism/internal/parser.h" -#include - /** * Returns the location associated with the given magic comment key. */ diff --git a/src/parser.c b/src/parser.c index 27c9641f83..68778487e8 100644 --- a/src/parser.c +++ b/src/parser.c @@ -80,14 +80,6 @@ pm_parser_line_offsets(const pm_parser_t *parser) { return &parser->line_offsets; } -/** - * Returns the constant pool associated with the given parser. - */ -const pm_constant_pool_t * -pm_parser_constant_pool(const pm_parser_t *parser) { - return &parser->constant_pool; -} - /** * Returns the location of the __DATA__ section that is associated with the * given parser, if it exists. @@ -204,3 +196,24 @@ void pm_parser_warnings_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data) { pm_parser_diagnostics_each(&parser->warning_list, callback, data); } + +/** + * Returns the number of constants in the constant pool associated with the + * given parser. + */ +size_t +pm_parser_constants_size(const pm_parser_t *parser) { + return parser->constant_pool.size; +} + +/** + * Iterates over the constants in the constant pool associated with the given + * parser and calls the given callback for each constant. + */ +void +pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callback, void *data) { + for (uint32_t index = 0; index < parser->constant_pool.size; index++) { + const pm_constant_t *constant = &parser->constant_pool.constants[index]; + callback(constant, data); + } +} diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index fffb2bebb5..ca793b471c 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -122,26 +122,33 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) { return visit; } -VALUE -pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) { - const pm_constant_pool_t *constant_pool = pm_parser_constant_pool(parser); - VALUE constants = rb_ary_new_capa(constant_pool->size); - - for (uint32_t index = 0; index < constant_pool->size; index++) { - pm_constant_t *constant = &constant_pool->constants[index]; - int state = 0; +typedef struct { + VALUE constants; + rb_encoding *encoding; +} pm_ast_constants_each_data_t; - VALUE string = rb_enc_str_new((const char *) constant->start, constant->length, encoding); - VALUE value = rb_protect(rb_str_intern, string, &state); +static void +pm_ast_constants_each(const pm_constant_t *constant, void *data) { + pm_ast_constants_each_data_t *constants_data = (pm_ast_constants_each_data_t *) data; + int state = 0; - if (state != 0) { - value = ID2SYM(rb_intern_const("?")); - rb_set_errinfo(Qnil); - } + VALUE string = rb_enc_str_new((const char *) pm_constant_start(constant), pm_constant_length(constant), constants_data->encoding); + VALUE value = rb_protect(rb_str_intern, string, &state); - rb_ary_push(constants, value); + if (state != 0) { + value = ID2SYM(rb_intern_const("?")); + rb_set_errinfo(Qnil); } + rb_ary_push(constants_data->constants, value); +} + +VALUE +pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) { + VALUE constants = rb_ary_new_capa(pm_parser_constants_size(parser)); + pm_ast_constants_each_data_t constants_data = { .constants = constants, .encoding = encoding }; + pm_parser_constants_each(parser, pm_ast_constants_each, &constants_data); + pm_node_stack_node_t *node_stack = NULL; pm_node_stack_push(&node_stack, node); VALUE value_stack = rb_ary_new(); From fb0d1369f423310fb2297de20a67faedd1ab22c8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:32:38 -0400 Subject: [PATCH 219/289] Inline comments and magic comments, they do not need their own TUs --- prism.gemspec | 2 -- src/comments.c | 19 ------------------- src/magic_comments.c | 19 ------------------- src/parser.c | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 40 deletions(-) delete mode 100644 src/comments.c delete mode 100644 src/magic_comments.c diff --git a/prism.gemspec b/prism.gemspec index 41eb9888ca..d3fd8da546 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -189,14 +189,12 @@ Gem::Specification.new do |spec| "src/arena.c", "src/buffer.c", "src/char.c", - "src/comments.c", "src/constant_pool.c", "src/diagnostic.c", "src/encoding.c", "src/integer.c", "src/line_offset_list.c", "src/list.c", - "src/magic_comments.c", "src/memchr.c", "src/node.c", "src/options.c", diff --git a/src/comments.c b/src/comments.c deleted file mode 100644 index 5c2898a43f..0000000000 --- a/src/comments.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "prism/internal/comments.h" - -#include "prism/internal/parser.h" - -/** - * Returns the location associated with the given comment. - */ -pm_location_t -pm_comment_location(const pm_comment_t *comment) { - return comment->location; -} - -/** - * Returns the type associated with the given comment. - */ -pm_comment_type_t -pm_comment_type(const pm_comment_t *comment) { - return comment->type; -} diff --git a/src/magic_comments.c b/src/magic_comments.c deleted file mode 100644 index 0b2e1d3049..0000000000 --- a/src/magic_comments.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "prism/internal/magic_comments.h" - -#include "prism/internal/parser.h" - -/** - * Returns the location associated with the given magic comment key. - */ -pm_location_t -pm_magic_comment_key(const pm_magic_comment_t *magic_comment) { - return magic_comment->key; -} - -/** - * Returns the location associated with the given magic comment value. - */ -pm_location_t -pm_magic_comment_value(const pm_magic_comment_t *magic_comment) { - return magic_comment->value; -} diff --git a/src/parser.c b/src/parser.c index 68778487e8..b61fb6ce03 100644 --- a/src/parser.c +++ b/src/parser.c @@ -109,6 +109,22 @@ pm_parser_lex_state(const pm_parser_t *parser) { return (int) parser->lex_state; } +/** + * Returns the location associated with the given comment. + */ +pm_location_t +pm_comment_location(const pm_comment_t *comment) { + return comment->location; +} + +/** + * Returns the type associated with the given comment. + */ +pm_comment_type_t +pm_comment_type(const pm_comment_t *comment) { + return comment->type; +} + /** * Returns the number of comments associated with the given parser. */ @@ -131,6 +147,22 @@ pm_parser_comments_each(const pm_parser_t *parser, pm_comment_callback_t callbac } } +/** + * Returns the location associated with the given magic comment key. + */ +pm_location_t +pm_magic_comment_key(const pm_magic_comment_t *magic_comment) { + return magic_comment->key; +} + +/** + * Returns the location associated with the given magic comment value. + */ +pm_location_t +pm_magic_comment_value(const pm_magic_comment_t *magic_comment) { + return magic_comment->value; +} + /** * Returns the number of magic comments associated with the given parser. */ From aa84fd5f5311c02abc0203f0d963f361b963d493 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:36:32 -0400 Subject: [PATCH 220/289] Cleanup --- cpp/test.cpp | 6 +++--- include/prism.h | 14 +++++++------- include/prism/magic_comments.h | 35 ---------------------------------- include/prism/node.h | 6 +++--- 4 files changed, 13 insertions(+), 48 deletions(-) diff --git a/cpp/test.cpp b/cpp/test.cpp index 916d10381d..3d21c99769 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -5,8 +5,8 @@ extern "C" { #include int main() { - pm_arena_t arena = { 0 }; - pm_parser_t *parser = pm_parser_new(&arena, reinterpret_cast("1 + 2"), 5, NULL); + pm_arena_t *arena = pm_arena_new(); + pm_parser_t *parser = pm_parser_new(arena, reinterpret_cast("1 + 2"), 5, NULL); pm_node_t *root = pm_parse(parser); pm_buffer_t *buffer = pm_buffer_new(); @@ -18,7 +18,7 @@ int main() { pm_buffer_free(buffer); pm_parser_free(parser); - pm_arena_cleanup(&arena); + pm_arena_free(arena); return 0; } diff --git a/include/prism.h b/include/prism.h index 5a8b835978..64c1657113 100644 --- a/include/prism.h +++ b/include/prism.h @@ -260,20 +260,20 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * * `pm_parser_new()` - allocate and initialize a new parser * * `pm_parse()` - parse and return the root node * * `pm_parser_free()` - free the parser and its internal memory - * * `pm_arena_cleanup()` - free all AST-lifetime memory + * * `pm_arena_free()` - free all AST-lifetime memory * * Putting all of this together would look something like: * * ```c * void parse(const uint8_t *source, size_t length) { - * pm_arena_t arena = { 0 }; - * pm_parser_t *parser = pm_parser_new(&arena, source, length, NULL); + * pm_arena_t *arena = pm_arena_new(); + * pm_parser_t *parser = pm_parser_new(arena, source, length, NULL); * * pm_node_t *root = pm_parse(parser); * printf("PARSED!\n"); * * pm_parser_free(parser); - * pm_arena_cleanup(&arena); + * pm_arena_free(arena); * } * ``` * @@ -315,8 +315,8 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * * ```c * void prettyprint(const uint8_t *source, size_t length) { - * pm_arena_t arena = { 0 }; - * pm_parser_t *parser = pm_parser_new(&arena, source, length, NULL); + * pm_arena_t *arena = pm_arena_new(); + * pm_parser_t *parser = pm_parser_new(arena, source, length, NULL); * * pm_node_t *root = pm_parse(parser); * pm_buffer_t *buffer = pm_buffer_new(); @@ -326,7 +326,7 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * * pm_buffer_free(buffer); * pm_parser_free(parser); - * pm_arena_cleanup(&arena); + * pm_arena_free(arena); * } * ``` */ diff --git a/include/prism/magic_comments.h b/include/prism/magic_comments.h index 10f9cfa32d..a19ecedb74 100644 --- a/include/prism/magic_comments.h +++ b/include/prism/magic_comments.h @@ -29,39 +29,4 @@ PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_key(const pm_magic_commen */ PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_value(const pm_magic_comment_t *comment); -/* An opaque pointer to an iterator that can be used to iterate over the - * magic comments associated with a parser. */ -typedef struct pm_magic_comments_iter_t pm_magic_comments_iter_t; - -/** - * Returns the number of magic comments associated with the magic comments iterator. - * - * @param iter the iterator to get the number of magic comments from - * @return the number of magic comments associated with the magic comments iterator - * - * \public \memberof pm_magic_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION size_t pm_magic_comments_iter_size(const pm_magic_comments_iter_t *iter); - -/** - * Returns the next magic comment in the iteration, or NULL if there are no more - * magic comments. - * - * @param iter the iterator to get the next magic comment from - * @return the next magic comment in the iteration, or NULL if there are no more - * magic comments. - * - * \public \memberof pm_magic_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION const pm_magic_comment_t * pm_magic_comments_iter_next(pm_magic_comments_iter_t *iter); - -/** - * Frees the memory associated with the given magic comments iterator. - * - * @param iter the iterator to free - * - * \public \memberof pm_magic_comments_iter_t - */ -PRISM_EXPORTED_FUNCTION void pm_magic_comments_iter_free(pm_magic_comments_iter_t *iter); - #endif diff --git a/include/prism/node.h b/include/prism/node.h index bfda2a6a52..5056bfbb26 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -54,10 +54,10 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * const char *source = "1 + 2; 3 + 4"; * size_t size = strlen(source); * - * pm_arena_t arena = { 0 }; + * pm_arena_t *arena = pm_arena_new(); * pm_options_t *options = pm_options_new(); * - * pm_parser_t *parser = pm_parser_new(&arena, (const uint8_t *) source, size, options); + * pm_parser_t *parser = pm_parser_new(arena, (const uint8_t *) source, size, options); * * size_t indent = 0; * pm_node_t *node = pm_parse(parser); @@ -67,7 +67,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * * pm_parser_free(parser); * pm_options_free(options); - * pm_arena_cleanup(&arena); + * pm_arena_free(arena); * * return EXIT_SUCCESS; * } From 879139efc9e2e153250b0a306752f40ff11e5263 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:43:18 -0400 Subject: [PATCH 221/289] pm_parser_init and pm_parser_cleanup -> internal --- include/prism.h | 38 ++++++--------------------------- include/prism/internal/parser.h | 23 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/include/prism.h b/include/prism.h index 64c1657113..2fdb048519 100644 --- a/include/prism.h +++ b/include/prism.h @@ -28,21 +28,6 @@ extern "C" { */ PRISM_EXPORTED_FUNCTION const char * pm_version(void); -/** - * Initialize a parser with the given start and end pointers. - * - * @param arena The arena to use for all AST-lifetime allocations. It is caller- - * owned and must outlive the parser. - * @param parser The parser to initialize. - * @param source The source to parse. - * @param size The size of the source. - * @param options The optional options to use when parsing. These options must - * live for the whole lifetime of this parser. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); - /** * Allocate and initialize a parser with the given start and end pointers. * @@ -59,18 +44,6 @@ PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_arena_t *arena, pm_parser_t *pars */ PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options); -/** - * Free the memory held by the given parser. - * - * This does not free the `pm_options_t` object that was used to initialize the - * parser. - * - * @param parser The parser whose held memory should be freed. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION void pm_parser_cleanup(pm_parser_t *parser); - /** * Free both the memory held by the given parser and the parser itself. * @@ -120,9 +93,9 @@ typedef int (pm_parse_stream_feof_t)(void *stream); */ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); -// We optionally support serializing to a binary string. For systems that don't -// want or need this functionality, it can be turned off with the -// PRISM_EXCLUDE_SERIALIZATION define. +/* We optionally support serializing to a binary string. For systems that do not + * want or need this functionality, it can be turned off with the + * PRISM_EXCLUDE_SERIALIZATION define. */ #ifndef PRISM_EXCLUDE_SERIALIZATION /** @@ -215,8 +188,9 @@ PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_ty */ const char * pm_token_type_human(pm_token_type_t token_type); -// We optionally support dumping to JSON. For systems that don't want or need -// this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. +/* We optionally support dumping to JSON. For systems that don't want or need + * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. + */ #ifndef PRISM_EXCLUDE_JSON /** diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index 354b5adef4..c731e629db 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -934,4 +934,27 @@ struct pm_parser_t { #endif }; +/** + * Initialize a parser with the given start and end pointers. + * + * @param arena The arena to use for all AST-lifetime allocations. It is caller- + * owned and must outlive the parser. + * @param parser The parser to initialize. + * @param source The source to parse. + * @param size The size of the source. + * @param options The optional options to use when parsing. These options must + * live for the whole lifetime of this parser. + */ +void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); + +/** + * Free the memory held by the given parser. + * + * This does not free the `pm_options_t` object that was used to initialize the + * parser. + * + * @param parser The parser whose held memory should be freed. + */ +void pm_parser_cleanup(pm_parser_t *parser); + #endif From 456167dccd910d92bb53ca139567bafcf41fbf86 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 13:55:33 -0400 Subject: [PATCH 222/289] Move even more headers into their own spots --- include/prism.h | 172 ++---------------------------- include/prism/json.h | 31 ++++++ include/prism/parser.h | 26 +++++ include/prism/serialize.h | 86 +++++++++++++++ include/prism/stream.h | 44 ++++++++ src/prism.c | 4 +- templates/include/prism/ast.h.erb | 16 +++ 7 files changed, 213 insertions(+), 166 deletions(-) create mode 100644 include/prism/json.h create mode 100644 include/prism/serialize.h create mode 100644 include/prism/stream.h diff --git a/include/prism.h b/include/prism.h index 2fdb048519..64674d154a 100644 --- a/include/prism.h +++ b/include/prism.h @@ -14,10 +14,13 @@ extern "C" { #include "prism/ast.h" #include "prism/diagnostic.h" #include "prism/excludes.h" +#include "prism/json.h" #include "prism/node.h" #include "prism/options.h" #include "prism/parser.h" #include "prism/prettyprint.h" +#include "prism/serialize.h" +#include "prism/stream.h" #include "prism/string_query.h" #include "prism/version.h" @@ -28,31 +31,6 @@ extern "C" { */ PRISM_EXPORTED_FUNCTION const char * pm_version(void); -/** - * Allocate and initialize a parser with the given start and end pointers. - * - * @param arena The arena to use for all AST-lifetime allocations. It is caller- - * owned and must outlive the parser. - * @param source The source to parse. - * @param size The size of the source. - * @param options The optional options to use when parsing. These options must - * live for the whole lifetime of this parser. - * @return The initialized parser. It is the responsibility of the caller to - * free the parser with `pm_parser_free()`. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options); - -/** - * Free both the memory held by the given parser and the parser itself. - * - * @param parser The parser to free. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser); - /** * Initiate the parser with the given parser. * @@ -63,105 +41,6 @@ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser); */ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser); -/** - * This function is used in pm_parse_stream() to retrieve a line of input from a - * stream. It closely mirrors that of fgets so that fgets can be used as the - * default implementation. - */ -typedef char * (pm_parse_stream_fgets_t)(char *string, int size, void *stream); - -/** - * This function is used in pm_parse_stream to check whether a stream is EOF. - * It closely mirrors that of feof so that feof can be used as the - * default implementation. - */ -typedef int (pm_parse_stream_feof_t)(void *stream); - -/** - * Parse a stream of Ruby source and return the tree. - * - * @param parser The out parameter to write the parser to. - * @param arena The arena to use for all AST-lifetime allocations. - * @param buffer The buffer to use. - * @param stream The stream to parse. - * @param stream_fgets The function to use to read from the stream. - * @param stream_feof The function to use to determine if the stream has hit eof. - * @param options The optional options to use when parsing. - * @return The AST representing the source. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); - -/* We optionally support serializing to a binary string. For systems that do not - * want or need this functionality, it can be turned off with the - * PRISM_EXCLUDE_SERIALIZATION define. */ -#ifndef PRISM_EXCLUDE_SERIALIZATION - -/** - * Parse and serialize the AST represented by the source that is read out of the - * given stream into to the given buffer. - * - * @param buffer The buffer to serialize to. - * @param stream The stream to parse. - * @param stream_fgets The function to use to read from the stream. - * @param stream_feof The function to use to tell if the stream has hit eof. - * @param data The optional data to pass to the parser. - */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data); - -/** - * Serialize the AST represented by the given node to the given buffer. - * - * @param parser The parser to serialize. - * @param node The node to serialize. - * @param buffer The buffer to serialize to. - */ -PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer); - -/** - * Parse the given source to the AST and dump the AST to the given buffer. - * - * @param buffer The buffer to serialize to. - * @param source The source to parse. - * @param size The size of the source. - * @param data The optional data to pass to the parser. - */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); - -/** - * Parse and serialize the comments in the given source to the given buffer. - * - * @param buffer The buffer to serialize to. - * @param source The source to parse. - * @param size The size of the source. - * @param data The optional data to pass to the parser. - */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); - -/** - * Lex the given source and serialize to the given buffer. - * - * @param source The source to lex. - * @param size The size of the source. - * @param buffer The buffer to serialize to. - * @param data The optional data to pass to the lexer. - */ -PRISM_EXPORTED_FUNCTION void pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); - -/** - * Parse and serialize both the AST and the tokens represented by the given - * source to the given buffer. - * - * @param buffer The buffer to serialize to. - * @param source The source to parse. - * @param size The size of the source. - * @param data The optional data to pass to the parser. - */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); - -#endif - /** * Parse the source and return true if it parses without errors or warnings. * @@ -172,38 +51,6 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const u */ PRISM_EXPORTED_FUNCTION bool pm_parse_success_p(const uint8_t *source, size_t size, const char *data); -/** - * Returns a string representation of the given token type. - * - * @param token_type The token type to convert to a string. - * @return A string representation of the given token type. - */ -PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_type); - -/** - * Returns the human name of the given token type. - * - * @param token_type The token type to convert to a human name. - * @return The human name of the given token type. - */ -const char * pm_token_type_human(pm_token_type_t token_type); - -/* We optionally support dumping to JSON. For systems that don't want or need - * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. - */ -#ifndef PRISM_EXCLUDE_JSON - -/** - * Dump JSON to the given buffer. - * - * @param buffer The buffer to serialize to. - * @param parser The parser that parsed the node. - * @param node The node to serialize. - */ -PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node); - -#endif - /** * @mainpage * @@ -226,11 +73,10 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * * @section parsing Parsing * - * In order to parse Ruby code, the structures and functions that you're going - * to want to use and be aware of are: + * In order to parse Ruby code, the functions that you are going to want to use + * and be aware of are: * - * * `pm_arena_t` - the arena allocator for AST-lifetime memory - * * `pm_parser_t` - the main parser structure + * * `pm_arena_new()` - create a new arena to hold all AST-lifetime allocations * * `pm_parser_new()` - allocate and initialize a new parser * * `pm_parse()` - parse and return the root node * * `pm_parser_free()` - free the parser and its internal memory @@ -260,13 +106,11 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t * Prism provides the ability to serialize the AST and its related metadata into * a binary format. This format is designed to be portable to different * languages and runtimes so that you only need to make one FFI call in order to - * parse Ruby code. The structures and functions that you're going to want to - * use and be aware of are: + * parse Ruby code. The functions that you are going to want to use and be + * aware of are: * - * * `pm_buffer_t` - an opaque buffer object that will hold the serialized AST * * `pm_buffer_new()` - create a new buffer * * `pm_buffer_free()` - free the buffer and its internal memory - * * `pm_serialize()` - serialize the AST into a buffer * * `pm_serialize_parse()` - parse and serialize the AST into a buffer * * Putting all of this together would look something like: diff --git a/include/prism/json.h b/include/prism/json.h new file mode 100644 index 0000000000..cc2f6f3bb1 --- /dev/null +++ b/include/prism/json.h @@ -0,0 +1,31 @@ +/** + * @file json.h + */ +#ifndef PRISM_JSON_H +#define PRISM_JSON_H + +#include "prism/excludes.h" + +/* We optionally support dumping to JSON. For systems that don't want or need + * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. + */ +#ifndef PRISM_EXCLUDE_JSON + +#include "prism/compiler/exported.h" + +#include "prism/ast.h" +#include "prism/buffer.h" +#include "prism/parser.h" + +/** + * Dump JSON to the given buffer. + * + * @param buffer The buffer to serialize to. + * @param parser The parser that parsed the node. + * @param node The node to serialize. + */ +PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node); + +#endif + +#endif diff --git a/include/prism/parser.h b/include/prism/parser.h index 1f0b7fc0f3..f49155799d 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -11,12 +11,38 @@ #include "prism/diagnostic.h" #include "prism/line_offset_list.h" #include "prism/magic_comments.h" +#include "prism/options.h" /** * The parser used to parse Ruby source. */ typedef struct pm_parser_t pm_parser_t; +/** + * Allocate and initialize a parser with the given start and end pointers. + * + * @param arena The arena to use for all AST-lifetime allocations. It is caller- + * owned and must outlive the parser. + * @param source The source to parse. + * @param size The size of the source. + * @param options The optional options to use when parsing. These options must + * live for the whole lifetime of this parser. + * @return The initialized parser. It is the responsibility of the caller to + * free the parser with `pm_parser_free()`. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options); + +/** + * Free both the memory held by the given parser and the parser itself. + * + * @param parser The parser to free. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser); + /** * When the encoding that is being used to parse the source is changed by prism, * we provide the ability here to call out to a user-defined function. diff --git a/include/prism/serialize.h b/include/prism/serialize.h new file mode 100644 index 0000000000..b2e93e5e9b --- /dev/null +++ b/include/prism/serialize.h @@ -0,0 +1,86 @@ +/** + * @file serialize.h + * + * The functions related to serializing the AST to a binary format. + */ +#ifndef PRISM_SERIALIZE_H +#define PRISM_SERIALIZE_H + +#include "prism/excludes.h" + +/* We optionally support serializing to a binary string. For systems that do not + * want or need this functionality, it can be turned off with the + * PRISM_EXCLUDE_SERIALIZATION define. */ +#ifndef PRISM_EXCLUDE_SERIALIZATION + +#include "prism/compiler/exported.h" + +#include "prism/buffer.h" +#include "prism/parser.h" +#include "prism/stream.h" + +/** + * Serialize the AST represented by the given node to the given buffer. + * + * @param parser The parser to serialize. + * @param node The node to serialize. + * @param buffer The buffer to serialize to. + */ +PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer); + +/** + * Parse the given source to the AST and dump the AST to the given buffer. + * + * @param buffer The buffer to serialize to. + * @param source The source to parse. + * @param size The size of the source. + * @param data The optional data to pass to the parser. + */ +PRISM_EXPORTED_FUNCTION void pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); + +/** + * Parse and serialize the AST represented by the source that is read out of the + * given stream into to the given buffer. + * + * @param buffer The buffer to serialize to. + * @param stream The stream to parse. + * @param stream_fgets The function to use to read from the stream. + * @param stream_feof The function to use to tell if the stream has hit eof. + * @param data The optional data to pass to the parser. + */ +PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data); + +/** + * Parse and serialize the comments in the given source to the given buffer. + * + * @param buffer The buffer to serialize to. + * @param source The source to parse. + * @param size The size of the source. + * @param data The optional data to pass to the parser. + */ +PRISM_EXPORTED_FUNCTION void pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); + +/** + * Lex the given source and serialize to the given buffer. + * + * @param source The source to lex. + * @param size The size of the source. + * @param buffer The buffer to serialize to. + * @param data The optional data to pass to the lexer. + */ +PRISM_EXPORTED_FUNCTION void pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); + +/** + * Parse and serialize both the AST and the tokens represented by the given + * source to the given buffer. + * + * @param buffer The buffer to serialize to. + * @param source The source to parse. + * @param size The size of the source. + * @param data The optional data to pass to the parser. + */ +PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); + +#endif + +#endif diff --git a/include/prism/stream.h b/include/prism/stream.h new file mode 100644 index 0000000000..9ed94f58e9 --- /dev/null +++ b/include/prism/stream.h @@ -0,0 +1,44 @@ +/** + * @file stream.h + * + * Functions for parsing streams. + */ +#ifndef PRISM_STREAM_H +#define PRISM_STREAM_H + +#include "prism/compiler/exported.h" + +#include "prism/arena.h" +#include "prism/buffer.h" +#include "prism/options.h" +#include "prism/parser.h" + +/** + * This function is used in pm_parse_stream() to retrieve a line of input from a + * stream. It closely mirrors that of fgets so that fgets can be used as the + * default implementation. + */ +typedef char * (pm_parse_stream_fgets_t)(char *string, int size, void *stream); + +/** + * This function is used in pm_parse_stream to check whether a stream is EOF. + * It closely mirrors that of feof so that feof can be used as the + * default implementation. + */ +typedef int (pm_parse_stream_feof_t)(void *stream); + +/** + * Parse a stream of Ruby source and return the tree. + * + * @param parser The out parameter to write the parser to. + * @param arena The arena to use for all AST-lifetime allocations. + * @param buffer The buffer to use. + * @param stream The stream to parse. + * @param stream_fgets The function to use to read from the stream. + * @param stream_feof The function to use to determine if the stream has hit eof. + * @param options The optional options to use when parsing. + * @return The AST representing the source. + */ +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); + +#endif diff --git a/src/prism.c b/src/prism.c index fb2b67a779..3f8e3ad870 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1,5 +1,3 @@ -#include "prism.h" - #include "prism/compiler/accel.h" #include "prism/compiler/fallthrough.h" #include "prism/compiler/unused.h" @@ -30,6 +28,8 @@ #include "prism/internal/strpbrk.h" #include "prism/excludes.h" +#include "prism/serialize.h" +#include "prism/version.h" #include #include diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 3a949f1000..f08e017fc0 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -47,6 +47,22 @@ typedef struct { const uint8_t *end; } pm_token_t; +/** + * Returns a string representation of the given token type. + * + * @param token_type The token type to convert to a string. + * @return A string representation of the given token type. + */ +PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_type); + +/** + * Returns the human name of the given token type. + * + * @param token_type The token type to convert to a human name. + * @return The human name of the given token type. + */ +const char * pm_token_type_human(pm_token_type_t token_type); + /** * This struct represents a slice in the source code, defined by an offset and * a length. Note that we have confirmation that we can represent all locations From 3b098866330fb8ae6175f01c5f160f6950ae5eb2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 14:04:05 -0400 Subject: [PATCH 223/289] Move JSON to its own TU --- include/prism.h | 2 +- include/prism/internal/encoding.h | 4 +- src/json.c | 5723 +++++++++++++++++++++++++++++ templates/src/json.c.erb | 130 + templates/src/node.c.erb | 127 - templates/src/prettyprint.c.erb | 14 +- templates/template.rb | 1 + 7 files changed, 5862 insertions(+), 139 deletions(-) create mode 100644 src/json.c create mode 100644 templates/src/json.c.erb diff --git a/include/prism.h b/include/prism.h index 64674d154a..b344a43691 100644 --- a/include/prism.h +++ b/include/prism.h @@ -12,8 +12,8 @@ extern "C" { #include "prism/arena.h" #include "prism/ast.h" +#include "prism/buffer.h" #include "prism/diagnostic.h" -#include "prism/excludes.h" #include "prism/json.h" #include "prism/node.h" #include "prism/options.h" diff --git a/include/prism/internal/encoding.h b/include/prism/internal/encoding.h index eb68ad6250..409345fd7f 100644 --- a/include/prism/internal/encoding.h +++ b/include/prism/internal/encoding.h @@ -136,8 +136,8 @@ typedef enum { PM_ENCODING_EUC_JP, PM_ENCODING_WINDOWS_31J, -// We optionally support excluding the full set of encodings to only support the -// minimum necessary to process Ruby code without encoding comments. +/* We optionally support excluding the full set of encodings to only support the + * minimum necessary to process Ruby code without encoding comments. */ #ifndef PRISM_ENCODING_EXCLUDE_FULL PM_ENCODING_BIG5, PM_ENCODING_BIG5_HKSCS, diff --git a/src/json.c b/src/json.c new file mode 100644 index 0000000000..0d72ca8368 --- /dev/null +++ b/src/json.c @@ -0,0 +1,5723 @@ +/*----------------------------------------------------------------------------*/ +/* This file is generated by the templates/template.rb script and should not */ +/* be modified manually. See */ +/* templates/src/json.c.erb */ +/* if you are looking to modify the */ +/* template */ +/*----------------------------------------------------------------------------*/ + +#include "prism/json.h" + +/* We optionally support dumping to JSON. For systems that don not want or need + * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. + */ +#ifndef PRISM_EXCLUDE_JSON + +#include "prism/internal/buffer.h" +#include "prism/internal/constant_pool.h" +#include "prism/internal/integer.h" +#include "prism/internal/parser.h" + +#include + +static void +pm_dump_json_constant(pm_buffer_t *buffer, const pm_parser_t *parser, pm_constant_id_t constant_id) { + const pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id); + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, constant->start, constant->length, PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); +} + +static void +pm_dump_json_location(pm_buffer_t *buffer, const pm_location_t *location) { + pm_buffer_append_format(buffer, "{\"start\":%" PRIu32 ",\"length\":%" PRIu32 "}", location->start, location->length); +} + +/** + * Dump JSON to the given buffer. + */ +void +pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_ALIAS_GLOBAL_VARIABLE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"AliasGlobalVariableNode\",\"location\":", 45); + + const pm_alias_global_variable_node_t *cast = (const pm_alias_global_variable_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the new_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"new_name\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->new_name); + + // Dump the old_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"old_name\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->old_name); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ALIAS_METHOD_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"AliasMethodNode\",\"location\":", 37); + + const pm_alias_method_node_t *cast = (const pm_alias_method_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the new_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"new_name\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->new_name); + + // Dump the old_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"old_name\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->old_name); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ALTERNATION_PATTERN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"AlternationPatternNode\",\"location\":", 44); + + const pm_alternation_pattern_node_t *cast = (const pm_alternation_pattern_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the left field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"left\":", 7); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); + + // Dump the right field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"right\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_AND_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"AndNode\",\"location\":", 29); + + const pm_and_node_t *cast = (const pm_and_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the left field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"left\":", 7); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); + + // Dump the right field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"right\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ARGUMENTS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ArgumentsNode\",\"location\":", 35); + + const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ArgumentsNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"CONTAINS_FORWARDING\"", 21); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"CONTAINS_KEYWORDS\"", 19); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"CONTAINS_KEYWORD_SPLAT\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"CONTAINS_SPLAT\"", 16); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"CONTAINS_MULTIPLE_SPLATS\"", 26); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + const pm_node_list_t *arguments = &cast->arguments; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < arguments->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, arguments->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ARRAY_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ArrayNode\",\"location\":", 31); + + const pm_array_node_t *cast = (const pm_array_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ArrayNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"CONTAINS_SPLAT\"", 16); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the elements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"elements\":", 11); + const pm_node_list_t *elements = &cast->elements; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < elements->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, elements->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ARRAY_PATTERN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ArrayPatternNode\",\"location\":", 38); + + const pm_array_pattern_node_t *cast = (const pm_array_pattern_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the constant field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"constant\":", 11); + if (cast->constant != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the requireds field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"requireds\":", 12); + const pm_node_list_t *requireds = &cast->requireds; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < requireds->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, requireds->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the rest field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rest\":", 7); + if (cast->rest != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the posts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"posts\":", 8); + const pm_node_list_t *posts = &cast->posts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < posts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, posts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ASSOC_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"AssocNode\",\"location\":", 31); + + const pm_assoc_node_t *cast = (const pm_assoc_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the key field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"key\":", 6); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->key); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + if (cast->operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ASSOC_SPLAT_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"AssocSplatNode\",\"location\":", 36); + + const pm_assoc_splat_node_t *cast = (const pm_assoc_splat_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + if (cast->value != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BACK_REFERENCE_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BackReferenceReadNode\",\"location\":", 43); + + const pm_back_reference_read_node_t *cast = (const pm_back_reference_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BEGIN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BeginNode\",\"location\":", 31); + + const pm_begin_node_t *cast = (const pm_begin_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the begin_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"begin_keyword_loc\":", 20); + if (cast->begin_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->begin_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rescue_clause field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rescue_clause\":", 16); + if (cast->rescue_clause != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->rescue_clause); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the else_clause field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"else_clause\":", 14); + if (cast->else_clause != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the ensure_clause field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ensure_clause\":", 16); + if (cast->ensure_clause != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->ensure_clause); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + if (cast->end_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->end_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BLOCK_ARGUMENT_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BlockArgumentNode\",\"location\":", 39); + + const pm_block_argument_node_t *cast = (const pm_block_argument_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the expression field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"expression\":", 13); + if (cast->expression != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BLOCK_LOCAL_VARIABLE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BlockLocalVariableNode\",\"location\":", 44); + + const pm_block_local_variable_node_t *cast = (const pm_block_local_variable_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BLOCK_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BlockNode\",\"location\":", 31); + + const pm_block_node_t *cast = (const pm_block_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_constant_id_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, locals->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the parameters field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parameters\":", 13); + if (cast->parameters != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + if (cast->body != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BLOCK_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BlockParameterNode\",\"location\":", 40); + + const pm_block_parameter_node_t *cast = (const pm_block_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + if (cast->name != PM_CONSTANT_ID_UNSET) { + pm_dump_json_constant(buffer, parser, cast->name); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + if (cast->name_loc.length != 0) { + pm_dump_json_location(buffer, &cast->name_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BLOCK_PARAMETERS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BlockParametersNode\",\"location\":", 41); + + const pm_block_parameters_node_t *cast = (const pm_block_parameters_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the parameters field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parameters\":", 13); + if (cast->parameters != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_node_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, locals->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_BREAK_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"BreakNode\",\"location\":", 31); + + const pm_break_node_t *cast = (const pm_break_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CALL_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CallAndWriteNode\",\"location\":", 38); + + const pm_call_and_write_node_t *cast = (const pm_call_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + if (cast->call_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->call_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the message_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"message_loc\":", 14); + if (cast->message_loc.length != 0) { + pm_dump_json_location(buffer, &cast->message_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the read_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"read_name\":", 12); + pm_dump_json_constant(buffer, parser, cast->read_name); + + // Dump the write_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"write_name\":", 13); + pm_dump_json_constant(buffer, parser, cast->write_name); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CALL_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CallNode\",\"location\":", 30); + + const pm_call_node_t *cast = (const pm_call_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + if (cast->call_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->call_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the message_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"message_loc\":", 14); + if (cast->message_loc.length != 0) { + pm_dump_json_location(buffer, &cast->message_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the equal_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"equal_loc\":", 12); + if (cast->equal_loc.length != 0) { + pm_dump_json_location(buffer, &cast->equal_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CALL_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CallOperatorWriteNode\",\"location\":", 43); + + const pm_call_operator_write_node_t *cast = (const pm_call_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + if (cast->call_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->call_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the message_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"message_loc\":", 14); + if (cast->message_loc.length != 0) { + pm_dump_json_location(buffer, &cast->message_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the read_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"read_name\":", 12); + pm_dump_json_constant(buffer, parser, cast->read_name); + + // Dump the write_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"write_name\":", 13); + pm_dump_json_constant(buffer, parser, cast->write_name); + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CALL_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CallOrWriteNode\",\"location\":", 37); + + const pm_call_or_write_node_t *cast = (const pm_call_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + if (cast->call_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->call_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the message_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"message_loc\":", 14); + if (cast->message_loc.length != 0) { + pm_dump_json_location(buffer, &cast->message_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the read_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"read_name\":", 12); + pm_dump_json_constant(buffer, parser, cast->read_name); + + // Dump the write_name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"write_name\":", 13); + pm_dump_json_constant(buffer, parser, cast->write_name); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CALL_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CallTargetNode\",\"location\":", 36); + + const pm_call_target_node_t *cast = (const pm_call_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + pm_dump_json_location(buffer, &cast->call_operator_loc); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the message_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"message_loc\":", 14); + pm_dump_json_location(buffer, &cast->message_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CAPTURE_PATTERN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CapturePatternNode\",\"location\":", 40); + + const pm_capture_pattern_node_t *cast = (const pm_capture_pattern_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the target field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"target\":", 9); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CASE_MATCH_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CaseMatchNode\",\"location\":", 35); + + const pm_case_match_node_t *cast = (const pm_case_match_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the predicate field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"predicate\":", 12); + if (cast->predicate != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the conditions field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"conditions\":", 13); + const pm_node_list_t *conditions = &cast->conditions; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < conditions->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, conditions->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the else_clause field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"else_clause\":", 14); + if (cast->else_clause != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the case_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"case_keyword_loc\":", 19); + pm_dump_json_location(buffer, &cast->case_keyword_loc); + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->end_keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CASE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"CaseNode\",\"location\":", 30); + + const pm_case_node_t *cast = (const pm_case_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the predicate field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"predicate\":", 12); + if (cast->predicate != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the conditions field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"conditions\":", 13); + const pm_node_list_t *conditions = &cast->conditions; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < conditions->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, conditions->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the else_clause field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"else_clause\":", 14); + if (cast->else_clause != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the case_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"case_keyword_loc\":", 19); + pm_dump_json_location(buffer, &cast->case_keyword_loc); + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->end_keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CLASS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ClassNode\",\"location\":", 31); + + const pm_class_node_t *cast = (const pm_class_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_constant_id_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, locals->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the class_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"class_keyword_loc\":", 20); + pm_dump_json_location(buffer, &cast->class_keyword_loc); + + // Dump the constant_path field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"constant_path\":", 16); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant_path); + + // Dump the inheritance_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"inheritance_operator_loc\":", 27); + if (cast->inheritance_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->inheritance_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the superclass field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"superclass\":", 13); + if (cast->superclass != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->superclass); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + if (cast->body != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->end_keyword_loc); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CLASS_VARIABLE_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableAndWriteNode\",\"location\":", 47); + + const pm_class_variable_and_write_node_t *cast = (const pm_class_variable_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableOperatorWriteNode\",\"location\":", 52); + + const pm_class_variable_operator_write_node_t *cast = (const pm_class_variable_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CLASS_VARIABLE_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableOrWriteNode\",\"location\":", 46); + + const pm_class_variable_or_write_node_t *cast = (const pm_class_variable_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CLASS_VARIABLE_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableReadNode\",\"location\":", 43); + + const pm_class_variable_read_node_t *cast = (const pm_class_variable_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CLASS_VARIABLE_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableTargetNode\",\"location\":", 45); + + const pm_class_variable_target_node_t *cast = (const pm_class_variable_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CLASS_VARIABLE_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableWriteNode\",\"location\":", 44); + + const pm_class_variable_write_node_t *cast = (const pm_class_variable_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantAndWriteNode\",\"location\":", 42); + + const pm_constant_and_write_node_t *cast = (const pm_constant_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantOperatorWriteNode\",\"location\":", 47); + + const pm_constant_operator_write_node_t *cast = (const pm_constant_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantOrWriteNode\",\"location\":", 41); + + const pm_constant_or_write_node_t *cast = (const pm_constant_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_PATH_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathAndWriteNode\",\"location\":", 46); + + const pm_constant_path_and_write_node_t *cast = (const pm_constant_path_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the target field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"target\":", 9); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_PATH_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathNode\",\"location\":", 38); + + const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the parent field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parent\":", 9); + if (cast->parent != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->parent); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + if (cast->name != PM_CONSTANT_ID_UNSET) { + pm_dump_json_constant(buffer, parser, cast->name); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the delimiter_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"delimiter_loc\":", 16); + pm_dump_json_location(buffer, &cast->delimiter_loc); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathOperatorWriteNode\",\"location\":", 51); + + const pm_constant_path_operator_write_node_t *cast = (const pm_constant_path_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the target field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"target\":", 9); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_PATH_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathOrWriteNode\",\"location\":", 45); + + const pm_constant_path_or_write_node_t *cast = (const pm_constant_path_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the target field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"target\":", 9); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_PATH_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathTargetNode\",\"location\":", 44); + + const pm_constant_path_target_node_t *cast = (const pm_constant_path_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the parent field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parent\":", 9); + if (cast->parent != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->parent); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + if (cast->name != PM_CONSTANT_ID_UNSET) { + pm_dump_json_constant(buffer, parser, cast->name); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the delimiter_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"delimiter_loc\":", 16); + pm_dump_json_location(buffer, &cast->delimiter_loc); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_PATH_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathWriteNode\",\"location\":", 43); + + const pm_constant_path_write_node_t *cast = (const pm_constant_path_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the target field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"target\":", 9); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantReadNode\",\"location\":", 38); + + const pm_constant_read_node_t *cast = (const pm_constant_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantTargetNode\",\"location\":", 40); + + const pm_constant_target_node_t *cast = (const pm_constant_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_CONSTANT_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ConstantWriteNode\",\"location\":", 39); + + const pm_constant_write_node_t *cast = (const pm_constant_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_DEF_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"DefNode\",\"location\":", 29); + + const pm_def_node_t *cast = (const pm_def_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the parameters field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parameters\":", 13); + if (cast->parameters != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + if (cast->body != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_constant_id_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, locals->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the def_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"def_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->def_keyword_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + if (cast->operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the lparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); + if (cast->lparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->lparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); + if (cast->rparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->rparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the equal_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"equal_loc\":", 12); + if (cast->equal_loc.length != 0) { + pm_dump_json_location(buffer, &cast->equal_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + if (cast->end_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->end_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_DEFINED_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"DefinedNode\",\"location\":", 33); + + const pm_defined_node_t *cast = (const pm_defined_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the lparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); + if (cast->lparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->lparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the rparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); + if (cast->rparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->rparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ELSE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ElseNode\",\"location\":", 30); + + const pm_else_node_t *cast = (const pm_else_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the else_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"else_keyword_loc\":", 19); + pm_dump_json_location(buffer, &cast->else_keyword_loc); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + if (cast->end_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->end_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_EMBEDDED_STATEMENTS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"EmbeddedStatementsNode\",\"location\":", 44); + + const pm_embedded_statements_node_t *cast = (const pm_embedded_statements_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_EMBEDDED_VARIABLE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"EmbeddedVariableNode\",\"location\":", 42); + + const pm_embedded_variable_node_t *cast = (const pm_embedded_variable_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the variable field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"variable\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->variable); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_ENSURE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"EnsureNode\",\"location\":", 32); + + const pm_ensure_node_t *cast = (const pm_ensure_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ensure_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ensure_keyword_loc\":", 21); + pm_dump_json_location(buffer, &cast->ensure_keyword_loc); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->end_keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FALSE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"FalseNode\",\"location\":", 31); + + const pm_false_node_t *cast = (const pm_false_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FIND_PATTERN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"FindPatternNode\",\"location\":", 37); + + const pm_find_pattern_node_t *cast = (const pm_find_pattern_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the constant field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"constant\":", 11); + if (cast->constant != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the left field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"left\":", 7); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); + + // Dump the requireds field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"requireds\":", 12); + const pm_node_list_t *requireds = &cast->requireds; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < requireds->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, requireds->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the right field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"right\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FLIP_FLOP_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"FlipFlopNode\",\"location\":", 34); + + const pm_flip_flop_node_t *cast = (const pm_flip_flop_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the RangeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_RANGE_FLAGS_EXCLUDE_END)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXCLUDE_END\"", 13); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the left field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"left\":", 7); + if (cast->left != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the right field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"right\":", 8); + if (cast->right != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FLOAT_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"FloatNode\",\"location\":", 31); + + const pm_float_node_t *cast = (const pm_float_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_buffer_append_format(buffer, "%f", cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FOR_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ForNode\",\"location\":", 29); + + const pm_for_node_t *cast = (const pm_for_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the index field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"index\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->index); + + // Dump the collection field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"collection\":", 13); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->collection); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the for_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"for_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->for_keyword_loc); + + // Dump the in_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"in_keyword_loc\":", 17); + pm_dump_json_location(buffer, &cast->in_keyword_loc); + + // Dump the do_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17); + if (cast->do_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->do_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->end_keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FORWARDING_ARGUMENTS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ForwardingArgumentsNode\",\"location\":", 45); + + const pm_forwarding_arguments_node_t *cast = (const pm_forwarding_arguments_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FORWARDING_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ForwardingParameterNode\",\"location\":", 45); + + const pm_forwarding_parameter_node_t *cast = (const pm_forwarding_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_FORWARDING_SUPER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ForwardingSuperNode\",\"location\":", 41); + + const pm_forwarding_super_node_t *cast = (const pm_forwarding_super_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableAndWriteNode\",\"location\":", 48); + + const pm_global_variable_and_write_node_t *cast = (const pm_global_variable_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableOperatorWriteNode\",\"location\":", 53); + + const pm_global_variable_operator_write_node_t *cast = (const pm_global_variable_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableOrWriteNode\",\"location\":", 47); + + const pm_global_variable_or_write_node_t *cast = (const pm_global_variable_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_GLOBAL_VARIABLE_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableReadNode\",\"location\":", 44); + + const pm_global_variable_read_node_t *cast = (const pm_global_variable_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_GLOBAL_VARIABLE_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableTargetNode\",\"location\":", 46); + + const pm_global_variable_target_node_t *cast = (const pm_global_variable_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_GLOBAL_VARIABLE_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableWriteNode\",\"location\":", 45); + + const pm_global_variable_write_node_t *cast = (const pm_global_variable_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_HASH_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"HashNode\",\"location\":", 30); + + const pm_hash_node_t *cast = (const pm_hash_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the elements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"elements\":", 11); + const pm_node_list_t *elements = &cast->elements; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < elements->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, elements->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_HASH_PATTERN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"HashPatternNode\",\"location\":", 37); + + const pm_hash_pattern_node_t *cast = (const pm_hash_pattern_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the constant field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"constant\":", 11); + if (cast->constant != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the elements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"elements\":", 11); + const pm_node_list_t *elements = &cast->elements; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < elements->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, elements->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the rest field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rest\":", 7); + if (cast->rest != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_IF_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"IfNode\",\"location\":", 28); + + const pm_if_node_t *cast = (const pm_if_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the if_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"if_keyword_loc\":", 17); + if (cast->if_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->if_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the predicate field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"predicate\":", 12); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); + + // Dump the then_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); + if (cast->then_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->then_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the subsequent field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"subsequent\":", 13); + if (cast->subsequent != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->subsequent); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + if (cast->end_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->end_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_IMAGINARY_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ImaginaryNode\",\"location\":", 35); + + const pm_imaginary_node_t *cast = (const pm_imaginary_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the numeric field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"numeric\":", 10); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->numeric); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_IMPLICIT_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ImplicitNode\",\"location\":", 34); + + const pm_implicit_node_t *cast = (const pm_implicit_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_IMPLICIT_REST_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ImplicitRestNode\",\"location\":", 38); + + const pm_implicit_rest_node_t *cast = (const pm_implicit_rest_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_IN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InNode\",\"location\":", 28); + + const pm_in_node_t *cast = (const pm_in_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the pattern field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"pattern\":", 10); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the in_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"in_loc\":", 9); + pm_dump_json_location(buffer, &cast->in_loc); + + // Dump the then_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"then_loc\":", 11); + if (cast->then_loc.length != 0) { + pm_dump_json_location(buffer, &cast->then_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INDEX_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"IndexAndWriteNode\",\"location\":", 39); + + const pm_index_and_write_node_t *cast = (const pm_index_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + if (cast->call_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->call_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INDEX_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"IndexOperatorWriteNode\",\"location\":", 44); + + const pm_index_operator_write_node_t *cast = (const pm_index_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + if (cast->call_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->call_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INDEX_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"IndexOrWriteNode\",\"location\":", 38); + + const pm_index_or_write_node_t *cast = (const pm_index_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + if (cast->receiver != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the call_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); + if (cast->call_operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->call_operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INDEX_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"IndexTargetNode\",\"location\":", 37); + + const pm_index_target_node_t *cast = (const pm_index_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the CallNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the receiver field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"receiver\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableAndWriteNode\",\"location\":", 50); + + const pm_instance_variable_and_write_node_t *cast = (const pm_instance_variable_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableOperatorWriteNode\",\"location\":", 55); + + const pm_instance_variable_operator_write_node_t *cast = (const pm_instance_variable_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableOrWriteNode\",\"location\":", 49); + + const pm_instance_variable_or_write_node_t *cast = (const pm_instance_variable_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INSTANCE_VARIABLE_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableReadNode\",\"location\":", 46); + + const pm_instance_variable_read_node_t *cast = (const pm_instance_variable_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INSTANCE_VARIABLE_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableTargetNode\",\"location\":", 48); + + const pm_instance_variable_target_node_t *cast = (const pm_instance_variable_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INSTANCE_VARIABLE_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableWriteNode\",\"location\":", 47); + + const pm_instance_variable_write_node_t *cast = (const pm_instance_variable_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INTEGER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"IntegerNode\",\"location\":", 33); + + const pm_integer_node_t *cast = (const pm_integer_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the IntegerBaseFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_BINARY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"BINARY\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_DECIMAL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"DECIMAL\"", 9); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_OCTAL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"OCTAL\"", 7); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_HEXADECIMAL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"HEXADECIMAL\"", 13); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_integer_string(buffer, &cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedMatchLastLineNode\",\"location\":", 51); + + const pm_interpolated_match_last_line_node_t *cast = (const pm_interpolated_match_last_line_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the RegularExpressionFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ONCE\"", 6); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"UTF_8\"", 7); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the parts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parts\":", 8); + const pm_node_list_t *parts = &cast->parts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < parts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, parts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedRegularExpressionNode\",\"location\":", 55); + + const pm_interpolated_regular_expression_node_t *cast = (const pm_interpolated_regular_expression_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the RegularExpressionFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ONCE\"", 6); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"UTF_8\"", 7); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the parts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parts\":", 8); + const pm_node_list_t *parts = &cast->parts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < parts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, parts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INTERPOLATED_STRING_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedStringNode\",\"location\":", 44); + + const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the InterpolatedStringNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FROZEN\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MUTABLE\"", 9); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the parts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parts\":", 8); + const pm_node_list_t *parts = &cast->parts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < parts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, parts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INTERPOLATED_SYMBOL_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedSymbolNode\",\"location\":", 44); + + const pm_interpolated_symbol_node_t *cast = (const pm_interpolated_symbol_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the parts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parts\":", 8); + const pm_node_list_t *parts = &cast->parts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < parts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, parts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_INTERPOLATED_X_STRING_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedXStringNode\",\"location\":", 45); + + const pm_interpolated_x_string_node_t *cast = (const pm_interpolated_x_string_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the parts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parts\":", 8); + const pm_node_list_t *parts = &cast->parts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < parts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, parts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_IT_LOCAL_VARIABLE_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ItLocalVariableReadNode\",\"location\":", 45); + + const pm_it_local_variable_read_node_t *cast = (const pm_it_local_variable_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_IT_PARAMETERS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ItParametersNode\",\"location\":", 38); + + const pm_it_parameters_node_t *cast = (const pm_it_parameters_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_KEYWORD_HASH_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"KeywordHashNode\",\"location\":", 37); + + const pm_keyword_hash_node_t *cast = (const pm_keyword_hash_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the KeywordHashNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"SYMBOL_KEYS\"", 13); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the elements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"elements\":", 11); + const pm_node_list_t *elements = &cast->elements; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < elements->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, elements->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_KEYWORD_REST_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"KeywordRestParameterNode\",\"location\":", 46); + + const pm_keyword_rest_parameter_node_t *cast = (const pm_keyword_rest_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + if (cast->name != PM_CONSTANT_ID_UNSET) { + pm_dump_json_constant(buffer, parser, cast->name); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + if (cast->name_loc.length != 0) { + pm_dump_json_location(buffer, &cast->name_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_LAMBDA_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"LambdaNode\",\"location\":", 32); + + const pm_lambda_node_t *cast = (const pm_lambda_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_constant_id_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, locals->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the parameters field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"parameters\":", 13); + if (cast->parameters != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + if (cast->body != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_LOCAL_VARIABLE_AND_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableAndWriteNode\",\"location\":", 47); + + const pm_local_variable_and_write_node_t *cast = (const pm_local_variable_and_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the depth field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"depth\":", 8); + pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableOperatorWriteNode\",\"location\":", 52); + + const pm_local_variable_operator_write_node_t *cast = (const pm_local_variable_operator_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the binary_operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); + pm_dump_json_location(buffer, &cast->binary_operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the binary_operator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"binary_operator\":", 18); + pm_dump_json_constant(buffer, parser, cast->binary_operator); + + // Dump the depth field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"depth\":", 8); + pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_LOCAL_VARIABLE_OR_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableOrWriteNode\",\"location\":", 46); + + const pm_local_variable_or_write_node_t *cast = (const pm_local_variable_or_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the depth field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"depth\":", 8); + pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_LOCAL_VARIABLE_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableReadNode\",\"location\":", 43); + + const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the depth field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"depth\":", 8); + pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_LOCAL_VARIABLE_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableTargetNode\",\"location\":", 45); + + const pm_local_variable_target_node_t *cast = (const pm_local_variable_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the depth field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"depth\":", 8); + pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_LOCAL_VARIABLE_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableWriteNode\",\"location\":", 44); + + const pm_local_variable_write_node_t *cast = (const pm_local_variable_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the depth field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"depth\":", 8); + pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MATCH_LAST_LINE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"MatchLastLineNode\",\"location\":", 39); + + const pm_match_last_line_node_t *cast = (const pm_match_last_line_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the RegularExpressionFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ONCE\"", 6); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"UTF_8\"", 7); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the content_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"content_loc\":", 14); + pm_dump_json_location(buffer, &cast->content_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the unescaped field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"unescaped\":", 12); + const pm_string_t *unescaped = &cast->unescaped; + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MATCH_PREDICATE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"MatchPredicateNode\",\"location\":", 40); + + const pm_match_predicate_node_t *cast = (const pm_match_predicate_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the pattern field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"pattern\":", 10); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MATCH_REQUIRED_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"MatchRequiredNode\",\"location\":", 39); + + const pm_match_required_node_t *cast = (const pm_match_required_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + // Dump the pattern field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"pattern\":", 10); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MATCH_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"MatchWriteNode\",\"location\":", 36); + + const pm_match_write_node_t *cast = (const pm_match_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the call field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"call\":", 7); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->call); + + // Dump the targets field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"targets\":", 10); + const pm_node_list_t *targets = &cast->targets; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < targets->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, targets->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MISSING_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"MissingNode\",\"location\":", 33); + + const pm_missing_node_t *cast = (const pm_missing_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MODULE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ModuleNode\",\"location\":", 32); + + const pm_module_node_t *cast = (const pm_module_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_constant_id_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, locals->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the module_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"module_keyword_loc\":", 21); + pm_dump_json_location(buffer, &cast->module_keyword_loc); + + // Dump the constant_path field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"constant_path\":", 16); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant_path); + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + if (cast->body != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->end_keyword_loc); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MULTI_TARGET_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"MultiTargetNode\",\"location\":", 37); + + const pm_multi_target_node_t *cast = (const pm_multi_target_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the lefts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lefts\":", 8); + const pm_node_list_t *lefts = &cast->lefts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < lefts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, lefts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the rest field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rest\":", 7); + if (cast->rest != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rights field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rights\":", 9); + const pm_node_list_t *rights = &cast->rights; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < rights->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, rights->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the lparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); + if (cast->lparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->lparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); + if (cast->rparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->rparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_MULTI_WRITE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"MultiWriteNode\",\"location\":", 36); + + const pm_multi_write_node_t *cast = (const pm_multi_write_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the lefts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lefts\":", 8); + const pm_node_list_t *lefts = &cast->lefts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < lefts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, lefts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the rest field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rest\":", 7); + if (cast->rest != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rights field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rights\":", 9); + const pm_node_list_t *rights = &cast->rights; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < rights->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, rights->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the lparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); + if (cast->lparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->lparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); + if (cast->rparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->rparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_NEXT_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"NextNode\",\"location\":", 30); + + const pm_next_node_t *cast = (const pm_next_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_NIL_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"NilNode\",\"location\":", 29); + + const pm_nil_node_t *cast = (const pm_nil_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_NO_BLOCK_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"NoBlockParameterNode\",\"location\":", 42); + + const pm_no_block_parameter_node_t *cast = (const pm_no_block_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_NO_KEYWORDS_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"NoKeywordsParameterNode\",\"location\":", 45); + + const pm_no_keywords_parameter_node_t *cast = (const pm_no_keywords_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_NUMBERED_PARAMETERS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"NumberedParametersNode\",\"location\":", 44); + + const pm_numbered_parameters_node_t *cast = (const pm_numbered_parameters_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the maximum field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"maximum\":", 10); + pm_buffer_append_format(buffer, "%" PRIu8, cast->maximum); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_NUMBERED_REFERENCE_READ_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"NumberedReferenceReadNode\",\"location\":", 47); + + const pm_numbered_reference_read_node_t *cast = (const pm_numbered_reference_read_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the number field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"number\":", 9); + pm_buffer_append_format(buffer, "%" PRIu32, cast->number); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"OptionalKeywordParameterNode\",\"location\":", 50); + + const pm_optional_keyword_parameter_node_t *cast = (const pm_optional_keyword_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_OPTIONAL_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"OptionalParameterNode\",\"location\":", 43); + + const pm_optional_parameter_node_t *cast = (const pm_optional_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the value field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_OR_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"OrNode\",\"location\":", 28); + + const pm_or_node_t *cast = (const pm_or_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the left field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"left\":", 7); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); + + // Dump the right field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"right\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_PARAMETERS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ParametersNode\",\"location\":", 36); + + const pm_parameters_node_t *cast = (const pm_parameters_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the requireds field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"requireds\":", 12); + const pm_node_list_t *requireds = &cast->requireds; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < requireds->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, requireds->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the optionals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"optionals\":", 12); + const pm_node_list_t *optionals = &cast->optionals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < optionals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, optionals->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the rest field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rest\":", 7); + if (cast->rest != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the posts field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"posts\":", 8); + const pm_node_list_t *posts = &cast->posts; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < posts->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, posts->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the keywords field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keywords\":", 11); + const pm_node_list_t *keywords = &cast->keywords; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < keywords->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, keywords->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the keyword_rest field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_rest\":", 15); + if (cast->keyword_rest != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->keyword_rest); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_PARENTHESES_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ParenthesesNode\",\"location\":", 37); + + const pm_parentheses_node_t *cast = (const pm_parentheses_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParenthesesNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MULTIPLE_STATEMENTS\"", 21); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + if (cast->body != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_PINNED_EXPRESSION_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"PinnedExpressionNode\",\"location\":", 42); + + const pm_pinned_expression_node_t *cast = (const pm_pinned_expression_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the expression field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"expression\":", 13); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the lparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); + pm_dump_json_location(buffer, &cast->lparen_loc); + + // Dump the rparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); + pm_dump_json_location(buffer, &cast->rparen_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_PINNED_VARIABLE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"PinnedVariableNode\",\"location\":", 40); + + const pm_pinned_variable_node_t *cast = (const pm_pinned_variable_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the variable field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"variable\":", 11); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->variable); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_POST_EXECUTION_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"PostExecutionNode\",\"location\":", 39); + + const pm_post_execution_node_t *cast = (const pm_post_execution_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_PRE_EXECUTION_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"PreExecutionNode\",\"location\":", 38); + + const pm_pre_execution_node_t *cast = (const pm_pre_execution_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_PROGRAM_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ProgramNode\",\"location\":", 33); + + const pm_program_node_t *cast = (const pm_program_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_constant_id_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, locals->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_RANGE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RangeNode\",\"location\":", 31); + + const pm_range_node_t *cast = (const pm_range_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the RangeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_RANGE_FLAGS_EXCLUDE_END)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXCLUDE_END\"", 13); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the left field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"left\":", 7); + if (cast->left != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the right field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"right\":", 8); + if (cast->right != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_RATIONAL_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RationalNode\",\"location\":", 34); + + const pm_rational_node_t *cast = (const pm_rational_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the IntegerBaseFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_BINARY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"BINARY\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_DECIMAL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"DECIMAL\"", 9); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_OCTAL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"OCTAL\"", 7); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_HEXADECIMAL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"HEXADECIMAL\"", 13); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the numerator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"numerator\":", 12); + pm_integer_string(buffer, &cast->numerator); + + // Dump the denominator field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"denominator\":", 14); + pm_integer_string(buffer, &cast->denominator); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_REDO_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RedoNode\",\"location\":", 30); + + const pm_redo_node_t *cast = (const pm_redo_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_REGULAR_EXPRESSION_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RegularExpressionNode\",\"location\":", 43); + + const pm_regular_expression_node_t *cast = (const pm_regular_expression_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the RegularExpressionFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ONCE\"", 6); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"UTF_8\"", 7); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the content_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"content_loc\":", 14); + pm_dump_json_location(buffer, &cast->content_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the unescaped field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"unescaped\":", 12); + const pm_string_t *unescaped = &cast->unescaped; + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_REQUIRED_KEYWORD_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RequiredKeywordParameterNode\",\"location\":", 50); + + const pm_required_keyword_parameter_node_t *cast = (const pm_required_keyword_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + pm_dump_json_location(buffer, &cast->name_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_REQUIRED_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RequiredParameterNode\",\"location\":", 43); + + const pm_required_parameter_node_t *cast = (const pm_required_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + pm_dump_json_constant(buffer, parser, cast->name); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_RESCUE_MODIFIER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RescueModifierNode\",\"location\":", 40); + + const pm_rescue_modifier_node_t *cast = (const pm_rescue_modifier_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the expression field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"expression\":", 13); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the rescue_expression field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rescue_expression\":", 20); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->rescue_expression); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_RESCUE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RescueNode\",\"location\":", 32); + + const pm_rescue_node_t *cast = (const pm_rescue_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the exceptions field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"exceptions\":", 13); + const pm_node_list_t *exceptions = &cast->exceptions; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < exceptions->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, exceptions->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + if (cast->operator_loc.length != 0) { + pm_dump_json_location(buffer, &cast->operator_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the reference field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"reference\":", 12); + if (cast->reference != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->reference); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the then_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); + if (cast->then_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->then_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the subsequent field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"subsequent\":", 13); + if (cast->subsequent != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->subsequent); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_REST_PARAMETER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RestParameterNode\",\"location\":", 39); + + const pm_rest_parameter_node_t *cast = (const pm_rest_parameter_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ParameterFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the name field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name\":", 7); + if (cast->name != PM_CONSTANT_ID_UNSET) { + pm_dump_json_constant(buffer, parser, cast->name); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the name_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"name_loc\":", 11); + if (cast->name_loc.length != 0) { + pm_dump_json_location(buffer, &cast->name_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_RETRY_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"RetryNode\",\"location\":", 31); + + const pm_retry_node_t *cast = (const pm_retry_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_RETURN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ReturnNode\",\"location\":", 32); + + const pm_return_node_t *cast = (const pm_return_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SELF_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SelfNode\",\"location\":", 30); + + const pm_self_node_t *cast = (const pm_self_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SHAREABLE_CONSTANT_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"ShareableConstantNode\",\"location\":", 43); + + const pm_shareable_constant_node_t *cast = (const pm_shareable_constant_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the ShareableConstantNodeFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"LITERAL\"", 9); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXPERIMENTAL_EVERYTHING\"", 25); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"EXPERIMENTAL_COPY\"", 19); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the write field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"write\":", 8); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->write); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SINGLETON_CLASS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SingletonClassNode\",\"location\":", 40); + + const pm_singleton_class_node_t *cast = (const pm_singleton_class_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the locals field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"locals\":", 9); + const pm_constant_id_list_t *locals = &cast->locals; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < locals->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, locals->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the class_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"class_keyword_loc\":", 20); + pm_dump_json_location(buffer, &cast->class_keyword_loc); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the expression field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"expression\":", 13); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + if (cast->body != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + pm_dump_json_location(buffer, &cast->end_keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SOURCE_ENCODING_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SourceEncodingNode\",\"location\":", 40); + + const pm_source_encoding_node_t *cast = (const pm_source_encoding_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SOURCE_FILE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SourceFileNode\",\"location\":", 36); + + const pm_source_file_node_t *cast = (const pm_source_file_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the StringFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FROZEN)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FROZEN\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_MUTABLE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MUTABLE\"", 9); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the filepath field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"filepath\":", 11); + const pm_string_t *filepath = &cast->filepath; + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, pm_string_source(filepath), pm_string_length(filepath), PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SOURCE_LINE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SourceLineNode\",\"location\":", 36); + + const pm_source_line_node_t *cast = (const pm_source_line_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SPLAT_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SplatNode\",\"location\":", 31); + + const pm_splat_node_t *cast = (const pm_splat_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the operator_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"operator_loc\":", 15); + pm_dump_json_location(buffer, &cast->operator_loc); + + // Dump the expression field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"expression\":", 13); + if (cast->expression != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_STATEMENTS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"StatementsNode\",\"location\":", 36); + + const pm_statements_node_t *cast = (const pm_statements_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the body field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"body\":", 7); + const pm_node_list_t *body = &cast->body; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < body->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, body->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_STRING_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"StringNode\",\"location\":", 32); + + const pm_string_node_t *cast = (const pm_string_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the StringFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FROZEN)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FROZEN\"", 8); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_MUTABLE)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"MUTABLE\"", 9); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the content_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"content_loc\":", 14); + pm_dump_json_location(buffer, &cast->content_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the unescaped field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"unescaped\":", 12); + const pm_string_t *unescaped = &cast->unescaped; + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SUPER_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SuperNode\",\"location\":", 31); + + const pm_super_node_t *cast = (const pm_super_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the lparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); + if (cast->lparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->lparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); + if (cast->rparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->rparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the block field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"block\":", 8); + if (cast->block != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SYMBOL_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"SymbolNode\",\"location\":", 32); + + const pm_symbol_node_t *cast = (const pm_symbol_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the SymbolFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + if (cast->opening_loc.length != 0) { + pm_dump_json_location(buffer, &cast->opening_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the value_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"value_loc\":", 12); + if (cast->value_loc.length != 0) { + pm_dump_json_location(buffer, &cast->value_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the unescaped field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"unescaped\":", 12); + const pm_string_t *unescaped = &cast->unescaped; + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_TRUE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"TrueNode\",\"location\":", 30); + + const pm_true_node_t *cast = (const pm_true_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_UNDEF_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"UndefNode\",\"location\":", 31); + + const pm_undef_node_t *cast = (const pm_undef_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the names field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"names\":", 8); + const pm_node_list_t *names = &cast->names; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < names->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, names->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_UNLESS_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"UnlessNode\",\"location\":", 32); + + const pm_unless_node_t *cast = (const pm_unless_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the predicate field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"predicate\":", 12); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); + + // Dump the then_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); + if (cast->then_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->then_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the else_clause field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"else_clause\":", 14); + if (cast->else_clause != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the end_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); + if (cast->end_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->end_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_UNTIL_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"UntilNode\",\"location\":", 31); + + const pm_until_node_t *cast = (const pm_until_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the LoopFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_LOOP_FLAGS_BEGIN_MODIFIER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"BEGIN_MODIFIER\"", 16); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the do_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17); + if (cast->do_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->do_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the predicate field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"predicate\":", 12); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_WHEN_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"WhenNode\",\"location\":", 30); + + const pm_when_node_t *cast = (const pm_when_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the conditions field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"conditions\":", 13); + const pm_node_list_t *conditions = &cast->conditions; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < conditions->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, conditions->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the then_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); + if (cast->then_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->then_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_WHILE_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"WhileNode\",\"location\":", 31); + + const pm_while_node_t *cast = (const pm_while_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the LoopFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_LOOP_FLAGS_BEGIN_MODIFIER)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"BEGIN_MODIFIER\"", 16); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the do_keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17); + if (cast->do_keyword_loc.length != 0) { + pm_dump_json_location(buffer, &cast->do_keyword_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + if (cast->closing_loc.length != 0) { + pm_dump_json_location(buffer, &cast->closing_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the predicate field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"predicate\":", 12); + pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); + + // Dump the statements field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"statements\":", 13); + if (cast->statements != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_X_STRING_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"XStringNode\",\"location\":", 33); + + const pm_x_string_node_t *cast = (const pm_x_string_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the EncodingFlags field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"flags\":", 8); + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + if (PM_NODE_FLAG_P(cast, PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); + flags++; + } + if (PM_NODE_FLAG_P(cast, PM_ENCODING_FLAGS_FORCED_BINARY_ENCODING)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); + flags++; + } + pm_buffer_append_byte(buffer, ']'); + + // Dump the opening_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"opening_loc\":", 14); + pm_dump_json_location(buffer, &cast->opening_loc); + + // Dump the content_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"content_loc\":", 14); + pm_dump_json_location(buffer, &cast->content_loc); + + // Dump the closing_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"closing_loc\":", 14); + pm_dump_json_location(buffer, &cast->closing_loc); + + // Dump the unescaped field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"unescaped\":", 12); + const pm_string_t *unescaped = &cast->unescaped; + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_YIELD_NODE: { + pm_buffer_append_string(buffer, "{\"type\":\"YieldNode\",\"location\":", 31); + + const pm_yield_node_t *cast = (const pm_yield_node_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + + // Dump the keyword_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); + pm_dump_json_location(buffer, &cast->keyword_loc); + + // Dump the lparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); + if (cast->lparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->lparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the arguments field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"arguments\":", 12); + if (cast->arguments != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + // Dump the rparen_loc field + pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); + if (cast->rparen_loc.length != 0) { + pm_dump_json_location(buffer, &cast->rparen_loc); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + + pm_buffer_append_byte(buffer, '}'); + break; + } + case PM_SCOPE_NODE: + break; + } +} + +#endif diff --git a/templates/src/json.c.erb b/templates/src/json.c.erb new file mode 100644 index 0000000000..66397b8fcd --- /dev/null +++ b/templates/src/json.c.erb @@ -0,0 +1,130 @@ +#include "prism/json.h" + +/* We optionally support dumping to JSON. For systems that don not want or need + * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. + */ +#ifndef PRISM_EXCLUDE_JSON + +#include "prism/internal/buffer.h" +#include "prism/internal/constant_pool.h" +#include "prism/internal/integer.h" +#include "prism/internal/parser.h" + +#include + +static void +pm_dump_json_constant(pm_buffer_t *buffer, const pm_parser_t *parser, pm_constant_id_t constant_id) { + const pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id); + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, constant->start, constant->length, PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); +} + +static void +pm_dump_json_location(pm_buffer_t *buffer, const pm_location_t *location) { + pm_buffer_append_format(buffer, "{\"start\":%" PRIu32 ",\"length\":%" PRIu32 "}", location->start, location->length); +} + +/** + * Dump JSON to the given buffer. + */ +void +pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + <%- nodes.each do |node| -%> + case <%= node.type %>: { + pm_buffer_append_string(buffer, "{\"type\":\"<%= node.name %>\",\"location\":", <%= node.name.bytesize + 22 %>); + + const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node; + pm_dump_json_location(buffer, &cast->base.location); + <%- [*node.flags, *node.fields].each_with_index do |field, index| -%> + + // Dump the <%= field.name %> field + pm_buffer_append_byte(buffer, ','); + <%- if field.is_a?(Prism::Template::Flags) -%> + pm_buffer_append_string(buffer, "\"flags\":", 8); + <%- else -%> + pm_buffer_append_string(buffer, "\"<%= field.name %>\":", <%= field.name.bytesize + 3 %>); + <%- end -%> + <%- case field -%> + <%- when Prism::Template::NodeField -%> + pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>); + <%- when Prism::Template::OptionalNodeField -%> + if (cast-><%= field.name %> != NULL) { + pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + <%- when Prism::Template::NodeListField -%> + const pm_node_list_t *<%= field.name %> = &cast-><%= field.name %>; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < <%= field.name %>->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json(buffer, parser, <%= field.name %>->nodes[index]); + } + pm_buffer_append_byte(buffer, ']'); + <%- when Prism::Template::StringField -%> + const pm_string_t *<%= field.name %> = &cast-><%= field.name %>; + pm_buffer_append_byte(buffer, '"'); + pm_buffer_append_source(buffer, pm_string_source(<%= field.name %>), pm_string_length(<%= field.name %>), PM_BUFFER_ESCAPING_JSON); + pm_buffer_append_byte(buffer, '"'); + <%- when Prism::Template::ConstantField -%> + pm_dump_json_constant(buffer, parser, cast-><%= field.name %>); + <%- when Prism::Template::OptionalConstantField -%> + if (cast-><%= field.name %> != PM_CONSTANT_ID_UNSET) { + pm_dump_json_constant(buffer, parser, cast-><%= field.name %>); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + <%- when Prism::Template::ConstantListField -%> + const pm_constant_id_list_t *<%= field.name %> = &cast-><%= field.name %>; + pm_buffer_append_byte(buffer, '['); + + for (size_t index = 0; index < <%= field.name %>->size; index++) { + if (index != 0) pm_buffer_append_byte(buffer, ','); + pm_dump_json_constant(buffer, parser, <%= field.name %>->ids[index]); + } + pm_buffer_append_byte(buffer, ']'); + <%- when Prism::Template::LocationField -%> + pm_dump_json_location(buffer, &cast-><%= field.name %>); + <%- when Prism::Template::OptionalLocationField -%> + if (cast-><%= field.name %>.length != 0) { + pm_dump_json_location(buffer, &cast-><%= field.name %>); + } else { + pm_buffer_append_string(buffer, "null", 4); + } + <%- when Prism::Template::UInt8Field -%> + pm_buffer_append_format(buffer, "%" PRIu8, cast-><%= field.name %>); + <%- when Prism::Template::UInt32Field -%> + pm_buffer_append_format(buffer, "%" PRIu32, cast-><%= field.name %>); + <%- when Prism::Template::Flags -%> + size_t flags = 0; + pm_buffer_append_byte(buffer, '['); + <%- node.flags.values.each_with_index do |value, index| -%> + if (PM_NODE_FLAG_P(cast, PM_<%= node.flags.human.upcase %>_<%= value.name %>)) { + if (flags != 0) pm_buffer_append_byte(buffer, ','); + pm_buffer_append_string(buffer, "\"<%= value.name %>\"", <%= value.name.bytesize + 2 %>); + flags++; + } + <%- end -%> + pm_buffer_append_byte(buffer, ']'); + <%- when Prism::Template::IntegerField -%> + pm_integer_string(buffer, &cast-><%= field.name %>); + <%- when Prism::Template::DoubleField -%> + pm_buffer_append_format(buffer, "%f", cast-><%= field.name %>); + <%- else -%> + <%- raise %> + <%- end -%> + <%- end -%> + + pm_buffer_append_byte(buffer, '}'); + break; + } + <%- end -%> + case PM_SCOPE_NODE: + break; + } +} + +#endif diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 695175d7c8..7b95200632 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -2,14 +2,8 @@ #include "prism/internal/node.h" #include "prism/internal/arena.h" -#include "prism/internal/buffer.h" -#include "prism/internal/constant_pool.h" -#include "prism/internal/integer.h" -#include "prism/internal/parser.h" -#include #include -#include /** * Attempts to grow the node list to the next size. If there is already @@ -150,127 +144,6 @@ pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *nod break; } } - -// We optionally support dumping to JSON. For systems that don't want or need -// this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. -#ifndef PRISM_EXCLUDE_JSON - -static void -pm_dump_json_constant(pm_buffer_t *buffer, const pm_parser_t *parser, pm_constant_id_t constant_id) { - const pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id); - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, constant->start, constant->length, PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); -} - -static void -pm_dump_json_location(pm_buffer_t *buffer, const pm_location_t *location) { - pm_buffer_append_format(buffer, "{\"start\":%" PRIu32 ",\"length\":%" PRIu32 "}", location->start, location->length); -} - -/** - * Dump JSON to the given buffer. - */ -void -pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) { - switch (PM_NODE_TYPE(node)) { - <%- nodes.each do |node| -%> - case <%= node.type %>: { - pm_buffer_append_string(buffer, "{\"type\":\"<%= node.name %>\",\"location\":", <%= node.name.bytesize + 22 %>); - - const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - <%- [*node.flags, *node.fields].each_with_index do |field, index| -%> - - // Dump the <%= field.name %> field - pm_buffer_append_byte(buffer, ','); - <%- if field.is_a?(Prism::Template::Flags) -%> - pm_buffer_append_string(buffer, "\"flags\":", 8); - <%- else -%> - pm_buffer_append_string(buffer, "\"<%= field.name %>\":", <%= field.name.bytesize + 3 %>); - <%- end -%> - <%- case field -%> - <%- when Prism::Template::NodeField -%> - pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>); - <%- when Prism::Template::OptionalNodeField -%> - if (cast-><%= field.name %> != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - <%- when Prism::Template::NodeListField -%> - const pm_node_list_t *<%= field.name %> = &cast-><%= field.name %>; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < <%= field.name %>->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, <%= field.name %>->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - <%- when Prism::Template::StringField -%> - const pm_string_t *<%= field.name %> = &cast-><%= field.name %>; - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, pm_string_source(<%= field.name %>), pm_string_length(<%= field.name %>), PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); - <%- when Prism::Template::ConstantField -%> - pm_dump_json_constant(buffer, parser, cast-><%= field.name %>); - <%- when Prism::Template::OptionalConstantField -%> - if (cast-><%= field.name %> != PM_CONSTANT_ID_UNSET) { - pm_dump_json_constant(buffer, parser, cast-><%= field.name %>); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - <%- when Prism::Template::ConstantListField -%> - const pm_constant_id_list_t *<%= field.name %> = &cast-><%= field.name %>; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < <%= field.name %>->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, <%= field.name %>->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - <%- when Prism::Template::LocationField -%> - pm_dump_json_location(buffer, &cast-><%= field.name %>); - <%- when Prism::Template::OptionalLocationField -%> - if (cast-><%= field.name %>.length != 0) { - pm_dump_json_location(buffer, &cast-><%= field.name %>); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - <%- when Prism::Template::UInt8Field -%> - pm_buffer_append_format(buffer, "%" PRIu8, cast-><%= field.name %>); - <%- when Prism::Template::UInt32Field -%> - pm_buffer_append_format(buffer, "%" PRIu32, cast-><%= field.name %>); - <%- when Prism::Template::Flags -%> - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - <%- node.flags.values.each_with_index do |value, index| -%> - if (PM_NODE_FLAG_P(cast, PM_<%= node.flags.human.upcase %>_<%= value.name %>)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"<%= value.name %>\"", <%= value.name.bytesize + 2 %>); - flags++; - } - <%- end -%> - pm_buffer_append_byte(buffer, ']'); - <%- when Prism::Template::IntegerField -%> - pm_integer_string(buffer, &cast-><%= field.name %>); - <%- when Prism::Template::DoubleField -%> - pm_buffer_append_format(buffer, "%f", cast-><%= field.name %>); - <%- else -%> - <%- raise %> - <%- end -%> - <%- end -%> - - pm_buffer_append_byte(buffer, '}'); - break; - } - <%- end -%> - case PM_SCOPE_NODE: - break; - } -} - -#endif <%- nodes.each do |node| -%> <%- params = node.fields.map(&:c_param) -%> diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index ffe9b1f307..cede4b9d02 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -1,6 +1,11 @@ <%# encoding: ASCII -%> #include "prism/prettyprint.h" +/* We optionally support pretty printing nodes. For systems that don't want or + * need this functionality, it can be turned off with the + * PRISM_EXCLUDE_PRETTYPRINT define. */ +#ifndef PRISM_EXCLUDE_PRETTYPRINT + #include "prism/compiler/inline.h" #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" @@ -10,15 +15,6 @@ #include -// We optionally support pretty printing nodes. For systems that don't want or -// need this functionality, it can be turned off with the -// PRISM_EXCLUDE_PRETTYPRINT define. -#ifdef PRISM_EXCLUDE_PRETTYPRINT - -void pm_prettyprint(void) {} - -#else - static PRISM_INLINE void prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) { pm_line_column_t start = pm_line_offset_list_line_column(&parser->line_offsets, location->start, parser->start_line); diff --git a/templates/template.rb b/templates/template.rb index fb778871b4..a84a912366 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -702,6 +702,7 @@ def locals "lib/prism/serialize.rb", "lib/prism/visitor.rb", "src/diagnostic.c", + "src/json.c", "src/node.c", "src/prettyprint.c", "src/serialize.c", From f02d270409d7e3033e628b2af9dd538cb804103f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 14:06:56 -0400 Subject: [PATCH 224/289] Move parse_success_p into serialization functions --- include/prism.h | 27 --------------------------- include/prism/parser.h | 10 ++++++++++ include/prism/serialize.h | 10 ++++++++++ include/prism/version.h | 7 +++++++ lib/prism/ffi.rb | 11 ++++++++--- src/prism.c | 22 ---------------------- templates/src/serialize.c.erb | 22 ++++++++++++++++++++++ 7 files changed, 57 insertions(+), 52 deletions(-) diff --git a/include/prism.h b/include/prism.h index b344a43691..d082e2f655 100644 --- a/include/prism.h +++ b/include/prism.h @@ -24,33 +24,6 @@ extern "C" { #include "prism/string_query.h" #include "prism/version.h" -/** - * The prism version and the serialization format. - * - * @returns The prism version as a constant string. - */ -PRISM_EXPORTED_FUNCTION const char * pm_version(void); - -/** - * Initiate the parser with the given parser. - * - * @param parser The parser to use. - * @return The AST representing the source. - * - * \public \memberof pm_parser - */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser); - -/** - * Parse the source and return true if it parses without errors or warnings. - * - * @param source The source to parse. - * @param size The size of the source. - * @param data The optional data to pass to the parser. - * @return True if the source parses without errors or warnings. - */ -PRISM_EXPORTED_FUNCTION bool pm_parse_success_p(const uint8_t *source, size_t size, const char *data); - /** * @mainpage * diff --git a/include/prism/parser.h b/include/prism/parser.h index f49155799d..f3927d663f 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -285,4 +285,14 @@ typedef void (*pm_constant_callback_t)(const pm_constant_t *constant, void *data */ PRISM_EXPORTED_FUNCTION void pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callback, void *data); +/** + * Initiate the parser with the given parser. + * + * @param parser The parser to use. + * @return The AST representing the source. + * + * \public \memberof pm_parser + */ +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser); + #endif diff --git a/include/prism/serialize.h b/include/prism/serialize.h index b2e93e5e9b..775fa6fbfb 100644 --- a/include/prism/serialize.h +++ b/include/prism/serialize.h @@ -81,6 +81,16 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_lex(pm_buffer_t *buffer, const uint8_t */ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); +/** + * Parse the source and return true if it parses without errors or warnings. + * + * @param source The source to parse. + * @param size The size of the source. + * @param data The optional data to pass to the parser. + * @return True if the source parses without errors or warnings. + */ +PRISM_EXPORTED_FUNCTION bool pm_serialize_parse_success_p(const uint8_t *source, size_t size, const char *data); + #endif #endif diff --git a/include/prism/version.h b/include/prism/version.h index b95611f96c..99cc99158e 100644 --- a/include/prism/version.h +++ b/include/prism/version.h @@ -26,4 +26,11 @@ */ #define PRISM_VERSION "1.9.0" +/** + * The prism version and the serialization format. + * + * @returns The prism version as a constant string. + */ +PRISM_EXPORTED_FUNCTION const char * pm_version(void); + #endif diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index d4a9ad0302..7b22a1304c 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -91,14 +91,19 @@ def self.load_exported_functions_from(header, *functions, callbacks) enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE] load_exported_functions_from( - "prism.h", + "prism/version.h", "pm_version", + [] + ) + + load_exported_functions_from( + "prism/serialize.h", "pm_serialize_parse", "pm_serialize_parse_stream", "pm_serialize_parse_comments", "pm_serialize_lex", "pm_serialize_parse_lex", - "pm_parse_success_p", + "pm_serialize_parse_success_p", [:pm_parse_stream_fgets_t, :pm_parse_stream_feof_t] ) @@ -404,7 +409,7 @@ def parse_lex_common(string, code, options) # :nodoc: end def parse_file_success_common(string, options) # :nodoc: - LibRubyParser.pm_parse_success_p(string.pointer, string.length, dump_options(options)) + LibRubyParser.pm_serialize_parse_success_p(string.pointer, string.length, dump_options(options)) end # Return the value that should be dumped for the command_line option. diff --git a/src/prism.c b/src/prism.c index 3f8e3ad870..901b8971cd 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22778,28 +22778,6 @@ pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, vo return node; } -/** - * Parse the source and return true if it parses without errors or warnings. - */ -bool -pm_parse_success_p(const uint8_t *source, size_t size, const char *data) { - pm_options_t options = { 0 }; - pm_options_read(&options, data); - - pm_arena_t arena = { 0 }; - pm_parser_t parser; - pm_parser_init(&arena, &parser, source, size, &options); - - pm_parse(&parser); - - bool result = parser.error_list.size == 0; - pm_parser_cleanup(&parser); - pm_arena_cleanup(&arena); - pm_options_cleanup(&options); - - return result; -} - #undef PM_CASE_KEYWORD #undef PM_CASE_OPERATOR #undef PM_CASE_WRITABLE diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index c92300b33d..0263ef56cc 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -373,4 +373,26 @@ pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, pm_options_cleanup(&options); } +/** + * Parse the source and return true if it parses without errors or warnings. + */ +bool +pm_serialize_parse_success_p(const uint8_t *source, size_t size, const char *data) { + pm_options_t options = { 0 }; + pm_options_read(&options, data); + + pm_arena_t arena = { 0 }; + pm_parser_t parser; + pm_parser_init(&arena, &parser, source, size, &options); + + pm_parse(&parser); + + bool result = parser.error_list.size == 0; + pm_parser_cleanup(&parser); + pm_arena_cleanup(&arena); + pm_options_cleanup(&options); + + return result; +} + #endif From d54885e7cccc6c4ae6e9781527f4572d23a69e16 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 14:13:40 -0400 Subject: [PATCH 225/289] Naming conventions --- ext/prism/extension.c | 32 +++++++++++++++---------------- include/prism/options.h | 12 ++++++------ rust/ruby-prism-sys/build/main.rs | 4 ++-- rust/ruby-prism/src/lib.rs | 6 +++--- src/options.c | 12 ++++++------ src/prism.c | 4 ++-- 6 files changed, 35 insertions(+), 35 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 2c64ff14ed..0c9458e6cf 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -148,7 +148,7 @@ build_options_scopes(pm_options_t *options, VALUE scopes) { // Initialize the scope array. size_t locals_count = RARRAY_LEN(locals); - pm_options_scope_t *options_scope = pm_options_scope_get_mut(options, scope_index); + pm_options_scope_t *options_scope = pm_options_scope_mut(options, scope_index); pm_options_scope_init(options_scope, locals_count); // Iterate over the locals and add them to the scope. @@ -162,7 +162,7 @@ build_options_scopes(pm_options_t *options, VALUE scopes) { } // Add the local to the scope. - pm_string_t *scope_local = pm_options_scope_local_get_mut(options_scope, local_index); + pm_string_t *scope_local = pm_options_scope_local_mut(options_scope, local_index); const char *name = rb_id2name(SYM2ID(local)); pm_string_constant_init(scope_local, name, strlen(name)); } @@ -327,7 +327,7 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V *encoded_filepath = rb_str_encode_ospath(filepath); extract_options(options, *encoded_filepath, keywords); - const char *source = (const char *) pm_string_source(pm_options_filepath_get(options)); + const char *source = (const char *) pm_string_source(pm_options_filepath(options)); pm_string_init_result_t result; switch (result = pm_string_file_init(input, source)) { @@ -408,7 +408,7 @@ dump(int argc, VALUE *argv, VALUE self) { #endif VALUE value = dump_input(&input, options); - if (pm_options_freeze_get(options)) rb_obj_freeze(value); + if (pm_options_freeze(options)) rb_obj_freeze(value); #ifdef PRISM_BUILD_DEBUG xfree_sized(dup, length); @@ -789,7 +789,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod .source = source, .tokens = rb_ary_new(), .encoding = rb_utf8_encoding(), - .freeze = pm_options_freeze_get(options), + .freeze = pm_options_freeze(options), }; parse_lex_data_t *data = &parse_lex_data; @@ -809,7 +809,7 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod rb_ary_push(offsets, ULONG2NUM(line_offsets->offsets[index])); } - if (pm_options_freeze_get(options)) { + if (pm_options_freeze(options)) { rb_obj_freeze(source_string); rb_obj_freeze(offsets); rb_obj_freeze(source); @@ -819,12 +819,12 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod VALUE result; if (return_nodes) { VALUE value = rb_ary_new_capa(2); - rb_ary_push(value, pm_ast_new(parser, node, parse_lex_data.encoding, source, pm_options_freeze_get(options))); + rb_ary_push(value, pm_ast_new(parser, node, parse_lex_data.encoding, source, pm_options_freeze(options))); rb_ary_push(value, parse_lex_data.tokens); - if (pm_options_freeze_get(options)) rb_obj_freeze(value); - result = parse_result_create(rb_cPrismParseLexResult, parser, value, parse_lex_data.encoding, source, pm_options_freeze_get(options)); + if (pm_options_freeze(options)) rb_obj_freeze(value); + result = parse_result_create(rb_cPrismParseLexResult, parser, value, parse_lex_data.encoding, source, pm_options_freeze(options)); } else { - result = parse_result_create(rb_cPrismLexResult, parser, parse_lex_data.tokens, parse_lex_data.encoding, source, pm_options_freeze_get(options)); + result = parse_result_create(rb_cPrismLexResult, parser, parse_lex_data.tokens, parse_lex_data.encoding, source, pm_options_freeze(options)); } pm_parser_free(parser); @@ -892,7 +892,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) { pm_node_t *node = pm_parse(parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); - bool freeze = pm_options_freeze_get(options); + bool freeze = pm_options_freeze(options); VALUE source = pm_source_new(parser, encoding, freeze); VALUE value = pm_ast_new(parser, node, encoding, source, freeze); VALUE result = parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, freeze); @@ -1111,9 +1111,9 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_node_t *node = pm_parse_stream(&parser, arena, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, options); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); - VALUE source = pm_source_new(parser, encoding, pm_options_freeze_get(options)); - VALUE value = pm_ast_new(parser, node, encoding, source, pm_options_freeze_get(options)); - VALUE result = parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, pm_options_freeze_get(options)); + VALUE source = pm_source_new(parser, encoding, pm_options_freeze(options)); + VALUE value = pm_ast_new(parser, node, encoding, source, pm_options_freeze(options)); + VALUE result = parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, pm_options_freeze(options)); pm_buffer_free(buffer); pm_parser_free(parser); @@ -1134,8 +1134,8 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { pm_parse(parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); - VALUE source = pm_source_new(parser, encoding, pm_options_freeze_get(options)); - VALUE comments = parser_comments(parser, source, pm_options_freeze_get(options)); + VALUE source = pm_source_new(parser, encoding, pm_options_freeze(options)); + VALUE comments = parser_comments(parser, source, pm_options_freeze(options)); pm_parser_free(parser); pm_arena_free(arena); diff --git a/include/prism/options.h b/include/prism/options.h index 61afc0df92..c1df928e06 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -143,7 +143,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *optio * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath_get(const pm_options_t *options); +PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath(const pm_options_t *options); /** * Set the filepath option on the given options struct. @@ -266,7 +266,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION bool pm_options_freeze_get(const pm_options_t *options); +PRISM_EXPORTED_FUNCTION bool pm_options_freeze(const pm_options_t *options); /** * Set the freeze option on the given options struct. @@ -299,7 +299,7 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_ * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index); +PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope(const pm_options_t *options, size_t index); /** * Return a mutable pointer to the scope at the given index within the given @@ -311,7 +311,7 @@ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_get_mut(pm_options_t *options, size_t index); +PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_mut(pm_options_t *options, size_t index); /** * Create a new options scope struct. This will hold a set of locals that are in @@ -335,7 +335,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, si * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index); +PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local(const pm_options_scope_t *scope, size_t index); /** * Return a mutable pointer to the local at the given index within the given @@ -347,7 +347,7 @@ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_ * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_get_mut(pm_options_scope_t *scope, size_t index); +PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_mut(pm_options_scope_t *scope, size_t index); /** * Set the forwarding option on the given scope struct. diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 9c4d807030..bf9c8e2db7 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -157,9 +157,9 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_function("pm_options_new") .allowlist_function("pm_options_partial_script_set") .allowlist_function("pm_options_scope_forwarding_set") - .allowlist_function("pm_options_scope_get_mut") + .allowlist_function("pm_options_scope_mut") .allowlist_function("pm_options_scope_init") - .allowlist_function("pm_options_scope_local_get_mut") + .allowlist_function("pm_options_scope_local_mut") .allowlist_function("pm_options_scopes_init") .allowlist_function("pm_options_version_set") .allowlist_function("pm_parse") diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index 7c678e1a67..b841af7807 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -28,7 +28,7 @@ pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnos use ruby_prism_sys::{ pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_free, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_new, pm_options_partial_script_set, pm_options_scope_forwarding_set, - pm_options_scope_get_mut, pm_options_scope_init, pm_options_scope_local_get_mut, pm_options_scopes_init, pm_options_t, pm_options_version_set, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, + pm_options_scope_mut, pm_options_scope_init, pm_options_scope_local_mut, pm_options_scopes_init, pm_options_t, pm_options_version_set, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, }; /// The version of Ruby syntax to parse with. @@ -287,11 +287,11 @@ impl Options { unsafe { pm_options_scopes_init(opts, self.scopes.len()) }; for (scope_index, scope) in self.scopes.iter().enumerate() { - let pm_scope = unsafe { pm_options_scope_get_mut(opts, scope_index) }; + let pm_scope = unsafe { pm_options_scope_mut(opts, scope_index) }; unsafe { pm_options_scope_init(pm_scope, scope.locals.len()) }; for (local_index, local) in scope.locals.iter().enumerate() { - let pm_local = unsafe { pm_options_scope_local_get_mut(pm_scope, local_index) }; + let pm_local = unsafe { pm_options_scope_local_mut(pm_scope, local_index) }; unsafe { pm_string_constant_init(pm_local, local.as_ptr().cast::(), local.len()) }; } diff --git a/src/options.c b/src/options.c index 9dbafdf63c..59f1dd4f17 100644 --- a/src/options.c +++ b/src/options.c @@ -64,7 +64,7 @@ pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callba * Get the filepath option on the given options struct. */ const pm_string_t * -pm_options_filepath_get(const pm_options_t *options) { +pm_options_filepath(const pm_options_t *options) { return &options->filepath; } @@ -230,7 +230,7 @@ pm_options_partial_script_set(pm_options_t *options, bool partial_script) { * Get the freeze option on the given options struct. */ bool -pm_options_freeze_get(const pm_options_t *options) { +pm_options_freeze(const pm_options_t *options) { return options->freeze; } @@ -265,7 +265,7 @@ pm_options_scopes_init(pm_options_t *options, size_t scopes_count) { * options. */ const pm_options_scope_t * -pm_options_scope_get(const pm_options_t *options, size_t index) { +pm_options_scope(const pm_options_t *options, size_t index) { return &options->scopes[index]; } @@ -274,7 +274,7 @@ pm_options_scope_get(const pm_options_t *options, size_t index) { * options. */ pm_options_scope_t * -pm_options_scope_get_mut(pm_options_t *options, size_t index) { +pm_options_scope_mut(pm_options_t *options, size_t index) { return &options->scopes[index]; } @@ -295,7 +295,7 @@ pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) { * scope. */ const pm_string_t * -pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { +pm_options_scope_local(const pm_options_scope_t *scope, size_t index) { return &scope->locals[index]; } @@ -304,7 +304,7 @@ pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { * scope. */ pm_string_t * -pm_options_scope_local_get_mut(pm_options_scope_t *scope, size_t index) { +pm_options_scope_local_mut(pm_options_scope_t *scope, size_t index) { return &scope->locals[index]; } diff --git a/src/prism.c b/src/prism.c index 901b8971cd..4bafdf3bb8 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22339,7 +22339,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si if (parser->parsing_eval) parser->warn_mismatched_indentation = false; for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { - const pm_options_scope_t *scope = pm_options_scope_get(options, scope_index); + const pm_options_scope_t *scope = pm_options_scope(options, scope_index); pm_parser_scope_push(parser, scope_index == 0); // Scopes given from the outside are not allowed to have numbered @@ -22347,7 +22347,7 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si parser->current_scope->parameters = ((pm_scope_parameters_t) scope->forwarding) | PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED; for (size_t local_index = 0; local_index < scope->locals_count; local_index++) { - const pm_string_t *local = pm_options_scope_local_get(scope, local_index); + const pm_string_t *local = pm_options_scope_local(scope, local_index); const uint8_t *source = pm_string_source(local); size_t length = pm_string_length(local); From 06a944a08fa1c1c8f24d7417c17b2e9bb9db4d16 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 14:23:02 -0400 Subject: [PATCH 226/289] Make some token logic internal --- .gitignore | 2 +- include/prism/internal/tokens.h | 17 +++++ prism.gemspec | 2 +- src/prism.c | 71 ++++++++++--------- templates/ext/prism/api_node.c.erb | 2 +- templates/include/prism/ast.h.erb | 15 ++-- .../src/{token_type.c.erb => tokens.c.erb} | 8 +-- templates/template.rb | 2 +- 8 files changed, 65 insertions(+), 54 deletions(-) create mode 100644 include/prism/internal/tokens.h rename templates/src/{token_type.c.erb => tokens.c.erb} (98%) diff --git a/.gitignore b/.gitignore index 7df40e7ba6..5bce199577 100644 --- a/.gitignore +++ b/.gitignore @@ -57,7 +57,7 @@ out.svg /src/node.c /src/prettyprint.c /src/serialize.c -/src/token_type.c +/src/tokens.c /src/**/*.o /rbi/prism/dsl.rbi /rbi/prism/node.rbi diff --git a/include/prism/internal/tokens.h b/include/prism/internal/tokens.h new file mode 100644 index 0000000000..05651bf5c8 --- /dev/null +++ b/include/prism/internal/tokens.h @@ -0,0 +1,17 @@ +/** + * @file internal/tokens.h + */ +#ifndef PRISM_INTERNAL_TOKENS_H +#define PRISM_INTERNAL_TOKENS_H + +#include "prism/ast.h" + +/** + * Returns the human name of the given token type. + * + * @param token_type The token type to convert to a human name. + * @return The human name of the given token type. + */ +const char * pm_token_str(pm_token_type_t token_type); + +#endif diff --git a/prism.gemspec b/prism.gemspec index d3fd8da546..4c9b685427 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -208,7 +208,7 @@ Gem::Specification.new do |spec| "src/strings.c", "src/strncasecmp.c", "src/strpbrk.c", - "src/token_type.c" + "src/tokens.c" ] spec.extensions = ["ext/prism/extconf.rb"] diff --git a/src/prism.c b/src/prism.c index 4bafdf3bb8..18249acc71 100644 --- a/src/prism.c +++ b/src/prism.c @@ -26,6 +26,7 @@ #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" #include "prism/internal/strpbrk.h" +#include "prism/internal/tokens.h" #include "prism/excludes.h" #include "prism/serialize.h" @@ -10348,7 +10349,7 @@ parser_lex(pm_parser_t *parser) { // , case ',': if ((parser->previous.type == PM_TOKEN_COMMA) && (parser->enclosure_nesting > 0)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_ARRAY_TERM, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_ARRAY_TERM, pm_token_str(parser->current.type)); } lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL); @@ -13487,7 +13488,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) { // This is an inlined version of accept1 because the error that we // want to add has varargs. If this happens again, we should // probably extract a helper function. - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(parser->current.type)); parser->previous.start = parser->previous.end; parser->previous.type = 0; } @@ -15102,7 +15103,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT, (uint8_t) (flags & ~PM_PARSE_ACCEPTS_DO_BLOCK), (uint16_t) (depth + 1)); if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_ARGUMENT_TERM_PAREN, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_ARGUMENT_TERM_PAREN, pm_token_str(parser->current.type)); parser->previous.start = parser->previous.end; parser->previous.type = 0; } @@ -15124,7 +15125,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept // then we have a trailing comma where we need to check whether it is // allowed or not. if (parser->previous.type == PM_TOKEN_COMMA && !match1(parser, PM_TOKEN_SEMICOLON)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, PM_ERR_EXPECT_ARGUMENT, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, PM_ERR_EXPECT_ARGUMENT, pm_token_str(parser->current.type)); } pm_accepts_block_stack_pop(parser); @@ -16101,7 +16102,7 @@ parse_method_definition_name(pm_parser_t *parser) { parser_lex(parser); return parser->previous; default: - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_DEF_NAME, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_DEF_NAME, pm_token_str(parser->current.type)); return (pm_token_t) { .type = 0, .start = parser->current.start, .end = parser->current.end }; } } @@ -16303,7 +16304,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint1 } else if (accept1(parser, PM_TOKEN_STRING_END)) { node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped)); } else { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_type_human(parser->previous.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_str(parser->previous.type)); parser->previous.start = parser->previous.end; parser->previous.type = 0; node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped)); @@ -16940,7 +16941,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm first_node = parse_expression(parser, PM_BINDING_POWER_MAX, PM_PARSE_ACCEPTS_DO_BLOCK | PM_PARSE_ACCEPTS_LABEL, PM_ERR_PATTERN_HASH_KEY_LABEL, (uint16_t) (depth + 1)); break; default: { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_PATTERN_HASH_KEY, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_PATTERN_HASH_KEY, pm_token_str(parser->current.type)); parser_lex(parser); first_node = UP(pm_missing_node_create(parser, PM_TOKEN_START(parser, &parser->previous), PM_TOKEN_LENGTH(&parser->previous))); @@ -17413,22 +17414,22 @@ static void pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { switch (diag_id) { case PM_ERR_HASH_KEY: { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, diag_id, pm_token_type_human(parser->previous.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, diag_id, pm_token_str(parser->previous.type)); break; } case PM_ERR_HASH_VALUE: case PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR: { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, diag_id, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, diag_id, pm_token_str(parser->current.type)); break; } case PM_ERR_UNARY_RECEIVER: { - const char *human = (parser->current.type == PM_TOKEN_EOF ? "end-of-input" : pm_token_type_human(parser->current.type)); + const char *human = (parser->current.type == PM_TOKEN_EOF ? "end-of-input" : pm_token_str(parser->current.type)); PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, diag_id, human, parser->previous.start[0]); break; } case PM_ERR_UNARY_DISALLOWED: case PM_ERR_EXPECT_ARGUMENT: { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, diag_id, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, diag_id, pm_token_str(parser->current.type)); break; } default: @@ -17751,7 +17752,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u } else { // If there was no comma, then we need to add a syntax // error. - PM_PARSER_ERR_FORMAT(parser, PM_TOKEN_END(parser, &parser->previous), 0, PM_ERR_ARRAY_SEPARATOR, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_FORMAT(parser, PM_TOKEN_END(parser, &parser->previous), 0, PM_ERR_ARRAY_SEPARATOR, pm_token_str(parser->current.type)); parser->previous.start = parser->previous.end; parser->previous.type = 0; } @@ -17827,7 +17828,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u accept1(parser, PM_TOKEN_NEWLINE); if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_ARRAY_TERM, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_ARRAY_TERM, pm_token_str(parser->current.type)); parser->previous.start = parser->previous.end; parser->previous.type = 0; } @@ -17970,7 +17971,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u // If we didn't find a terminator and we didn't find a right // parenthesis, then this is a syntax error. if (!terminator_found && !match1(parser, PM_TOKEN_EOF)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(parser->current.type)); } // Parse each statement within the parentheses. @@ -18001,7 +18002,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u } else if (!match1(parser, PM_TOKEN_EOF)) { // If we're at the end of the file, then we're going to add // an error after this for the ) anyway. - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(parser->current.type)); } } @@ -18760,7 +18761,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u // Reject `foo && return bar`. if (!(flags & PM_PARSE_ACCEPTS_COMMAND_CALL) && arguments.arguments != NULL) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(next.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(next.type)); } } } @@ -18841,7 +18842,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u pm_parser_scope_push(parser, true); if (!match2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_SINGLETON_CLASS_DELIMITER, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_SINGLETON_CLASS_DELIMITER, pm_token_str(parser->current.type)); } pm_node_t *statements = NULL; @@ -19046,7 +19047,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u name = parse_method_definition_name(parser); } else { if (!valid_name) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &identifier, PM_ERR_DEF_NAME, pm_token_type_human(identifier.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &identifier, PM_ERR_DEF_NAME, pm_token_str(identifier.type)); } name = identifier; @@ -19120,7 +19121,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u context_pop(parser); if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_DEF_PARAMS_TERM_PAREN, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_DEF_PARAMS_TERM_PAREN, pm_token_str(parser->current.type)); parser->previous.start = parser->previous.end; parser->previous.type = 0; } @@ -19232,7 +19233,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u // `def f = def g = foo bar`) is a command assignment and // cannot appear as a def body. if (PM_NODE_TYPE_P(statement, PM_DEF_NODE) && pm_command_call_value_p(statement)) { - PM_PARSER_ERR_NODE_FORMAT(parser, statement, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_NODE_FORMAT(parser, statement, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(parser->current.type)); } pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement, false); @@ -19407,7 +19408,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u do_keyword = parser->previous; } else { if (!match2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_FOR_DELIMITER, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_FOR_DELIMITER, pm_token_str(parser->current.type)); } } @@ -20439,12 +20440,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, u // If we get here, then we are assuming this token is closing a // parent context, so we'll indicate that to the user so that // they know how we behaved. - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT, pm_token_type_human(parser->current.type), context_human(recoverable)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT, pm_token_str(parser->current.type), context_human(recoverable)); } else if (diag_id == PM_ERR_CANNOT_PARSE_EXPRESSION) { // We're going to make a special case here, because "cannot // parse expression" is pretty generic, and we know here that we // have an unexpected token. - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, pm_token_str(parser->current.type)); } else { pm_parser_err_prefix(parser, diag_id); } @@ -20472,7 +20473,7 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ // operators with higher binding power. If we find one, emit an error // and skip the operator and its right-hand side. if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER && (pm_command_call_value_p(value) || pm_block_call_p(value))) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(parser->current.type)); parser_lex(parser); parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); } @@ -20578,7 +20579,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding // operators with higher binding power. If we find one, emit an error // and skip the operator and its right-hand side. if (single_value && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER && (pm_command_call_value_p(value) || pm_block_call_p(value))) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(parser->current.type)); parser_lex(parser); parse_expression(parser, pm_binding_powers[parser->previous.type].right, flags & PM_PARSE_ACCEPTS_DO_BLOCK, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1)); } @@ -21306,7 +21307,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // In this case we have an operator but we don't know what it's for. // We need to treat it as an error. For now, we'll mark it as an error // and just skip right past it. - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->previous, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, pm_token_str(parser->current.type)); return node; } } @@ -21428,21 +21429,21 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_RESCUE_MODIFIER_NODE: { pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; if (PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_REQUIRED_NODE)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(operator.type)); } break; } case PM_AND_NODE: { pm_and_node_t *cast = (pm_and_node_t *) node; if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(operator.type)); } break; } case PM_OR_NODE: { pm_or_node_t *cast = (pm_or_node_t *) node; if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(operator.type)); } break; } @@ -21481,21 +21482,21 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t case PM_RESCUE_MODIFIER_NODE: { pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; if (PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_REQUIRED_NODE)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(operator.type)); } break; } case PM_AND_NODE: { pm_and_node_t *cast = (pm_and_node_t *) node; if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(operator.type)); } break; } case PM_OR_NODE: { pm_or_node_t *cast = (pm_or_node_t *) node; if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_str(operator.type)); } break; } @@ -21516,7 +21517,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t break; } default: { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_MESSAGE, pm_token_type_human(parser->current.type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_EXPECT_MESSAGE, pm_token_str(parser->current.type)); message = (pm_token_t) { .type = 0, .start = parser->previous.end, .end = parser->previous.end }; } } @@ -21930,7 +21931,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t // If this is a non-assoc operator and we are about to parse the // exact same operator, then we need to add an error. if (match1(parser, current_token_type)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_type_human(parser->current.type), pm_token_type_human(current_token_type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_str(parser->current.type), pm_token_str(current_token_type)); break; } @@ -21943,7 +21944,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t // if (PM_NODE_TYPE_P(node, PM_RANGE_NODE) && ((pm_range_node_t *) node)->right == NULL) { if (match4(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_DOT, PM_TOKEN_AMPERSAND_DOT)) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_type_human(parser->current.type), pm_token_type_human(current_token_type)); + PM_PARSER_ERR_TOKEN_FORMAT(parser, &parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_str(parser->current.type), pm_token_str(current_token_type)); break; } diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index ca793b471c..6dd3a59372 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -25,7 +25,7 @@ pm_location_new(const uint32_t start, const uint32_t length, VALUE source, bool VALUE pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source, bool freeze) { - ID type = rb_intern(pm_token_type_name(token->type)); + ID type = rb_intern(pm_token_type(token->type)); VALUE location = pm_location_new((uint32_t) (token->start - pm_parser_start(parser)), (uint32_t) (token->end - token->start), source, freeze); VALUE slice = rb_enc_str_new((const char *) token->start, token->end - token->start, encoding); diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index f08e017fc0..e1b233918d 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -50,18 +50,11 @@ typedef struct { /** * Returns a string representation of the given token type. * - * @param token_type The token type to convert to a string. - * @return A string representation of the given token type. + * @param token_type The type of the token to get the string representation of. + * @return A string representation of the given token type. This is meant for + * debugging purposes and is not guaranteed to be stable across versions. */ -PRISM_EXPORTED_FUNCTION const char * pm_token_type_name(pm_token_type_t token_type); - -/** - * Returns the human name of the given token type. - * - * @param token_type The token type to convert to a human name. - * @return The human name of the given token type. - */ -const char * pm_token_type_human(pm_token_type_t token_type); +PRISM_EXPORTED_FUNCTION const char * pm_token_type(pm_token_type_t token_type); /** * This struct represents a slice in the source code, defined by an offset and diff --git a/templates/src/token_type.c.erb b/templates/src/tokens.c.erb similarity index 98% rename from templates/src/token_type.c.erb rename to templates/src/tokens.c.erb index cdf4e73658..1e82954738 100644 --- a/templates/src/token_type.c.erb +++ b/templates/src/tokens.c.erb @@ -6,7 +6,7 @@ * Returns a string representation of the given token type. */ const char * -pm_token_type_name(pm_token_type_t token_type) { +pm_token_type(pm_token_type_t token_type) { switch (token_type) { <%- tokens.each do |token| -%> case PM_TOKEN_<%= token.name %>: @@ -27,7 +27,7 @@ pm_token_type_name(pm_token_type_t token_type) { * Returns the human name of the given token type. */ const char * -pm_token_type_human(pm_token_type_t token_type) { +pm_token_str(pm_token_type_t token_type) { switch (token_type) { case PM_TOKEN_EOF: return "end-of-input"; @@ -360,8 +360,8 @@ pm_token_type_human(pm_token_type_t token_type) { return ""; } - // Provide a default, because some compilers can't determine that the above - // switch is exhaustive. + /* Provide a default, because some compilers cannot determine that the above + * switch is exhaustive. */ assert(false && "unreachable"); return ""; } diff --git a/templates/template.rb b/templates/template.rb index a84a912366..78c8ac1954 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -706,7 +706,7 @@ def locals "src/node.c", "src/prettyprint.c", "src/serialize.c", - "src/token_type.c" + "src/tokens.c" ] end end From 7dde21044733961f93903ca082dca3de2d518f4e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 14:35:08 -0400 Subject: [PATCH 227/289] Documentation on public API functions --- include/prism/arena.h | 6 ++-- include/prism/buffer.h | 10 +++--- include/prism/comments.h | 6 ++-- include/prism/compiler/nodiscard.h | 22 +++++++++++++ include/prism/compiler/nonnull.h | 18 +++++++++++ include/prism/constant_pool.h | 6 ++-- include/prism/diagnostic.h | 12 ++++--- include/prism/json.h | 3 +- include/prism/line_offset_list.h | 3 +- include/prism/magic_comments.h | 5 +-- include/prism/node.h | 9 +++--- include/prism/options.h | 51 ++++++++++++++++-------------- include/prism/parser.h | 51 ++++++++++++++++-------------- include/prism/prettyprint.h | 3 +- include/prism/serialize.h | 15 +++++---- include/prism/stream.h | 3 +- include/prism/string_query.h | 7 ++-- include/prism/strings.h | 13 ++++---- templates/src/node.c.erb | 2 +- 19 files changed, 155 insertions(+), 90 deletions(-) create mode 100644 include/prism/compiler/nodiscard.h create mode 100644 include/prism/compiler/nonnull.h diff --git a/include/prism/arena.h b/include/prism/arena.h index 1b1729bb24..890c98a7b4 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -7,6 +7,8 @@ #define PRISM_ARENA_H #include "prism/compiler/exported.h" +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" #include @@ -23,13 +25,13 @@ typedef struct pm_arena_t pm_arena_t; * the caller to free the arena using pm_arena_free when it is no longer * needed. */ -PRISM_EXPORTED_FUNCTION pm_arena_t * pm_arena_new(void); +PRISM_EXPORTED_FUNCTION pm_arena_t * pm_arena_new(void) PRISM_NODISCARD; /** * Frees both the held memory and the arena itself. * * @param arena The arena to free. */ -PRISM_EXPORTED_FUNCTION void pm_arena_free(pm_arena_t *arena); +PRISM_EXPORTED_FUNCTION void pm_arena_free(pm_arena_t *arena) PRISM_NONNULL(1); #endif diff --git a/include/prism/buffer.h b/include/prism/buffer.h index b6e8feea31..0d67633ede 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -7,6 +7,8 @@ #define PRISM_BUFFER_H #include "prism/compiler/exported.h" +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" #include @@ -24,7 +26,7 @@ typedef struct pm_buffer_t pm_buffer_t; * * \public \memberof pm_buffer_t */ -PRISM_EXPORTED_FUNCTION pm_buffer_t * pm_buffer_new(void); +PRISM_EXPORTED_FUNCTION pm_buffer_t * pm_buffer_new(void) PRISM_NODISCARD; /** * Free both the memory held by the buffer and the buffer itself. @@ -33,7 +35,7 @@ PRISM_EXPORTED_FUNCTION pm_buffer_t * pm_buffer_new(void); * * \public \memberof pm_buffer_t */ -PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer) PRISM_NONNULL(1); /** * Return the value of the buffer. @@ -43,7 +45,7 @@ PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer); * * \public \memberof pm_buffer_t */ -PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer) PRISM_NONNULL(1); /** * Return the length of the buffer. @@ -53,6 +55,6 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer); * * \public \memberof pm_buffer_t */ -PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer) PRISM_NONNULL(1); #endif diff --git a/include/prism/comments.h b/include/prism/comments.h index 91792897d9..3e2dfcddfd 100644 --- a/include/prism/comments.h +++ b/include/prism/comments.h @@ -5,6 +5,8 @@ #define PRISM_COMMENTS_H #include "prism/compiler/exported.h" +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" #include "prism/ast.h" @@ -25,7 +27,7 @@ typedef struct pm_comment_t pm_comment_t; * @param comment the comment whose location we want to get * @return the location associated with the given comment */ -PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *comment); +PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *comment) PRISM_NONNULL(1); /** * Returns the type associated with the given comment. @@ -34,6 +36,6 @@ PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *co * @return the type associated with the given comment. This can either be * PM_COMMENT_INLINE or PM_COMMENT_EMBDOC. */ -PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *comment); +PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *comment) PRISM_NONNULL(1); #endif diff --git a/include/prism/compiler/nodiscard.h b/include/prism/compiler/nodiscard.h new file mode 100644 index 0000000000..ccd6c00719 --- /dev/null +++ b/include/prism/compiler/nodiscard.h @@ -0,0 +1,22 @@ +/** + * @file compiler/nodiscard.h + */ +#ifndef PRISM_COMPILER_NODISCARD_H +#define PRISM_COMPILER_NODISCARD_H + +/** + * Mark the return value of a function as important so that the compiler warns + * if a caller ignores it. This is useful for functions that return error codes + * or allocated resources that must be freed. + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +# define PRISM_NODISCARD [[nodiscard]] +#elif defined(__GNUC__) || defined(__clang__) +# define PRISM_NODISCARD __attribute__((__warn_unused_result__)) +#elif defined(_MSC_VER) +# define PRISM_NODISCARD _Check_return_ +#else +# define PRISM_NODISCARD +#endif + +#endif diff --git a/include/prism/compiler/nonnull.h b/include/prism/compiler/nonnull.h new file mode 100644 index 0000000000..9d19355665 --- /dev/null +++ b/include/prism/compiler/nonnull.h @@ -0,0 +1,18 @@ +/** + * @file compiler/nonnull.h + */ +#ifndef PRISM_COMPILER_NONNULL_H +#define PRISM_COMPILER_NONNULL_H + +/** + * Mark the parameters of a function as non-null. This allows the compiler to + * warn if a caller passes NULL for a parameter that should never be NULL. The + * arguments are the 1-based indices of the parameters. + */ +#if defined(__GNUC__) || defined(__clang__) +# define PRISM_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else +# define PRISM_NONNULL(...) +#endif + +#endif diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index 08a06d1612..7fea4fad94 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -11,6 +11,8 @@ #define PRISM_CONSTANT_POOL_H #include "prism/compiler/exported.h" +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" #include #include @@ -46,7 +48,7 @@ typedef struct pm_constant_pool_t pm_constant_pool_t; * @param constant The constant to get the start of. * @return A raw pointer to the start of the constant. */ -PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *constant); +PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *constant) PRISM_NONNULL(1); /** * Return the length of a constant. @@ -54,6 +56,6 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *c * @param constant The constant to get the length of. * @return The length of the constant. */ -PRISM_EXPORTED_FUNCTION size_t pm_constant_length(const pm_constant_t *constant); +PRISM_EXPORTED_FUNCTION size_t pm_constant_length(const pm_constant_t *constant) PRISM_NONNULL(1); #endif diff --git a/include/prism/diagnostic.h b/include/prism/diagnostic.h index 6c098c55ef..f2b541024f 100644 --- a/include/prism/diagnostic.h +++ b/include/prism/diagnostic.h @@ -15,6 +15,8 @@ #define PRISM_DIAGNOSTIC_H #include "prism/compiler/exported.h" +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" #include "prism/ast.h" @@ -58,7 +60,7 @@ typedef enum { * not change in the future. This is meant to be used for debugging and * error reporting purposes, and not for programmatic checks. */ -PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_type(const pm_diagnostic_t *diagnostic); +PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_type(const pm_diagnostic_t *diagnostic) PRISM_NONNULL(1); /** * Get the location of the given diagnostic. @@ -66,7 +68,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_type(const pm_diagnostic_t *d * @param diagnostic The diagnostic to get the location of. * @returns The location of the given diagnostic. */ -PRISM_EXPORTED_FUNCTION pm_location_t pm_diagnostic_location(const pm_diagnostic_t *diagnostic); +PRISM_EXPORTED_FUNCTION pm_location_t pm_diagnostic_location(const pm_diagnostic_t *diagnostic) PRISM_NONNULL(1); /** * Get the message of the given diagnostic. @@ -74,7 +76,7 @@ PRISM_EXPORTED_FUNCTION pm_location_t pm_diagnostic_location(const pm_diagnostic * @param diagnostic The diagnostic to get the message of. * @returns The message of the given diagnostic. */ -PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_message(const pm_diagnostic_t *diagnostic); +PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_message(const pm_diagnostic_t *diagnostic) PRISM_NONNULL(1); /** * Get the error level associated with the given diagnostic. @@ -84,7 +86,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_diagnostic_message(const pm_diagnostic_t * warning, or is in any way not an error, then the return value is * undefined and should not be relied upon. */ -PRISM_EXPORTED_FUNCTION pm_error_level_t pm_diagnostic_error_level(const pm_diagnostic_t *diagnostic); +PRISM_EXPORTED_FUNCTION pm_error_level_t pm_diagnostic_error_level(const pm_diagnostic_t *diagnostic) PRISM_NONNULL(1); /** * Get the warning level associated with the given diagnostic. @@ -94,6 +96,6 @@ PRISM_EXPORTED_FUNCTION pm_error_level_t pm_diagnostic_error_level(const pm_diag * error, or is in any way not a warning, then the return value is * undefined and should not be relied upon. */ -PRISM_EXPORTED_FUNCTION pm_warning_level_t pm_diagnostic_warning_level(const pm_diagnostic_t *diagnostic); +PRISM_EXPORTED_FUNCTION pm_warning_level_t pm_diagnostic_warning_level(const pm_diagnostic_t *diagnostic) PRISM_NONNULL(1); #endif diff --git a/include/prism/json.h b/include/prism/json.h index cc2f6f3bb1..11039e7796 100644 --- a/include/prism/json.h +++ b/include/prism/json.h @@ -12,6 +12,7 @@ #ifndef PRISM_EXCLUDE_JSON #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include "prism/ast.h" #include "prism/buffer.h" @@ -24,7 +25,7 @@ * @param parser The parser that parsed the node. * @param node The node to serialize. */ -PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node); +PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) PRISM_NONNULL(1, 2, 3); #endif diff --git a/include/prism/line_offset_list.h b/include/prism/line_offset_list.h index 9d0ddf3889..e839862fea 100644 --- a/include/prism/line_offset_list.h +++ b/include/prism/line_offset_list.h @@ -15,6 +15,7 @@ #define PRISM_LINE_OFFSET_LIST_H #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include #include @@ -55,6 +56,6 @@ typedef struct { * @param start_line The line to start counting from. * @return The line and column of the given offset. */ -PRISM_EXPORTED_FUNCTION pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); +PRISM_EXPORTED_FUNCTION pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) PRISM_NONNULL(1); #endif diff --git a/include/prism/magic_comments.h b/include/prism/magic_comments.h index a19ecedb74..4941e94885 100644 --- a/include/prism/magic_comments.h +++ b/include/prism/magic_comments.h @@ -5,6 +5,7 @@ #define PRISM_MAGIC_COMMENTS_H #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include "prism/ast.h" @@ -19,7 +20,7 @@ typedef struct pm_magic_comment_t pm_magic_comment_t; * @param comment the magic comment whose key location we want to get * @return the location of the key associated with the given magic comment */ -PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_key(const pm_magic_comment_t *comment); +PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_key(const pm_magic_comment_t *comment) PRISM_NONNULL(1); /** * Returns the location of the value associated with the given magic comment. @@ -27,6 +28,6 @@ PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_key(const pm_magic_commen * @param comment the magic comment whose value location we want to get * @return the location of the value associated with the given magic comment */ -PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_value(const pm_magic_comment_t *comment); +PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_value(const pm_magic_comment_t *comment) PRISM_NONNULL(1); #endif diff --git a/include/prism/node.h b/include/prism/node.h index 5056bfbb26..7db4dcd891 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -7,6 +7,7 @@ #define PRISM_NODE_H #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include "prism/ast.h" @@ -23,7 +24,7 @@ * @param node_type The node type to convert to a string. * @return A string representation of the given node type. */ -PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_type); +PRISM_EXPORTED_FUNCTION const char * pm_node_type(pm_node_type_t node_type); /** * Visit each of the nodes in this subtree using the given visitor callback. The @@ -41,7 +42,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * bool visit(const pm_node_t *node, void *data) { * size_t *indent = (size_t *) data; * for (size_t i = 0; i < *indent * 2; i++) putc(' ', stdout); - * printf("%s\n", pm_node_type_to_str(node->type)); + * printf("%s\n", pm_node_type(node->type)); * * size_t next_indent = *indent + 1; * size_t *next_data = &next_indent; @@ -77,7 +78,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ * @param visitor The callback to call for each node in the subtree. * @param data An opaque pointer that is passed to the visitor callback. */ -PRISM_EXPORTED_FUNCTION void pm_visit_node(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data); +PRISM_EXPORTED_FUNCTION void pm_visit_node(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) PRISM_NONNULL(1); /** * Visit the children of the given node with the given callback. This is the @@ -88,6 +89,6 @@ PRISM_EXPORTED_FUNCTION void pm_visit_node(const pm_node_t *node, bool (*visitor * @param visitor The callback to call for each child node. * @param data An opaque pointer that is passed to the visitor callback. */ -PRISM_EXPORTED_FUNCTION void pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data); +PRISM_EXPORTED_FUNCTION void pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) PRISM_NONNULL(1); #endif diff --git a/include/prism/options.h b/include/prism/options.h index c1df928e06..10834f28e7 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -6,6 +6,9 @@ #ifndef PRISM_OPTIONS_H #define PRISM_OPTIONS_H +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" + #include "prism/strings.h" #include @@ -112,7 +115,7 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20; * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION pm_options_t * pm_options_new(void); +PRISM_EXPORTED_FUNCTION pm_options_t * pm_options_new(void) PRISM_NODISCARD; /** * Free both the held memory of the given options struct and the struct itself. @@ -121,7 +124,7 @@ PRISM_EXPORTED_FUNCTION pm_options_t * pm_options_new(void); * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); +PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options) PRISM_NONNULL(1); /** * Set the shebang callback option on the given options struct. @@ -133,7 +136,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data); +PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data) PRISM_NONNULL(1); /** * Get the filepath option on the given options struct. @@ -143,7 +146,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *optio * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath(const pm_options_t *options); +PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath(const pm_options_t *options) PRISM_NONNULL(1); /** * Set the filepath option on the given options struct. @@ -153,7 +156,7 @@ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath(const pm_options * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath); +PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath) PRISM_NONNULL(1); /** * Set the line option on the given options struct. @@ -163,7 +166,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, cons * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t line); +PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t line) PRISM_NONNULL(1); /** * Set the encoding option on the given options struct. @@ -173,7 +176,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding); +PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding) PRISM_NONNULL(1); /** * Set the encoding_locked option on the given options struct. @@ -183,7 +186,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, cons * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked); +PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) PRISM_NONNULL(1); /** * Set the frozen string literal option on the given options struct. @@ -193,7 +196,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *option * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal); +PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal) PRISM_NONNULL(1); /** * Sets the command line option on the given options struct. @@ -203,7 +206,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t * * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line); +PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line) PRISM_NONNULL(1); /** * Set the version option on the given options struct by parsing the given @@ -217,7 +220,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length); +PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length) PRISM_NONNULL(1); /** * Set the version option on the given options struct to the lowest version of @@ -227,7 +230,7 @@ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_version_set_lowest(pm_options_t *options); +PRISM_EXPORTED_FUNCTION void pm_options_version_set_lowest(pm_options_t *options) PRISM_NONNULL(1); /** * Set the version option on the given options struct to the highest version of @@ -237,7 +240,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_version_set_lowest(pm_options_t *options * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_version_set_highest(pm_options_t *options); +PRISM_EXPORTED_FUNCTION void pm_options_version_set_highest(pm_options_t *options) PRISM_NONNULL(1); /** * Set the main script option on the given options struct. @@ -247,7 +250,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_version_set_highest(pm_options_t *option * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, bool main_script); +PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, bool main_script) PRISM_NONNULL(1); /** * Set the partial script option on the given options struct. @@ -257,7 +260,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, b * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script); +PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script) PRISM_NONNULL(1); /** * Get the freeze option on the given options struct. @@ -266,7 +269,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION bool pm_options_freeze(const pm_options_t *options); +PRISM_EXPORTED_FUNCTION bool pm_options_freeze(const pm_options_t *options) PRISM_NONNULL(1); /** * Set the freeze option on the given options struct. @@ -276,7 +279,7 @@ PRISM_EXPORTED_FUNCTION bool pm_options_freeze(const pm_options_t *options); * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool freeze); +PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool freeze) PRISM_NONNULL(1); /** * Allocate and zero out the scopes array on the given options struct. @@ -287,7 +290,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool f * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count); +PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count) PRISM_NONNULL(1); /** * Return a constant pointer to the scope at the given index within the given @@ -299,7 +302,7 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_ * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope(const pm_options_t *options, size_t index); +PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope(const pm_options_t *options, size_t index) PRISM_NONNULL(1); /** * Return a mutable pointer to the scope at the given index within the given @@ -311,7 +314,7 @@ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope(const pm_opt * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_mut(pm_options_t *options, size_t index); +PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_mut(pm_options_t *options, size_t index) PRISM_NONNULL(1); /** * Create a new options scope struct. This will hold a set of locals that are in @@ -323,7 +326,7 @@ PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_mut(pm_options_t * * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count); +PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) PRISM_NONNULL(1); /** * Return a constant pointer to the local at the given index within the given @@ -335,7 +338,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, si * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local(const pm_options_scope_t *scope, size_t index); +PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local(const pm_options_scope_t *scope, size_t index) PRISM_NONNULL(1); /** * Return a mutable pointer to the local at the given index within the given @@ -347,7 +350,7 @@ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local(const pm_opti * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_mut(pm_options_scope_t *scope, size_t index); +PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_mut(pm_options_scope_t *scope, size_t index) PRISM_NONNULL(1); /** * Set the forwarding option on the given scope struct. @@ -357,6 +360,6 @@ PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_mut(pm_options_scop * * \public \memberof pm_options */ -PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding); +PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) PRISM_NONNULL(1); #endif diff --git a/include/prism/parser.h b/include/prism/parser.h index f3927d663f..6d9efa6485 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -6,6 +6,9 @@ #ifndef PRISM_PARSER_H #define PRISM_PARSER_H +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" + #include "prism/ast.h" #include "prism/comments.h" #include "prism/diagnostic.h" @@ -32,7 +35,7 @@ typedef struct pm_parser_t pm_parser_t; * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options); +PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options) PRISM_NODISCARD PRISM_NONNULL(1); /** * Free both the memory held by the given parser and the parser itself. @@ -41,7 +44,7 @@ PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uin * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser) PRISM_NONNULL(1); /** * When the encoding that is being used to parse the source is changed by prism, @@ -64,7 +67,7 @@ typedef void (*pm_lex_callback_t)(pm_parser_t *parser, pm_token_t *token, void * * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION void pm_parser_encoding_changed_callback_set(pm_parser_t *parser, pm_encoding_changed_callback_t callback); +PRISM_EXPORTED_FUNCTION void pm_parser_encoding_changed_callback_set(pm_parser_t *parser, pm_encoding_changed_callback_t callback) PRISM_NONNULL(1); /** * Register a callback that will be called whenever a token is lexed. @@ -75,7 +78,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_encoding_changed_callback_set(pm_parser_t * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION void pm_parser_lex_callback_set(pm_parser_t *parser, pm_lex_callback_t callback, void *data); +PRISM_EXPORTED_FUNCTION void pm_parser_lex_callback_set(pm_parser_t *parser, pm_lex_callback_t callback, void *data) PRISM_NONNULL(1); /** * Returns the opaque data that is passed to the lex callback when it is called. @@ -83,7 +86,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_lex_callback_set(pm_parser_t *parser, pm_ * @param parser The parser whose lex callback data we want to get. * @return The opaque data that is passed to the lex callback when it is called. */ -PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the raw pointer to the start of the source that is being parsed. @@ -91,7 +94,7 @@ PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(const pm_parser_t *pa * @param parser the parser whose start pointer we want to get * @return the raw pointer to the start of the source that is being parsed */ -PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_start(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_start(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the raw pointer to the end of the source that is being parsed. @@ -99,7 +102,7 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_start(const pm_parser_t *parse * @param parser the parser whose end pointer we want to get * @return the raw pointer to the end of the source that is being parsed */ -PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_end(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_end(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the line that the parser was considered to have started on. @@ -107,7 +110,7 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_end(const pm_parser_t *parser) * @param parser the parser whose start line we want to get * @return the line that the parser was considered to have started on */ -PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the name of the encoding that is being used to parse the source. @@ -115,7 +118,7 @@ PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser); * @param parser the parser whose encoding name we want to get * @return the name of the encoding that is being used to parse the source */ -PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the line offsets that are associated with the given parser. @@ -123,7 +126,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t * * @param parser the parser whose line offsets we want to get * @return the line offsets that are associated with the given parser */ -PRISM_EXPORTED_FUNCTION const pm_line_offset_list_t * pm_parser_line_offsets(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION const pm_line_offset_list_t * pm_parser_line_offsets(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the location of the __DATA__ section that is associated with the @@ -133,7 +136,7 @@ PRISM_EXPORTED_FUNCTION const pm_line_offset_list_t * pm_parser_line_offsets(con * @return the location of the __DATA__ section that is associated with the * given parser. If it is unset, then the length will be set to 0. */ -PRISM_EXPORTED_FUNCTION const pm_location_t * pm_parser_data_loc(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION const pm_location_t * pm_parser_data_loc(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns whether the given parser is continuable, meaning that it could become @@ -142,7 +145,7 @@ PRISM_EXPORTED_FUNCTION const pm_location_t * pm_parser_data_loc(const pm_parser * @param parser the parser whose continuable status we want to get * @return whether the given parser is continuable */ -PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the lex state of the parser. Note that this is an internal detail, @@ -153,7 +156,7 @@ PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser); * @param parser the parser whose lex state we want to get * @return the lex state of the parser */ -PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the number of comments associated with the given parser. @@ -161,7 +164,7 @@ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser); * @param parser the parser whose comments we want to get the size of * @return the number of comments associated with the given parser */ -PRISM_EXPORTED_FUNCTION size_t pm_parser_comments_size(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION size_t pm_parser_comments_size(const pm_parser_t *parser) PRISM_NONNULL(1); /** * A callback function that can be used to process comments found while parsing. @@ -179,7 +182,7 @@ typedef void (*pm_comment_callback_t)(const pm_comment_t *comment, void *data); * @param data the data to pass to the callback function for each comment. This * can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION void pm_parser_comments_each(const pm_parser_t *parser, pm_comment_callback_t callback, void *data); +PRISM_EXPORTED_FUNCTION void pm_parser_comments_each(const pm_parser_t *parser, pm_comment_callback_t callback, void *data) PRISM_NONNULL(1); /** * Returns the number of magic comments associated with the given parser. @@ -187,7 +190,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_comments_each(const pm_parser_t *parser, * @param parser the parser whose magic comments we want to get the size of * @return the number of magic comments associated with the given parser */ -PRISM_EXPORTED_FUNCTION size_t pm_parser_magic_comments_size(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION size_t pm_parser_magic_comments_size(const pm_parser_t *parser) PRISM_NONNULL(1); /** * A callback function that can be used to process magic comments found while parsing. @@ -205,7 +208,7 @@ typedef void (*pm_magic_comment_callback_t)(const pm_magic_comment_t *magic_comm * @param data the data to pass to the callback function for each magic comment. * This can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION void pm_parser_magic_comments_each(const pm_parser_t *parser, pm_magic_comment_callback_t callback, void *data); +PRISM_EXPORTED_FUNCTION void pm_parser_magic_comments_each(const pm_parser_t *parser, pm_magic_comment_callback_t callback, void *data) PRISM_NONNULL(1); /** * Returns the number of errors associated with the given parser. @@ -213,7 +216,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_magic_comments_each(const pm_parser_t *pa * @param parser the parser whose errors we want to get the size of * @return the number of errors associated with the given parser */ -PRISM_EXPORTED_FUNCTION size_t pm_parser_errors_size(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION size_t pm_parser_errors_size(const pm_parser_t *parser) PRISM_NONNULL(1); /** * Returns the number of warnings associated with the given parser. @@ -221,7 +224,7 @@ PRISM_EXPORTED_FUNCTION size_t pm_parser_errors_size(const pm_parser_t *parser); * @param parser the parser whose warnings we want to get the size of * @return the number of warnings associated with the given parser */ -PRISM_EXPORTED_FUNCTION size_t pm_parser_warnings_size(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION size_t pm_parser_warnings_size(const pm_parser_t *parser) PRISM_NONNULL(1); /** * A callback function that can be used to process diagnostics found while @@ -240,7 +243,7 @@ typedef void (*pm_diagnostic_callback_t)(const pm_diagnostic_t *diagnostic, void * @param data the data to pass to the callback function for each error. This * can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION void pm_parser_errors_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data); +PRISM_EXPORTED_FUNCTION void pm_parser_errors_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data) PRISM_NONNULL(1); /** * Iterates over the warnings associated with the given parser and calls the @@ -253,7 +256,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_errors_each(const pm_parser_t *parser, pm * @param data the data to pass to the callback function for each warning. This * can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION void pm_parser_warnings_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data); +PRISM_EXPORTED_FUNCTION void pm_parser_warnings_each(const pm_parser_t *parser, pm_diagnostic_callback_t callback, void *data) PRISM_NONNULL(1); /** * Returns the number of constants in the constant pool associated with the @@ -264,7 +267,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_warnings_each(const pm_parser_t *parser, * @return the number of constants in the constant pool associated with the * given parser */ -PRISM_EXPORTED_FUNCTION size_t pm_parser_constants_size(const pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION size_t pm_parser_constants_size(const pm_parser_t *parser) PRISM_NONNULL(1); /** * A callback function that can be used to process constants found while @@ -283,7 +286,7 @@ typedef void (*pm_constant_callback_t)(const pm_constant_t *constant, void *data * @param data the data to pass to the callback function for each constant. This * can be NULL if no data needs to be passed to the callback function. */ -PRISM_EXPORTED_FUNCTION void pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callback, void *data); +PRISM_EXPORTED_FUNCTION void pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callback, void *data) PRISM_NONNULL(1); /** * Initiate the parser with the given parser. @@ -293,6 +296,6 @@ PRISM_EXPORTED_FUNCTION void pm_parser_constants_each(const pm_parser_t *parser, * * \public \memberof pm_parser */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser); +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser) PRISM_NONNULL(1); #endif diff --git a/include/prism/prettyprint.h b/include/prism/prettyprint.h index 0c81618e7f..0d8e416341 100644 --- a/include/prism/prettyprint.h +++ b/include/prism/prettyprint.h @@ -11,6 +11,7 @@ #ifndef PRISM_EXCLUDE_PRETTYPRINT #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include "prism/ast.h" #include "prism/buffer.h" @@ -23,7 +24,7 @@ * @param parser The parser that parsed the AST. * @param node The root node of the AST to pretty-print. */ -PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node); +PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node) PRISM_NONNULL(1, 2, 3); #endif diff --git a/include/prism/serialize.h b/include/prism/serialize.h index 775fa6fbfb..ee94801f6e 100644 --- a/include/prism/serialize.h +++ b/include/prism/serialize.h @@ -14,6 +14,7 @@ #ifndef PRISM_EXCLUDE_SERIALIZATION #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include "prism/buffer.h" #include "prism/parser.h" @@ -26,7 +27,7 @@ * @param node The node to serialize. * @param buffer The buffer to serialize to. */ -PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) PRISM_NONNULL(1, 2, 3); /** * Parse the given source to the AST and dump the AST to the given buffer. @@ -36,7 +37,7 @@ PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, * @param size The size of the source. * @param data The optional data to pass to the parser. */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); +PRISM_EXPORTED_FUNCTION void pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) PRISM_NONNULL(1, 2); /** * Parse and serialize the AST represented by the source that is read out of the @@ -48,7 +49,7 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_parse(pm_buffer_t *buffer, const uint8 * @param stream_feof The function to use to tell if the stream has hit eof. * @param data The optional data to pass to the parser. */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data); +PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) PRISM_NONNULL(1, 2); /** * Parse and serialize the comments in the given source to the given buffer. @@ -58,7 +59,7 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void * @param size The size of the source. * @param data The optional data to pass to the parser. */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); +PRISM_EXPORTED_FUNCTION void pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) PRISM_NONNULL(1, 2); /** * Lex the given source and serialize to the given buffer. @@ -68,7 +69,7 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_comments(pm_buffer_t *buffer, co * @param buffer The buffer to serialize to. * @param data The optional data to pass to the lexer. */ -PRISM_EXPORTED_FUNCTION void pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); +PRISM_EXPORTED_FUNCTION void pm_serialize_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) PRISM_NONNULL(1, 2); /** * Parse and serialize both the AST and the tokens represented by the given @@ -79,7 +80,7 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_lex(pm_buffer_t *buffer, const uint8_t * @param size The size of the source. * @param data The optional data to pass to the parser. */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data); +PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) PRISM_NONNULL(1, 2); /** * Parse the source and return true if it parses without errors or warnings. @@ -89,7 +90,7 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const u * @param data The optional data to pass to the parser. * @return True if the source parses without errors or warnings. */ -PRISM_EXPORTED_FUNCTION bool pm_serialize_parse_success_p(const uint8_t *source, size_t size, const char *data); +PRISM_EXPORTED_FUNCTION bool pm_serialize_parse_success_p(const uint8_t *source, size_t size, const char *data) PRISM_NONNULL(1); #endif diff --git a/include/prism/stream.h b/include/prism/stream.h index 9ed94f58e9..47325d667d 100644 --- a/include/prism/stream.h +++ b/include/prism/stream.h @@ -7,6 +7,7 @@ #define PRISM_STREAM_H #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include "prism/arena.h" #include "prism/buffer.h" @@ -39,6 +40,6 @@ typedef int (pm_parse_stream_feof_t)(void *stream); * @param options The optional options to use when parsing. * @return The AST representing the source. */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options); +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) PRISM_NONNULL(1, 2, 3); #endif diff --git a/include/prism/string_query.h b/include/prism/string_query.h index 55c6c82697..406aa952a9 100644 --- a/include/prism/string_query.h +++ b/include/prism/string_query.h @@ -8,6 +8,7 @@ #define PRISM_STRING_QUERY_H #include "prism/compiler/exported.h" +#include "prism/compiler/nonnull.h" #include #include @@ -35,7 +36,7 @@ typedef enum { * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. */ -PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name); +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) PRISM_NONNULL(1, 3); /** * Check that the slice is a valid constant name. @@ -46,7 +47,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *s * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. */ -PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name); +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) PRISM_NONNULL(1, 3); /** * Check that the slice is a valid method name. @@ -57,6 +58,6 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. */ -PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name); +PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) PRISM_NONNULL(1, 3); #endif diff --git a/include/prism/strings.h b/include/prism/strings.h index e4de068abc..48d3f9b0d9 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -8,6 +8,7 @@ #include "prism/compiler/exported.h" #include "prism/compiler/filesystem.h" +#include "prism/compiler/nonnull.h" #include #include @@ -55,7 +56,7 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_sizeof(void); * @param source The source of the string. * @param length The length of the string. */ -PRISM_EXPORTED_FUNCTION void pm_string_constant_init(pm_string_t *string, const char *source, size_t length); +PRISM_EXPORTED_FUNCTION void pm_string_constant_init(pm_string_t *string, const char *source, size_t length) PRISM_NONNULL(1); /** * Represents the result of calling pm_string_mapped_init or @@ -96,7 +97,7 @@ typedef enum { * * \public \memberof pm_string_t */ -PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath); +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath) PRISM_NONNULL(1, 2); /** * Read the file indicated by the filepath parameter into source and load its @@ -109,7 +110,7 @@ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_ * * \public \memberof pm_string_t */ -PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath); +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath) PRISM_NONNULL(1, 2); /** * Returns the length associated with the string. @@ -119,7 +120,7 @@ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t * * \public \memberof pm_string_t */ -PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string); +PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string) PRISM_NONNULL(1); /** * Returns the start pointer associated with the string. @@ -129,7 +130,7 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string); * * \public \memberof pm_string_t */ -PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string); +PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string) PRISM_NONNULL(1); /** * Free the associated memory of the given string. @@ -138,6 +139,6 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *stri * * \public \memberof pm_string_t */ -PRISM_EXPORTED_FUNCTION void pm_string_cleanup(pm_string_t *string); +PRISM_EXPORTED_FUNCTION void pm_string_cleanup(pm_string_t *string) PRISM_NONNULL(1); #endif diff --git a/templates/src/node.c.erb b/templates/src/node.c.erb index 7b95200632..f51aff6e53 100644 --- a/templates/src/node.c.erb +++ b/templates/src/node.c.erb @@ -79,7 +79,7 @@ pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *oth * Returns a string representation of the given node type. */ const char * -pm_node_type_to_str(pm_node_type_t node_type) +pm_node_type(pm_node_type_t node_type) { switch (node_type) { <%- nodes.each do |node| -%> From 94d16c61cf60535737edd35fecc1f63d20326ff6 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 14:53:09 -0400 Subject: [PATCH 228/289] Clean up documentation --- Doxyfile | 4 +- include/prism/arena.h | 2 +- include/prism/buffer.h | 8 - include/prism/comments.h | 4 +- include/prism/constant_pool.h | 8 +- include/prism/diagnostic.h | 8 - include/prism/internal/allocator.h | 41 +- include/prism/internal/allocator_debug.h | 5 - include/prism/internal/arena.h | 58 +-- include/prism/internal/bit.h | 7 +- include/prism/internal/buffer.h | 148 ++----- include/prism/internal/char.h | 135 +----- include/prism/internal/comments.h | 13 +- include/prism/internal/constant_pool.h | 132 ++---- include/prism/internal/encoding.h | 83 ++-- include/prism/internal/integer.h | 43 +- include/prism/internal/isinf.h | 9 +- include/prism/internal/line_offset_list.h | 50 +-- include/prism/internal/list.h | 31 +- include/prism/internal/magic_comments.h | 13 +- include/prism/internal/memchr.h | 15 +- include/prism/internal/node.h | 33 +- include/prism/internal/options.h | 76 ++-- include/prism/internal/parser.h | 389 +++++++++--------- include/prism/internal/regexp.h | 38 +- include/prism/internal/serialize.h | 19 +- include/prism/internal/static_literals.h | 58 +-- include/prism/internal/strings.h | 29 +- include/prism/internal/strncasecmp.h | 13 +- include/prism/internal/strpbrk.h | 16 +- include/prism/internal/tokens.h | 8 +- include/prism/line_offset_list.h | 2 +- include/prism/magic_comments.h | 12 +- include/prism/node.h | 2 +- include/prism/options.h | 67 +-- include/prism/parser.h | 42 +- include/prism/serialize.h | 2 +- include/prism/stream.h | 2 +- include/prism/string_query.h | 6 +- include/prism/strings.h | 20 +- templates/include/prism/ast.h.erb | 4 +- .../include/prism/internal/diagnostic.h.erb | 36 +- templates/template.rb | 2 +- 43 files changed, 481 insertions(+), 1212 deletions(-) diff --git a/Doxyfile b/Doxyfile index 00bb3537ab..adfd78c431 100644 --- a/Doxyfile +++ b/Doxyfile @@ -23,8 +23,8 @@ PROJECT_NAME = "Prism Ruby parser" OUTPUT_DIRECTORY = doc JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES -INPUT = src include include/prism -EXCLUDE = include/prism/internal/allocator_debug.h +INPUT = include/prism.h include/prism +EXCLUDE = include/prism/internal HTML_OUTPUT = c SORT_MEMBER_DOCS = NO GENERATE_LATEX = NO diff --git a/include/prism/arena.h b/include/prism/arena.h index 890c98a7b4..a637e9cef3 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -21,7 +21,7 @@ typedef struct pm_arena_t pm_arena_t; * Returns a newly allocated and initialized arena. If the arena cannot be * allocated, this function aborts the process. * - * @return A pointer to the newly allocated arena. It is the responsibility of + * @returns A pointer to the newly allocated arena. It is the responsibility of * the caller to free the arena using pm_arena_free when it is no longer * needed. */ diff --git a/include/prism/buffer.h b/include/prism/buffer.h index 0d67633ede..12844d60ff 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -23,8 +23,6 @@ typedef struct pm_buffer_t pm_buffer_t; * * @returns A pointer to the initialized buffer. The caller is responsible for * freeing the buffer with pm_buffer_free. - * - * \public \memberof pm_buffer_t */ PRISM_EXPORTED_FUNCTION pm_buffer_t * pm_buffer_new(void) PRISM_NODISCARD; @@ -32,8 +30,6 @@ PRISM_EXPORTED_FUNCTION pm_buffer_t * pm_buffer_new(void) PRISM_NODISCARD; * Free both the memory held by the buffer and the buffer itself. * * @param buffer The buffer to free. - * - * \public \memberof pm_buffer_t */ PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer) PRISM_NONNULL(1); @@ -42,8 +38,6 @@ PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer) PRISM_NONNULL(1 * * @param buffer The buffer to get the value of. * @returns The value of the buffer. - * - * \public \memberof pm_buffer_t */ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer) PRISM_NONNULL(1); @@ -52,8 +46,6 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer) PRISM_ * * @param buffer The buffer to get the length of. * @returns The length of the buffer. - * - * \public \memberof pm_buffer_t */ PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer) PRISM_NONNULL(1); diff --git a/include/prism/comments.h b/include/prism/comments.h index 3e2dfcddfd..5938f388cd 100644 --- a/include/prism/comments.h +++ b/include/prism/comments.h @@ -25,7 +25,7 @@ typedef struct pm_comment_t pm_comment_t; * Returns the location associated with the given comment. * * @param comment the comment whose location we want to get - * @return the location associated with the given comment + * @returns the location associated with the given comment */ PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *comment) PRISM_NONNULL(1); @@ -33,7 +33,7 @@ PRISM_EXPORTED_FUNCTION pm_location_t pm_comment_location(const pm_comment_t *co * Returns the type associated with the given comment. * * @param comment the comment whose type we want to get - * @return the type associated with the given comment. This can either be + * @returns the type associated with the given comment. This can either be * PM_COMMENT_INLINE or PM_COMMENT_EMBDOC. */ PRISM_EXPORTED_FUNCTION pm_comment_type_t pm_comment_type(const pm_comment_t *comment) PRISM_NONNULL(1); diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index 7fea4fad94..7868c584a7 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -39,14 +39,16 @@ typedef struct { /** A constant in the pool which effectively stores a string. */ typedef struct pm_constant_t pm_constant_t; -/** The overall constant pool, which stores constants found while parsing. */ +/** + * The overall constant pool, which stores constants found while parsing. + */ typedef struct pm_constant_pool_t pm_constant_pool_t; /** * Return a raw pointer to the start of a constant. * * @param constant The constant to get the start of. - * @return A raw pointer to the start of the constant. + * @returns A raw pointer to the start of the constant. */ PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *constant) PRISM_NONNULL(1); @@ -54,7 +56,7 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *c * Return the length of a constant. * * @param constant The constant to get the length of. - * @return The length of the constant. + * @returns The length of the constant. */ PRISM_EXPORTED_FUNCTION size_t pm_constant_length(const pm_constant_t *constant) PRISM_NONNULL(1); diff --git a/include/prism/diagnostic.h b/include/prism/diagnostic.h index f2b541024f..370061ec56 100644 --- a/include/prism/diagnostic.h +++ b/include/prism/diagnostic.h @@ -1,11 +1,3 @@ -/*----------------------------------------------------------------------------*/ -/* This file is generated by the templates/template.rb script and should not */ -/* be modified manually. See */ -/* templates/include/prism/diagnostic.h.erb */ -/* if you are looking to modify the */ -/* template */ -/*----------------------------------------------------------------------------*/ - /** * @file diagnostic.h * diff --git a/include/prism/internal/allocator.h b/include/prism/internal/allocator.h index bd46257e44..6c54010dbf 100644 --- a/include/prism/internal/allocator.h +++ b/include/prism/internal/allocator.h @@ -1,13 +1,7 @@ -/** - * @file internal/allocator.h - * - * Macro definitions for defining the main and a custom allocator for Prism. - */ #ifndef PRISM_INTERNAL_ALLOCATOR_H #define PRISM_INTERNAL_ALLOCATOR_H -/** - * If you build Prism with a custom allocator, configure it with +/* If you build Prism with a custom allocator, configure it with * "-D PRISM_XALLOCATOR" to use your own allocator that defines xmalloc, * xrealloc, xcalloc, and xfree. * @@ -29,52 +23,41 @@ #include "prism_xallocator.h" #else #ifndef xmalloc - /** - * The malloc function that should be used. This can be overridden with - * the PRISM_XALLOCATOR define. - */ + /* The malloc function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. */ #define xmalloc malloc #endif #ifndef xrealloc - /** - * The realloc function that should be used. This can be overridden with - * the PRISM_XALLOCATOR define. - */ + /* The realloc function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. */ #define xrealloc realloc #endif #ifndef xcalloc - /** - * The calloc function that should be used. This can be overridden with - * the PRISM_XALLOCATOR define. - */ + /* The calloc function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. */ #define xcalloc calloc #endif #ifndef xfree - /** - * The free function that should be used. This can be overridden with - * the PRISM_XALLOCATOR define. - */ + /* The free function that should be used. This can be overridden with + * the PRISM_XALLOCATOR define. */ #define xfree free #endif #endif #ifndef xfree_sized - /** - * The free_sized function that should be used. This can be overridden with + /* The free_sized function that should be used. This can be overridden with * the PRISM_XALLOCATOR define. If not defined, defaults to calling xfree. */ #define xfree_sized(p, s) xfree(((void)(s), (p))) #endif #ifndef xrealloc_sized - /** - * The xrealloc_sized function that should be used. This can be overridden + /* The xrealloc_sized function that should be used. This can be overridden * with the PRISM_XALLOCATOR define. If not defined, defaults to calling - * xrealloc. - */ + * xrealloc. */ #define xrealloc_sized(p, ns, os) xrealloc((p), ((void)(os), (ns))) #endif diff --git a/include/prism/internal/allocator_debug.h b/include/prism/internal/allocator_debug.h index 40f2a7b4cf..846e96ba2d 100644 --- a/include/prism/internal/allocator_debug.h +++ b/include/prism/internal/allocator_debug.h @@ -1,8 +1,3 @@ -/** - * @file internal/allocator_debug.h - * - * Decorate allocation function to ensure sizes are correct. - */ #ifndef PRISM_INTERNAL_ALLOCATOR_DEBUG_H #define PRISM_INTERNAL_ALLOCATOR_DEBUG_H diff --git a/include/prism/internal/arena.h b/include/prism/internal/arena.h index 54bbead6bd..2e413b42bf 100644 --- a/include/prism/internal/arena.h +++ b/include/prism/internal/arena.h @@ -1,8 +1,3 @@ -/** - * @file internal/arena.h - * - * A bump allocator for the prism parser. - */ #ifndef PRISM_INTERNAL_ARENA_H #define PRISM_INTERNAL_ARENA_H @@ -16,76 +11,62 @@ #include #include -/** +/* * A single block of memory in the arena. Blocks are linked via prev pointers so * they can be freed by walking the chain. */ typedef struct pm_arena_block { - /** The previous block in the chain (for freeing). */ + /* The previous block in the chain (for freeing). */ struct pm_arena_block *prev; - /** The total usable bytes in data[]. */ + /* The total usable bytes in data[]. */ size_t capacity; - /** The number of bytes consumed so far. */ + /* The number of bytes consumed so far. */ size_t used; - /** The block's data. */ + /* The block's data. */ char data[PM_FLEX_ARRAY_LENGTH]; } pm_arena_block_t; -/** +/* * A bump allocator. Allocations are made by bumping a pointer within the * current block. When a block is full, a new block is allocated and linked to * the previous one. All blocks are freed at once by walking the chain. */ struct pm_arena_t { - /** The active block (allocate from here). */ + /* The active block (allocate from here). */ pm_arena_block_t *current; - /** The number of blocks allocated. */ + /* The number of blocks allocated. */ size_t block_count; }; -/** +/* * Free all blocks in the arena. After this call, all pointers returned by * pm_arena_alloc and pm_arena_zalloc are invalid. - * - * @param arena The arena whose held memory should be freed. */ void pm_arena_cleanup(pm_arena_t *arena); -/** +/* * Ensure the arena has at least `capacity` bytes available in its current * block, allocating a new block if necessary. This allows callers to * pre-size the arena to avoid repeated small block allocations. - * - * @param arena The arena to pre-size. - * @param capacity The minimum number of bytes to ensure are available. */ void pm_arena_reserve(pm_arena_t *arena, size_t capacity); -/** +/* * Slow path for pm_arena_alloc: allocate a new block and return a pointer to * the first `size` bytes. Do not call directly — use pm_arena_alloc instead. - * - * @param arena The arena to allocate from. - * @param size The number of bytes to allocate. - * @returns A pointer to the allocated memory. */ void * pm_arena_alloc_slow(pm_arena_t *arena, size_t size); -/** +/* * Allocate memory from the arena. The returned memory is NOT zeroed. This * function is infallible — it aborts on allocation failure. * * The fast path (bump pointer within the current block) is inlined at each * call site. The slow path (new block allocation) is out-of-line. - * - * @param arena The arena to allocate from. - * @param size The number of bytes to allocate. - * @param alignment The required alignment (must be a power of 2). - * @returns A pointer to the allocated memory. */ static PRISM_FORCE_INLINE void * pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { @@ -102,14 +83,9 @@ pm_arena_alloc(pm_arena_t *arena, size_t size, size_t alignment) { return pm_arena_alloc_slow(arena, size); } -/** +/* * Allocate zero-initialized memory from the arena. This function is infallible * — it aborts on allocation failure. - * - * @param arena The arena to allocate from. - * @param size The number of bytes to allocate. - * @param alignment The required alignment (must be a power of 2). - * @returns A pointer to the allocated, zero-initialized memory. */ static PRISM_INLINE void * pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { @@ -118,15 +94,9 @@ pm_arena_zalloc(pm_arena_t *arena, size_t size, size_t alignment) { return ptr; } -/** +/* * Allocate memory from the arena and copy the given data into it. This is a * convenience wrapper around pm_arena_alloc + memcpy. - * - * @param arena The arena to allocate from. - * @param src The source data to copy. - * @param size The number of bytes to allocate and copy. - * @param alignment The required alignment (must be a power of 2). - * @returns A pointer to the allocated copy. */ static PRISM_INLINE void * pm_arena_memdup(pm_arena_t *arena, const void *src, size_t size, size_t alignment) { diff --git a/include/prism/internal/bit.h b/include/prism/internal/bit.h index b4249825a3..4eec494887 100644 --- a/include/prism/internal/bit.h +++ b/include/prism/internal/bit.h @@ -1,14 +1,9 @@ -/** - * @file internal/bit.h - * - * Bit manipulation utilities used throughout the prism library. - */ #ifndef PRISM_INTERNAL_BIT_H #define PRISM_INTERNAL_BIT_H #include "prism/compiler/inline.h" -/** +/* * Count trailing zero bits in a 64-bit value. Used by SWAR identifier scanning * to find the first non-matching byte in a word. * diff --git a/include/prism/internal/buffer.h b/include/prism/internal/buffer.h index 8eb0c7e243..a849bbf8e6 100644 --- a/include/prism/internal/buffer.h +++ b/include/prism/internal/buffer.h @@ -1,8 +1,3 @@ -/** - * @file internal/buffer.h - * - * A wrapper around a contiguous block of allocated memory. - */ #ifndef PRISM_INTERNAL_BUFFER_H #define PRISM_INTERNAL_BUFFER_H @@ -13,113 +8,54 @@ #include #include -/** +/* * A simple memory buffer that stores data in a contiguous block of memory. */ struct pm_buffer_t { - /** The length of the buffer in bytes. */ + /* The length of the buffer in bytes. */ size_t length; - /** The capacity of the buffer in bytes that has been allocated. */ + /* The capacity of the buffer in bytes that has been allocated. */ size_t capacity; - /** A pointer to the start of the buffer. */ + /* A pointer to the start of the buffer. */ char *value; }; -/** - * Initialize a pm_buffer_t with the given capacity. - * - * @param buffer The buffer to initialize. - * @param capacity The capacity of the buffer. - */ +/* Initialize a pm_buffer_t with the given capacity. */ void pm_buffer_init(pm_buffer_t *buffer, size_t capacity); -/** - * Free the memory held by the buffer. - * - * @param buffer The buffer whose held memory should be freed. - */ +/* Free the memory held by the buffer. */ void pm_buffer_cleanup(pm_buffer_t *buffer); -/** - * Append the given amount of space as zeroes to the buffer. - * - * @param buffer The buffer to append to. - * @param length The amount of space to append and zero. - */ +/* Append the given amount of space as zeroes to the buffer. */ void pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length); -/** - * Append a formatted string to the buffer. - * - * @param buffer The buffer to append to. - * @param format The format string to append. - * @param ... The arguments to the format string. - */ +/* Append a formatted string to the buffer. */ void pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...) PRISM_ATTRIBUTE_FORMAT(2, 3); -/** - * Append a string to the buffer. - * - * @param buffer The buffer to append to. - * @param value The string to append. - * @param length The length of the string to append. - */ +/* Append a string to the buffer. */ void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length); -/** - * Append a list of bytes to the buffer. - * - * @param buffer The buffer to append to. - * @param value The bytes to append. - * @param length The length of the bytes to append. - */ +/* Append a list of bytes to the buffer. */ void pm_buffer_append_bytes(pm_buffer_t *buffer, const uint8_t *value, size_t length); -/** - * Append a single byte to the buffer. - * - * @param buffer The buffer to append to. - * @param value The byte to append. - */ +/* Append a single byte to the buffer. */ void pm_buffer_append_byte(pm_buffer_t *buffer, uint8_t value); -/** - * Append a 32-bit unsigned integer to the buffer as a variable-length integer. - * - * @param buffer The buffer to append to. - * @param value The integer to append. - */ +/* Append a 32-bit unsigned integer to the buffer as a variable-length integer. */ void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value); -/** - * Append a 32-bit signed integer to the buffer as a variable-length integer. - * - * @param buffer The buffer to append to. - * @param value The integer to append. - */ +/* Append a 32-bit signed integer to the buffer as a variable-length integer. */ void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value); -/** - * Append a double to the buffer. - * - * @param buffer The buffer to append to. - * @param value The double to append. - */ +/* Append a double to the buffer. */ void pm_buffer_append_double(pm_buffer_t *buffer, double value); -/** - * Append a unicode codepoint to the buffer. - * - * @param buffer The buffer to append to. - * @param value The character to append. - * @returns True if the codepoint was valid and appended successfully, false - * otherwise. - */ +/* Append a unicode codepoint to the buffer. */ bool pm_buffer_append_unicode_codepoint(pm_buffer_t *buffer, uint32_t value); -/** +/* * The different types of escaping that can be performed by the buffer when * appending a slice of Ruby source code. */ @@ -128,66 +64,28 @@ typedef enum { PM_BUFFER_ESCAPING_JSON } pm_buffer_escaping_t; -/** - * Append a slice of source code to the buffer. - * - * @param buffer The buffer to append to. - * @param source The source code to append. - * @param length The length of the source code to append. - * @param escaping The type of escaping to perform. - */ +/* Append a slice of source code to the buffer. */ void pm_buffer_append_source(pm_buffer_t *buffer, const uint8_t *source, size_t length, pm_buffer_escaping_t escaping); -/** - * Prepend the given string to the buffer. - * - * @param buffer The buffer to prepend to. - * @param value The string to prepend. - * @param length The length of the string to prepend. - */ +/* Prepend the given string to the buffer. */ void pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t length); -/** - * Concatenate one buffer onto another. - * - * @param destination The buffer to concatenate onto. - * @param source The buffer to concatenate. - */ +/* Concatenate one buffer onto another. */ void pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source); -/** +/* * Clear the buffer by reducing its size to 0. This does not free the allocated * memory, but it does allow the buffer to be reused. - * - * @param buffer The buffer to clear. */ void pm_buffer_clear(pm_buffer_t *buffer); -/** - * Strip the whitespace from the end of the buffer. - * - * @param buffer The buffer to strip. - */ +/* Strip the whitespace from the end of the buffer. */ void pm_buffer_rstrip(pm_buffer_t *buffer); -/** - * Checks if the buffer includes the given value. - * - * @param buffer The buffer to check. - * @param value The value to check for. - * @returns The index of the first occurrence of the value in the buffer, or - * SIZE_MAX if the value is not found. - */ +/* Checks if the buffer includes the given value. */ size_t pm_buffer_index(const pm_buffer_t *buffer, char value); -/** - * Insert the given string into the buffer at the given index. - * - * @param buffer The buffer to insert into. - * @param index The index to insert at. - * @param value The string to insert. - * @param length The length of the string to insert. - */ +/* Insert the given string into the buffer at the given index. */ void pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t length); #endif diff --git a/include/prism/internal/char.h b/include/prism/internal/char.h index 8216a1828c..9a58fba8c5 100644 --- a/include/prism/internal/char.h +++ b/include/prism/internal/char.h @@ -1,8 +1,3 @@ -/** - * @file internal/char.h - * - * Functions for working with characters and strings. - */ #ifndef PRISM_INTERNAL_CHAR_H #define PRISM_INTERNAL_CHAR_H @@ -15,48 +10,33 @@ #include #include -/** Bit flag for whitespace characters in pm_byte_table. */ +/* Bit flag for whitespace characters in pm_byte_table. */ #define PRISM_CHAR_BIT_WHITESPACE (1 << 0) -/** Bit flag for inline whitespace characters in pm_byte_table. */ +/* Bit flag for inline whitespace characters in pm_byte_table. */ #define PRISM_CHAR_BIT_INLINE_WHITESPACE (1 << 1) -/** +/* * A lookup table for classifying bytes. Each entry is a bitfield of * PRISM_CHAR_BIT_* flags. Defined in char.c. */ extern const uint8_t pm_byte_table[256]; -/** - * Returns true if the given character is a whitespace character. - * - * @param b The character to check. - * @return True if the given character is a whitespace character. - */ +/* Returns true if the given character is a whitespace character. */ static PRISM_FORCE_INLINE bool pm_char_is_whitespace(const uint8_t b) { return (pm_byte_table[b] & PRISM_CHAR_BIT_WHITESPACE) != 0; } -/** - * Returns true if the given character is an inline whitespace character. - * - * @param b The character to check. - * @return True if the given character is an inline whitespace character. - */ +/* Returns true if the given character is an inline whitespace character. */ static PRISM_FORCE_INLINE bool pm_char_is_inline_whitespace(const uint8_t b) { return (pm_byte_table[b] & PRISM_CHAR_BIT_INLINE_WHITESPACE) != 0; } -/** +/* * Returns the number of characters at the start of the string that are inline * whitespace (space/tab). Scans the byte table directly for use in hot paths. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @return The number of characters at the start of the string that are inline - * whitespace. */ static PRISM_FORCE_INLINE size_t pm_strspn_inline_whitespace(const uint8_t *string, ptrdiff_t length) { @@ -67,57 +47,33 @@ pm_strspn_inline_whitespace(const uint8_t *string, ptrdiff_t length) { return size; } -/** +/* * Returns the number of characters at the start of the string that are * whitespace. Disallows searching past the given maximum number of characters. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @return The number of characters at the start of the string that are - * whitespace. */ size_t pm_strspn_whitespace(const uint8_t *string, ptrdiff_t length); -/** +/* * Returns the number of characters at the start of the string that are * whitespace while also tracking the location of each newline. Disallows * searching past the given maximum number of characters. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @param arena The arena to allocate from when appending to line_offsets. - * @param line_offsets The list of newlines to populate. - * @param start_offset The offset at which the string occurs in the source, for - * the purpose of tracking newlines. - * @return The number of characters at the start of the string that are - * whitespace. */ size_t pm_strspn_whitespace_newlines(const uint8_t *string, ptrdiff_t length, pm_arena_t *arena, pm_line_offset_list_t *line_offsets, uint32_t start_offset); -/** +/* * Returns the number of characters at the start of the string that are decimal * digits. Disallows searching past the given maximum number of characters. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @return The number of characters at the start of the string that are decimal - * digits. */ size_t pm_strspn_decimal_digit(const uint8_t *string, ptrdiff_t length); -/** +/* * Returns the number of characters at the start of the string that are * hexadecimal digits. Disallows searching past the given maximum number of * characters. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @return The number of characters at the start of the string that are - * hexadecimal digits. */ size_t pm_strspn_hexadecimal_digit(const uint8_t *string, ptrdiff_t length); -/** +/* * Returns the number of characters at the start of the string that are octal * digits or underscores. Disallows searching past the given maximum number of * characters. @@ -125,17 +81,10 @@ size_t pm_strspn_hexadecimal_digit(const uint8_t *string, ptrdiff_t length); * If multiple underscores are found in a row or if an underscore is * found at the end of the number, then the invalid pointer is set to the index * of the first invalid underscore. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @param invalid The pointer to set to the index of the first invalid - * underscore. - * @return The number of characters at the start of the string that are octal - * digits or underscores. */ size_t pm_strspn_octal_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid); -/** +/* * Returns the number of characters at the start of the string that are decimal * digits or underscores. Disallows searching past the given maximum number of * characters. @@ -143,17 +92,10 @@ size_t pm_strspn_octal_number(const uint8_t *string, ptrdiff_t length, const uin * If multiple underscores are found in a row or if an underscore is * found at the end of the number, then the invalid pointer is set to the index * of the first invalid underscore. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @param invalid The pointer to set to the index of the first invalid - * underscore. - * @return The number of characters at the start of the string that are decimal - * digits or underscores. */ size_t pm_strspn_decimal_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid); -/** +/* * Returns the number of characters at the start of the string that are * hexadecimal digits or underscores. Disallows searching past the given maximum * number of characters. @@ -161,28 +103,16 @@ size_t pm_strspn_decimal_number(const uint8_t *string, ptrdiff_t length, const u * If multiple underscores are found in a row or if an underscore is * found at the end of the number, then the invalid pointer is set to the index * of the first invalid underscore. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @param invalid The pointer to set to the index of the first invalid - * underscore. - * @return The number of characters at the start of the string that are - * hexadecimal digits or underscores. */ size_t pm_strspn_hexadecimal_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid); -/** +/* * Returns the number of characters at the start of the string that are regexp * options. Disallows searching past the given maximum number of characters. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @return The number of characters at the start of the string that are regexp - * options. */ size_t pm_strspn_regexp_option(const uint8_t *string, ptrdiff_t length); -/** +/* * Returns the number of characters at the start of the string that are binary * digits or underscores. Disallows searching past the given maximum number of * characters. @@ -190,47 +120,20 @@ size_t pm_strspn_regexp_option(const uint8_t *string, ptrdiff_t length); * If multiple underscores are found in a row or if an underscore is * found at the end of the number, then the invalid pointer is set to the index * of the first invalid underscore. - * - * @param string The string to search. - * @param length The maximum number of characters to search. - * @param invalid The pointer to set to the index of the first invalid - * underscore. - * @return The number of characters at the start of the string that are binary - * digits or underscores. */ size_t pm_strspn_binary_number(const uint8_t *string, ptrdiff_t length, const uint8_t **invalid); -/** - * Returns true if the given character is a binary digit. - * - * @param b The character to check. - * @return True if the given character is a binary digit. - */ +/* Returns true if the given character is a binary digit. */ bool pm_char_is_binary_digit(const uint8_t b); -/** - * Returns true if the given character is an octal digit. - * - * @param b The character to check. - * @return True if the given character is an octal digit. - */ +/* Returns true if the given character is an octal digit. */ bool pm_char_is_octal_digit(const uint8_t b); -/** - * Returns true if the given character is a decimal digit. - * - * @param b The character to check. - * @return True if the given character is a decimal digit. - */ +/* Returns true if the given character is a decimal digit. */ bool pm_char_is_decimal_digit(const uint8_t b); -/** - * Returns true if the given character is a hexadecimal digit. - * - * @param b The character to check. - * @return True if the given character is a hexadecimal digit. - */ +/* Returns true if the given character is a hexadecimal digit. */ bool pm_char_is_hexadecimal_digit(const uint8_t b); #endif diff --git a/include/prism/internal/comments.h b/include/prism/internal/comments.h index e8fbb0e6aa..bb3039a658 100644 --- a/include/prism/internal/comments.h +++ b/include/prism/internal/comments.h @@ -1,6 +1,3 @@ -/** - * @file internal/comments.h - */ #ifndef PRISM_INTERNAL_COMMENTS_H #define PRISM_INTERNAL_COMMENTS_H @@ -8,17 +5,15 @@ #include "prism/internal/list.h" -/** - * A comment found while parsing. - */ +/* A comment found while parsing. */ struct pm_comment_t { - /** The embedded base node. */ + /* The embedded base node. */ pm_list_node_t node; - /** The location of the comment in the source. */ + /* The location of the comment in the source. */ pm_location_t location; - /** The type of the comment. */ + /* The type of the comment. */ pm_comment_type_t type; }; diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h index 68d7d63203..7ca265d594 100644 --- a/include/prism/internal/constant_pool.h +++ b/include/prism/internal/constant_pool.h @@ -1,12 +1,3 @@ -/** - * @file internal/constant_pool.h - * - * A data structure that stores a set of strings. - * - * Each string is assigned a unique id, which can be used to compare strings for - * equality. This comparison ends up being much faster than strcmp, since it - * only requires a single integer comparison. - */ #ifndef PRISM_INTERNAL_CONSTANT_POOL_H #define PRISM_INTERNAL_CONSTANT_POOL_H @@ -16,179 +7,116 @@ #include -/** A constant in the pool which effectively stores a string. */ +/* A constant in the pool which effectively stores a string. */ struct pm_constant_t { - /** A pointer to the start of the string. */ + /* A pointer to the start of the string. */ const uint8_t *start; - /** The length of the string. */ + /* The length of the string. */ size_t length; }; -/** +/* * The type of bucket in the constant pool hash map. This determines how the * bucket should be freed. */ typedef unsigned int pm_constant_pool_bucket_type_t; -/** By default, each constant is a slice of the source. */ +/* By default, each constant is a slice of the source. */ static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_DEFAULT = 0; -/** An owned constant is one for which memory has been allocated. */ +/* An owned constant is one for which memory has been allocated. */ static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_OWNED = 1; -/** A constant constant is known at compile time. */ +/* A constant constant is known at compile time. */ static const pm_constant_pool_bucket_type_t PM_CONSTANT_POOL_BUCKET_CONSTANT = 2; -/** A bucket in the hash map. */ +/* A bucket in the hash map. */ typedef struct { - /** The incremental ID used for indexing back into the pool. */ + /* The incremental ID used for indexing back into the pool. */ unsigned int id: 30; - /** The type of the bucket, which determines how to free it. */ + /* The type of the bucket, which determines how to free it. */ pm_constant_pool_bucket_type_t type: 2; - /** The hash of the bucket. */ + /* The hash of the bucket. */ uint32_t hash; - /** + /* * A pointer to the start of the string, stored directly in the bucket to * avoid a pointer chase to the constants array during probing. */ const uint8_t *start; - /** The length of the string. */ + /* The length of the string. */ size_t length; } pm_constant_pool_bucket_t; -/** The overall constant pool, which stores constants found while parsing. */ +/* The overall constant pool, which stores constants found while parsing. */ struct pm_constant_pool_t { - /** The buckets in the hash map. */ + /* The buckets in the hash map. */ pm_constant_pool_bucket_t *buckets; - /** The constants that are stored in the buckets. */ + /* The constants that are stored in the buckets. */ pm_constant_t *constants; - /** The number of buckets in the hash map. */ + /* The number of buckets in the hash map. */ uint32_t size; - /** The number of buckets that have been allocated in the hash map. */ + /* The number of buckets that have been allocated in the hash map. */ uint32_t capacity; }; -/** +/* * When we allocate constants into the pool, we reserve 0 to mean that the slot * is not yet filled. This constant is reused in other places to indicate the * lack of a constant id. */ #define PM_CONSTANT_ID_UNSET 0 -/** - * Initialize a list of constant ids. - * - * @param list The list to initialize. - */ +/* Initialize a list of constant ids. */ void pm_constant_id_list_init(pm_constant_id_list_t *list); -/** - * Initialize a list of constant ids with a given capacity. - * - * @param arena The arena to allocate from. - * @param list The list to initialize. - * @param capacity The initial capacity of the list. - */ +/* Initialize a list of constant ids with a given capacity. */ void pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity); -/** - * Append a constant id to a list of constant ids. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param id The id to append. - */ +/* Append a constant id to a list of constant ids. */ void pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id); -/** - * Insert a constant id into a list of constant ids at the specified index. - * - * @param list The list to insert into. - * @param index The index at which to insert. - * @param id The id to insert. - */ +/* Insert a constant id into a list of constant ids at the specified index. */ void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_constant_id_t id); -/** - * Checks if the current constant id list includes the given constant id. - * - * @param list The list to check. - * @param id The id to check for. - * @return Whether the list includes the given id. - */ +/* Checks if the current constant id list includes the given constant id. */ bool pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id); -/** - * Initialize a new constant pool with a given capacity. - * - * @param arena The arena to allocate from. - * @param pool The pool to initialize. - * @param capacity The initial capacity of the pool. - */ +/* Initialize a new constant pool with a given capacity. */ void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t capacity); -/** - * Return a pointer to the constant indicated by the given constant id. - * - * @param pool The pool to get the constant from. - * @param constant_id The id of the constant to get. - * @return A pointer to the constant. - */ +/* Return a pointer to the constant indicated by the given constant id. */ pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id); -/** +/* * Find a constant in a constant pool. Returns the id of the constant, or 0 if * the constant is not found. - * - * @param pool The pool to find the constant in. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. */ pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length); -/** +/* * Insert a constant into a constant pool that is a slice of a source string. * Returns the id of the constant, or 0 if any potential calls to resize fail. - * - * @param arena The arena to allocate from. - * @param pool The pool to insert the constant into. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. */ pm_constant_id_t pm_constant_pool_insert_shared(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); -/** +/* * Insert a constant into a constant pool from memory that is now owned by the * constant pool. Returns the id of the constant, or 0 if any potential calls to * resize fail. - * - * @param arena The arena to allocate from. - * @param pool The pool to insert the constant into. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. */ pm_constant_id_t pm_constant_pool_insert_owned(pm_arena_t *arena, pm_constant_pool_t *pool, uint8_t *start, size_t length); -/** +/* * Insert a constant into a constant pool from memory that is constant. Returns * the id of the constant, or 0 if any potential calls to resize fail. - * - * @param arena The arena to allocate from. - * @param pool The pool to insert the constant into. - * @param start A pointer to the start of the constant. - * @param length The length of the constant. - * @return The id of the constant. */ pm_constant_id_t pm_constant_pool_insert_constant(pm_arena_t *arena, pm_constant_pool_t *pool, const uint8_t *start, size_t length); diff --git a/include/prism/internal/encoding.h b/include/prism/internal/encoding.h index 409345fd7f..62392ef970 100644 --- a/include/prism/internal/encoding.h +++ b/include/prism/internal/encoding.h @@ -1,8 +1,3 @@ -/** - * @file internal/encoding.h - * - * The encoding interface and implementations used by the parser. - */ #ifndef PRISM_INTERNAL_ENCODING_H #define PRISM_INTERNAL_ENCODING_H @@ -10,115 +5,91 @@ #include #include -/** +/* * This struct defines the functions necessary to implement the encoding * interface so we can determine how many bytes the subsequent character takes. * Each callback should return the number of bytes, or 0 if the next bytes are * invalid for the encoding and type. */ typedef struct { - /** + /* * Return the number of bytes that the next character takes if it is valid * in the encoding. Does not read more than n bytes. It is assumed that n is * at least 1. */ size_t (*char_width)(const uint8_t *b, ptrdiff_t n); - /** + /* * Return the number of bytes that the next character takes if it is valid * in the encoding and is alphabetical. Does not read more than n bytes. It * is assumed that n is at least 1. */ size_t (*alpha_char)(const uint8_t *b, ptrdiff_t n); - /** + /* * Return the number of bytes that the next character takes if it is valid * in the encoding and is alphanumeric. Does not read more than n bytes. It * is assumed that n is at least 1. */ size_t (*alnum_char)(const uint8_t *b, ptrdiff_t n); - /** + /* * Return true if the next character is valid in the encoding and is an * uppercase character. Does not read more than n bytes. It is assumed that * n is at least 1. */ bool (*isupper_char)(const uint8_t *b, ptrdiff_t n); - /** + /* * The name of the encoding. This should correspond to a value that can be * passed to Encoding.find in Ruby. */ const char *name; - /** - * Return true if the encoding is a multibyte encoding. - */ + /* Return true if the encoding is a multibyte encoding. */ bool multibyte; } pm_encoding_t; -/** +/* * All of the lookup tables use the first bit of each embedded byte to indicate * whether the codepoint is alphabetical. */ #define PRISM_ENCODING_ALPHABETIC_BIT 1 << 0 -/** +/* * All of the lookup tables use the second bit of each embedded byte to indicate * whether the codepoint is alphanumeric. */ #define PRISM_ENCODING_ALPHANUMERIC_BIT 1 << 1 -/** +/* * All of the lookup tables use the third bit of each embedded byte to indicate * whether the codepoint is uppercase. */ #define PRISM_ENCODING_UPPERCASE_BIT 1 << 2 -/** - * Return the size of the next character in the UTF-8 encoding. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns The number of bytes that the next character takes if it is valid in - * the encoding, or 0 if it is not. - */ +/* Return the size of the next character in the UTF-8 encoding. */ size_t pm_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n); -/** +/* * Return the size of the next character in the UTF-8 encoding if it is an * alphabetical character. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns The number of bytes that the next character takes if it is valid in - * the encoding, or 0 if it is not. */ size_t pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n); -/** +/* * Return the size of the next character in the UTF-8 encoding if it is an * alphanumeric character. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns The number of bytes that the next character takes if it is valid in - * the encoding, or 0 if it is not. */ size_t pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n); -/** +/* * Return true if the next character in the UTF-8 encoding if it is an uppercase * character. - * - * @param b The bytes to read. - * @param n The number of bytes that can be read. - * @returns True if the next character is valid in the encoding and is an - * uppercase character, or false if it is not. */ bool pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n); -/** +/* * This lookup table is referenced in both the UTF-8 encoding file and the * parser directly in order to speed up the default encoding processing. It is * used to indicate whether a character is alphabetical, alphanumeric, or @@ -126,9 +97,7 @@ bool pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n); */ extern const uint8_t pm_encoding_unicode_table[256]; -/** - * These are all of the encodings that prism supports. - */ +/* These are all of the encodings that prism supports. */ typedef enum { PM_ENCODING_UTF_8 = 0, PM_ENCODING_US_ASCII, @@ -229,50 +198,44 @@ typedef enum { PM_ENCODING_MAXIMUM } pm_encoding_type_t; -/** - * This is the table of all of the encodings that prism supports. - */ +/* This is the table of all of the encodings that prism supports. */ extern const pm_encoding_t pm_encodings[PM_ENCODING_MAXIMUM]; -/** +/* * This is the default UTF-8 encoding. We need a reference to it to quickly * create parsers. */ #define PM_ENCODING_UTF_8_ENTRY (&pm_encodings[PM_ENCODING_UTF_8]) -/** +/* * This is the US-ASCII encoding. We need a reference to it to be able to * compare against it when a string is being created because it could possibly * need to fall back to ASCII-8BIT. */ #define PM_ENCODING_US_ASCII_ENTRY (&pm_encodings[PM_ENCODING_US_ASCII]) -/** +/* * This is the ASCII-8BIT encoding. We need a reference to it so that pm_strpbrk * can compare against it because invalid multibyte characters are not a thing * in this encoding. It is also needed for handling Regexp encoding flags. */ #define PM_ENCODING_ASCII_8BIT_ENTRY (&pm_encodings[PM_ENCODING_ASCII_8BIT]) -/** +/* * This is the EUC-JP encoding. We need a reference to it to quickly process * regular expression modifiers. */ #define PM_ENCODING_EUC_JP_ENTRY (&pm_encodings[PM_ENCODING_EUC_JP]) -/** +/* * This is the Windows-31J encoding. We need a reference to it to quickly * process regular expression modifiers. */ #define PM_ENCODING_WINDOWS_31J_ENTRY (&pm_encodings[PM_ENCODING_WINDOWS_31J]) -/** +/* * Parse the given name of an encoding and return a pointer to the corresponding * encoding struct if one can be found, otherwise return NULL. - * - * @param start A pointer to the first byte of the name. - * @param end A pointer to the last byte of the name. - * @returns A pointer to the encoding struct if one is found, otherwise NULL. */ const pm_encoding_t * pm_encoding_find(const uint8_t *start, const uint8_t *end); diff --git a/include/prism/internal/integer.h b/include/prism/internal/integer.h index 8bf21ae69d..7c9767e323 100644 --- a/include/prism/internal/integer.h +++ b/include/prism/internal/integer.h @@ -1,6 +1,4 @@ -/** - * @file internal/integer.h - * +/* * This module provides functions for working with arbitrary-sized integers. */ #ifndef PRISM_INTERNAL_INTEGER_H @@ -11,28 +9,28 @@ #include -/** +/* * An enum controlling the base of an integer. It is expected that the base is * already known before parsing the integer, even though it could be derived * from the string itself. */ typedef enum { - /** The default decimal base, with no prefix. Leading 0s will be ignored. */ + /* The default decimal base, with no prefix. Leading 0s will be ignored. */ PM_INTEGER_BASE_DEFAULT, - /** The binary base, indicated by a 0b or 0B prefix. */ + /* The binary base, indicated by a 0b or 0B prefix. */ PM_INTEGER_BASE_BINARY, - /** The octal base, indicated by a 0, 0o, or 0O prefix. */ + /* The octal base, indicated by a 0, 0o, or 0O prefix. */ PM_INTEGER_BASE_OCTAL, - /** The decimal base, indicated by a 0d, 0D, or empty prefix. */ + /* The decimal base, indicated by a 0d, 0D, or empty prefix. */ PM_INTEGER_BASE_DECIMAL, - /** The hexadecimal base, indicated by a 0x or 0X prefix. */ + /* The hexadecimal base, indicated by a 0x or 0X prefix. */ PM_INTEGER_BASE_HEXADECIMAL, - /** + /* * An unknown base, in which case pm_integer_parse will derive it based on * the content of the string. This is less efficient and does more * comparisons, so if callers know the base ahead of time, they should use @@ -41,47 +39,30 @@ typedef enum { PM_INTEGER_BASE_UNKNOWN } pm_integer_base_t; -/** +/* * Parse an integer from a string. This assumes that the format of the integer * has already been validated, as internal validation checks are not performed * here. - * - * @param integer The integer to parse into. - * @param base The base of the integer. - * @param start The start of the string. - * @param end The end of the string. */ void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end); -/** +/* * Compare two integers. This function returns -1 if the left integer is less * than the right integer, 0 if they are equal, and 1 if the left integer is * greater than the right integer. - * - * @param left The left integer to compare. - * @param right The right integer to compare. - * @return The result of the comparison. */ int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right); -/** +/* * Reduce a ratio of integers to its simplest form. * * If either the numerator or denominator do not fit into a 32-bit integer, then * this function is a no-op. In the future, we may consider reducing even the * larger numbers, but for now we're going to keep it simple. - * - * @param numerator The numerator of the ratio. - * @param denominator The denominator of the ratio. */ void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator); -/** - * Convert an integer to a decimal string. - * - * @param buffer The buffer to append the string to. - * @param integer The integer to convert to a string. - */ +/* Convert an integer to a decimal string. */ void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer); #endif diff --git a/include/prism/internal/isinf.h b/include/prism/internal/isinf.h index 569f4726e7..41c160f56d 100644 --- a/include/prism/internal/isinf.h +++ b/include/prism/internal/isinf.h @@ -1,10 +1,7 @@ -/** - * @file isinf.h - */ -#ifndef PRISM_ISINF_H -#define PRISM_ISINF_H +#ifndef PRISM_INTERNAL_ISINF_H +#define PRISM_INTERNAL_ISINF_H -/** +/* * isinf on POSIX systems accepts a float, a double, or a long double. But mingw * didn't provide an isinf macro, only an isinf function that only accepts * floats, so we need to use _finite instead. diff --git a/include/prism/internal/line_offset_list.h b/include/prism/internal/line_offset_list.h index e18f7276e6..dac9f7052e 100644 --- a/include/prism/internal/line_offset_list.h +++ b/include/prism/internal/line_offset_list.h @@ -1,16 +1,3 @@ -/** - * @file internal/line_offset_list.h - * - * A list of byte offsets of newlines in a string. - * - * When compiling the syntax tree, it's necessary to know the line and column - * of many nodes. This is necessary to support things like error messages, - * tracepoints, etc. - * - * It's possible that we could store the start line, start column, end line, and - * end column on every node in addition to the offsets that we already store, - * but that would be quite a lot of memory overhead. - */ #ifndef PRISM_INTERNAL_LINE_OFFSET_LIST_H #define PRISM_INTERNAL_LINE_OFFSET_LIST_H @@ -19,38 +6,16 @@ #include "prism/arena.h" #include "prism/line_offset_list.h" -/** - * Initialize a new line offset list with the given capacity. - * - * @param arena The arena to allocate from. - * @param list The list to initialize. - * @param capacity The initial capacity of the list. - */ +/* Initialize a new line offset list with the given capacity. */ void pm_line_offset_list_init(pm_arena_t *arena, pm_line_offset_list_t *list, size_t capacity); -/** - * Clear out the offsets that have been appended to the list. - * - * @param list The list to clear. - */ +/* Clear out the offsets that have been appended to the list. */ void pm_line_offset_list_clear(pm_line_offset_list_t *list); -/** - * Append a new offset to the list (slow path with resize). - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param cursor The offset to append. - */ +/* Append a new offset to the list (slow path with resize). */ void pm_line_offset_list_append_slow(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor); -/** - * Append a new offset to the list. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param cursor The offset to append. - */ +/* Append a new offset to the list. */ static PRISM_FORCE_INLINE void pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint32_t cursor) { if (list->size < list->capacity) { @@ -60,14 +25,9 @@ pm_line_offset_list_append(pm_arena_t *arena, pm_line_offset_list_t *list, uint3 } } -/** +/* * Returns the line of the given offset. If the offset is not in the list, the * line of the closest offset less than the given offset is returned. - * - * @param list The list to search. - * @param cursor The offset to search for. - * @param start_line The line to start counting from. - * @return The line of the given offset. */ int32_t pm_line_offset_list_line(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line); diff --git a/include/prism/internal/list.h b/include/prism/internal/list.h index 9a73e6bd3f..0ab59ef32a 100644 --- a/include/prism/internal/list.h +++ b/include/prism/internal/list.h @@ -1,14 +1,9 @@ -/** - * @file internal/list.h - * - * An abstract linked list. - */ #ifndef PRISM_INTERNAL_LIST_H #define PRISM_INTERNAL_LIST_H #include -/** +/* * This struct represents an abstract linked list that provides common * functionality. It is meant to be used any time a linked list is necessary to * store data. @@ -39,39 +34,29 @@ * iteration and appending of new nodes. */ typedef struct pm_list_node { - /** A pointer to the next node in the list. */ + /* A pointer to the next node in the list. */ struct pm_list_node *next; } pm_list_node_t; -/** +/* * This represents the overall linked list. It keeps a pointer to the head and * tail so that iteration is easy and pushing new nodes is easy. */ typedef struct { - /** The size of the list. */ + /* The size of the list. */ size_t size; - /** A pointer to the head of the list. */ + /* A pointer to the head of the list. */ pm_list_node_t *head; - /** A pointer to the tail of the list. */ + /* A pointer to the tail of the list. */ pm_list_node_t *tail; } pm_list_t; -/** - * Returns the size of the list. - * - * @param list The list to check. - * @return The size of the list. - */ +/* Returns the size of the list. */ size_t pm_list_size(pm_list_t *list); -/** - * Append a node to the given list. - * - * @param list The list to append to. - * @param node The node to append. - */ +/* Append a node to the given list. */ void pm_list_append(pm_list_t *list, pm_list_node_t *node); #endif diff --git a/include/prism/internal/magic_comments.h b/include/prism/internal/magic_comments.h index 57c964bf4e..72a581c5d7 100644 --- a/include/prism/internal/magic_comments.h +++ b/include/prism/internal/magic_comments.h @@ -1,6 +1,3 @@ -/** - * @file internal/magic_comments.h - */ #ifndef PRISM_INTERNAL_MAGIC_COMMENTS_H #define PRISM_INTERNAL_MAGIC_COMMENTS_H @@ -8,20 +5,18 @@ #include "prism/internal/list.h" -/** +/* * This is a node in the linked list of magic comments that we've found while * parsing. - * - * @extends pm_list_node_t */ struct pm_magic_comment_t { - /** The embedded base node. */ + /* The embedded base node. */ pm_list_node_t node; - /** The key of the magic comment. */ + /* The key of the magic comment. */ pm_location_t key; - /** The value of the magic comment. */ + /* The value of the magic comment. */ pm_location_t value; }; diff --git a/include/prism/internal/memchr.h b/include/prism/internal/memchr.h index 905e3f33a1..63c738387d 100644 --- a/include/prism/internal/memchr.h +++ b/include/prism/internal/memchr.h @@ -1,8 +1,3 @@ -/** - * @file internal/memchr.h - * - * A custom memchr implementation. - */ #ifndef PRISM_INTERNAL_MEMCHR_H #define PRISM_INTERNAL_MEMCHR_H @@ -10,18 +5,10 @@ #include -/** +/* * We need to roll our own memchr to handle cases where the encoding changes and * we need to search for a character in a buffer that could be the trailing byte * of a multibyte character. - * - * @param source The source string. - * @param character The character to search for. - * @param number The maximum number of bytes to search. - * @param encoding_changed Whether the encoding changed. - * @param encoding A pointer to the encoding. - * @return A pointer to the first occurrence of the character in the source - * string, or NULL if no such character exists. */ void * pm_memchr(const void *source, int character, size_t number, bool encoding_changed, const pm_encoding_t *encoding); diff --git a/include/prism/internal/node.h b/include/prism/internal/node.h index 075dc33e0a..ca6d5616d7 100644 --- a/include/prism/internal/node.h +++ b/include/prism/internal/node.h @@ -1,6 +1,3 @@ -/** - * @file internal/node.h - */ #ifndef PRISM_INTERNAL_NODE_H #define PRISM_INTERNAL_NODE_H @@ -10,23 +7,13 @@ #include "prism/arena.h" -/** +/* * Slow path for pm_node_list_append: grow the list and append the node. * Do not call directly — use pm_node_list_append instead. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param node The node to append. */ void pm_node_list_append_slow(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); -/** - * Append a new node onto the end of the node list. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param node The node to append. - */ +/* Append a new node onto the end of the node list. */ static PRISM_FORCE_INLINE void pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { if (list->size < list->capacity) { @@ -36,22 +23,10 @@ pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) { } } -/** - * Prepend a new node onto the beginning of the node list. - * - * @param arena The arena to allocate from. - * @param list The list to prepend to. - * @param node The node to prepend. - */ +/* Prepend a new node onto the beginning of the node list. */ void pm_node_list_prepend(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node); -/** - * Concatenate the given node list onto the end of the other node list. - * - * @param arena The arena to allocate from. - * @param list The list to concatenate onto. - * @param other The list to concatenate. - */ +/* Concatenate the given node list onto the end of the other node list. */ void pm_node_list_concat(pm_arena_t *arena, pm_node_list_t *list, pm_node_list_t *other); #endif diff --git a/include/prism/internal/options.h b/include/prism/internal/options.h index 59606b09e6..7e37742a8b 100644 --- a/include/prism/internal/options.h +++ b/include/prism/internal/options.h @@ -1,95 +1,84 @@ -/** - * @file internal/options.h - * - * The options that can be passed to parsing. - */ #ifndef PRISM_INTERNAL_OPTIONS_H #define PRISM_INTERNAL_OPTIONS_H #include "prism/options.h" -/** - * A scope of locals surrounding the code that is being parsed. - */ +/* A scope of locals surrounding the code that is being parsed. */ struct pm_options_scope_t { - /** The number of locals in the scope. */ + /* The number of locals in the scope. */ size_t locals_count; - /** The names of the locals in the scope. */ + /* The names of the locals in the scope. */ pm_string_t *locals; - /** Flags for the set of forwarding parameters in this scope. */ + /* Flags for the set of forwarding parameters in this scope. */ uint8_t forwarding; }; -/** +/* * The version of Ruby syntax that we should be parsing with. This is used to * allow consumers to specify which behavior they want in case they need to * parse in the same way as a specific version of CRuby would have. */ typedef enum { - /** + /* * If an explicit version is not provided, the current version of prism will * be used. */ PM_OPTIONS_VERSION_UNSET = 0, - /** The vendored version of prism in CRuby 3.3.x. */ + /* The vendored version of prism in CRuby 3.3.x. */ PM_OPTIONS_VERSION_CRUBY_3_3 = 1, - /** The vendored version of prism in CRuby 3.4.x. */ + /* The vendored version of prism in CRuby 3.4.x. */ PM_OPTIONS_VERSION_CRUBY_3_4 = 2, - /** The vendored version of prism in CRuby 4.0.x. */ + /* The vendored version of prism in CRuby 4.0.x. */ PM_OPTIONS_VERSION_CRUBY_3_5 = 3, - /** The vendored version of prism in CRuby 4.0.x. */ + /* The vendored version of prism in CRuby 4.0.x. */ PM_OPTIONS_VERSION_CRUBY_4_0 = 3, - /** The vendored version of prism in CRuby 4.1.x. */ + /* The vendored version of prism in CRuby 4.1.x. */ PM_OPTIONS_VERSION_CRUBY_4_1 = 4, - /** The current version of prism. */ + /* The current version of prism. */ PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_4_1 } pm_options_version_t; -/** - * The options that can be passed to the parser. - */ +/* The options that can be passed to the parser. */ struct pm_options_t { - /** + /* * The callback to call when additional switches are found in a shebang * comment. */ pm_options_shebang_callback_t shebang_callback; - /** + /* * Any additional data that should be passed along to the shebang callback * if one was set. */ void *shebang_callback_data; - /** The name of the file that is currently being parsed. */ + /* The name of the file that is currently being parsed. */ pm_string_t filepath; - /** + /* * The line within the file that the parse starts on. This value is * 1-indexed. */ int32_t line; - /** + /* * The name of the encoding that the source file is in. Note that this must * correspond to a name that can be found with Encoding.find in Ruby. */ pm_string_t encoding; - /** - * The number of scopes surrounding the code that is being parsed. - */ + /* The number of scopes surrounding the code that is being parsed. */ size_t scopes_count; - /** + /* * The scopes surrounding the code that is being parsed. For most parses * this will be NULL, but for evals it will be the locals that are in scope * surrounding the eval. Scopes are ordered from the outermost scope to the @@ -97,17 +86,17 @@ struct pm_options_t { */ pm_options_scope_t *scopes; - /** + /* * The version of prism that we should be parsing with. This is used to * allow consumers to specify which behavior they want in case they need to * parse exactly as a specific version of CRuby. */ pm_options_version_t version; - /** A bitset of the various options that were set on the command line. */ + /* A bitset of the various options that were set on the command line. */ uint8_t command_line; - /** + /* * Whether or not the frozen string literal option has been set. * May be: * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED @@ -116,21 +105,21 @@ struct pm_options_t { */ int8_t frozen_string_literal; - /** + /* * Whether or not the encoding magic comments should be respected. This is a * niche use-case where you want to parse a file with a specific encoding * but ignore any encoding magic comments at the top of the file. */ bool encoding_locked; - /** + /* * When the file being parsed is the main script, the shebang will be * considered for command-line flags (or for implicit -x). The caller needs * to pass this information to the parser so that it can behave correctly. */ bool main_script; - /** + /* * When the file being parsed is considered a "partial" script, jumps will * not be marked as errors if they are not contained within loops/blocks. * This is used in the case that you're parsing a script that you know will @@ -140,7 +129,7 @@ struct pm_options_t { */ bool partial_script; - /** + /* * Whether or not the parser should freeze the nodes that it creates. This * makes it possible to have a deeply frozen AST that is safe to share * between concurrency primitives. @@ -148,14 +137,10 @@ struct pm_options_t { bool freeze; }; -/** - * Free the internal memory associated with the options. - * - * @param options The options struct whose internal memory should be freed. - */ +/* Free the internal memory associated with the options. */ void pm_options_cleanup(pm_options_t *options); -/** +/* * Deserialize an options struct from the given binary string. This is used to * pass options to the parser from an FFI call so that consumers of the library * from an FFI perspective don't have to worry about the structure of our @@ -221,9 +206,6 @@ void pm_options_cleanup(pm_options_t *options); * * The frozen string literal, encoding locked, main script, and partial script * fields are booleans, so their values should be either 0 or 1. * * The number of scopes can be 0. - * - * @param options The options struct to deserialize into. - * @param data The binary string to deserialize from. */ void pm_options_read(pm_options_t *options, const char *data); diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index c731e629db..dbed71e737 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -1,8 +1,3 @@ -/** - * @file internal/parser.h - * - * The parser used to parse Ruby source. - */ #ifndef PRISM_INTERNAL_PARSER_H #define PRISM_INTERNAL_PARSER_H @@ -23,7 +18,7 @@ #include #include -/** +/* * This enum provides various bits that represent different kinds of states that * the lexer can track. This is used to determine which kind of token to return * based on the context of the parser. @@ -44,7 +39,7 @@ typedef enum { PM_LEX_STATE_BIT_FITEM } pm_lex_state_bit_t; -/** +/* * This enum combines the various bits from the above enum into individual * values that represent the various states of the lexer. */ @@ -68,7 +63,7 @@ typedef enum { PM_LEX_STATE_END_ANY = PM_LEX_STATE_END | PM_LEX_STATE_ENDARG | PM_LEX_STATE_ENDFN } pm_lex_state_t; -/** +/* * The type of quote that a heredoc uses. */ typedef enum { @@ -78,7 +73,7 @@ typedef enum { PM_HEREDOC_QUOTE_BACKTICK = '`', } pm_heredoc_quote_t; -/** +/* * The type of indentation that a heredoc uses. */ typedef enum { @@ -87,24 +82,24 @@ typedef enum { PM_HEREDOC_INDENT_TILDE, } pm_heredoc_indent_t; -/** +/* * All of the information necessary to store to lexing a heredoc. */ typedef struct { - /** A pointer to the start of the heredoc identifier. */ + /* A pointer to the start of the heredoc identifier. */ const uint8_t *ident_start; - /** The length of the heredoc identifier. */ + /* The length of the heredoc identifier. */ size_t ident_length; - /** The type of quote that the heredoc uses. */ + /* The type of quote that the heredoc uses. */ pm_heredoc_quote_t quote; - /** The type of indentation that the heredoc uses. */ + /* The type of indentation that the heredoc uses. */ pm_heredoc_indent_t indent; } pm_heredoc_lex_mode_t; -/** +/* * When lexing Ruby source, the lexer has a small amount of state to tell which * kind of token it is currently lexing. For example, when we find the start of * a string, the first token that we return is a TOKEN_STRING_BEGIN token. After @@ -112,64 +107,64 @@ typedef struct { * are found as part of a string. */ typedef struct pm_lex_mode { - /** The type of this lex mode. */ + /* The type of this lex mode. */ enum { - /** This state is used when any given token is being lexed. */ + /* This state is used when any given token is being lexed. */ PM_LEX_DEFAULT, - /** + /* * This state is used when we're lexing as normal but inside an embedded * expression of a string. */ PM_LEX_EMBEXPR, - /** + /* * This state is used when we're lexing a variable that is embedded * directly inside of a string with the # shorthand. */ PM_LEX_EMBVAR, - /** This state is used when you are inside the content of a heredoc. */ + /* This state is used when you are inside the content of a heredoc. */ PM_LEX_HEREDOC, - /** + /* * This state is used when we are lexing a list of tokens, as in a %w * word list literal or a %i symbol list literal. */ PM_LEX_LIST, - /** + /* * This state is used when a regular expression has been begun and we * are looking for the terminator. */ PM_LEX_REGEXP, - /** + /* * This state is used when we are lexing a string or a string-like * token, as in string content with either quote or an xstring. */ PM_LEX_STRING } mode; - /** The data associated with this type of lex mode. */ + /* The data associated with this type of lex mode. */ union { struct { - /** This keeps track of the nesting level of the list. */ + /* This keeps track of the nesting level of the list. */ size_t nesting; - /** Whether or not interpolation is allowed in this list. */ + /* Whether or not interpolation is allowed in this list. */ bool interpolation; - /** + /* * When lexing a list, it takes into account balancing the * terminator if the terminator is one of (), [], {}, or <>. */ uint8_t incrementor; - /** This is the terminator of the list literal. */ + /* This is the terminator of the list literal. */ uint8_t terminator; - /** + /* * This is the character set that should be used to delimit the * tokens within the list. */ @@ -177,21 +172,21 @@ typedef struct pm_lex_mode { } list; struct { - /** + /* * This keeps track of the nesting level of the regular expression. */ size_t nesting; - /** + /* * When lexing a regular expression, it takes into account balancing * the terminator if the terminator is one of (), [], {}, or <>. */ uint8_t incrementor; - /** This is the terminator of the regular expression. */ + /* This is the terminator of the regular expression. */ uint8_t terminator; - /** + /* * This is the character set that should be used to delimit the * tokens within the regular expression. */ @@ -199,32 +194,32 @@ typedef struct pm_lex_mode { } regexp; struct { - /** This keeps track of the nesting level of the string. */ + /* This keeps track of the nesting level of the string. */ size_t nesting; - /** Whether or not interpolation is allowed in this string. */ + /* Whether or not interpolation is allowed in this string. */ bool interpolation; - /** + /* * Whether or not at the end of the string we should allow a :, * which would indicate this was a dynamic symbol instead of a * string. */ bool label_allowed; - /** + /* * When lexing a string, it takes into account balancing the * terminator if the terminator is one of (), [], {}, or <>. */ uint8_t incrementor; - /** + /* * This is the terminator of the string. It is typically either a * single or double quote. */ uint8_t terminator; - /** + /* * This is the character set that should be used to delimit the * tokens within the string. */ @@ -232,273 +227,273 @@ typedef struct pm_lex_mode { } string; struct { - /** + /* * All of the data necessary to lex a heredoc. */ pm_heredoc_lex_mode_t base; - /** + /* * This is the pointer to the character where lexing should resume * once the heredoc has been completely processed. */ const uint8_t *next_start; - /** + /* * This is used to track the amount of common whitespace on each * line so that we know how much to dedent each line in the case of * a tilde heredoc. */ size_t *common_whitespace; - /** True if the previous token ended with a line continuation. */ + /* True if the previous token ended with a line continuation. */ bool line_continuation; } heredoc; } as; - /** The previous lex state so that it knows how to pop. */ + /* The previous lex state so that it knows how to pop. */ struct pm_lex_mode *prev; } pm_lex_mode_t; -/** +/* * We pre-allocate a certain number of lex states in order to avoid having to * call malloc too many times while parsing. You really shouldn't need more than * this because you only really nest deeply when doing string interpolation. */ #define PM_LEX_STACK_SIZE 4 -/** +/* * While parsing, we keep track of a stack of contexts. This is helpful for * error recovery so that we can pop back to a previous context when we hit a * token that is understood by a parent context but not by the current context. */ typedef enum { - /** a null context, used for returning a value from a function */ + /* a null context, used for returning a value from a function */ PM_CONTEXT_NONE = 0, - /** a begin statement */ + /* a begin statement */ PM_CONTEXT_BEGIN, - /** an ensure statement with an explicit begin */ + /* an ensure statement with an explicit begin */ PM_CONTEXT_BEGIN_ENSURE, - /** a rescue else statement with an explicit begin */ + /* a rescue else statement with an explicit begin */ PM_CONTEXT_BEGIN_ELSE, - /** a rescue statement with an explicit begin */ + /* a rescue statement with an explicit begin */ PM_CONTEXT_BEGIN_RESCUE, - /** expressions in block arguments using braces */ + /* expressions in block arguments using braces */ PM_CONTEXT_BLOCK_BRACES, - /** expressions in block arguments using do..end */ + /* expressions in block arguments using do..end */ PM_CONTEXT_BLOCK_KEYWORDS, - /** an ensure statement within a do..end block */ + /* an ensure statement within a do..end block */ PM_CONTEXT_BLOCK_ENSURE, - /** a rescue else statement within a do..end block */ + /* a rescue else statement within a do..end block */ PM_CONTEXT_BLOCK_ELSE, - /** expressions in block parameters `foo do |...| end ` */ + /* expressions in block parameters `foo do |...| end ` */ PM_CONTEXT_BLOCK_PARAMETERS, - /** a rescue statement within a do..end block */ + /* a rescue statement within a do..end block */ PM_CONTEXT_BLOCK_RESCUE, - /** a case when statements */ + /* a case when statements */ PM_CONTEXT_CASE_WHEN, - /** a case in statements */ + /* a case in statements */ PM_CONTEXT_CASE_IN, - /** a class declaration */ + /* a class declaration */ PM_CONTEXT_CLASS, - /** an ensure statement within a class statement */ + /* an ensure statement within a class statement */ PM_CONTEXT_CLASS_ENSURE, - /** a rescue else statement within a class statement */ + /* a rescue else statement within a class statement */ PM_CONTEXT_CLASS_ELSE, - /** a rescue statement within a class statement */ + /* a rescue statement within a class statement */ PM_CONTEXT_CLASS_RESCUE, - /** a method definition */ + /* a method definition */ PM_CONTEXT_DEF, - /** an ensure statement within a method definition */ + /* an ensure statement within a method definition */ PM_CONTEXT_DEF_ENSURE, - /** a rescue else statement within a method definition */ + /* a rescue else statement within a method definition */ PM_CONTEXT_DEF_ELSE, - /** a rescue statement within a method definition */ + /* a rescue statement within a method definition */ PM_CONTEXT_DEF_RESCUE, - /** a method definition's parameters */ + /* a method definition's parameters */ PM_CONTEXT_DEF_PARAMS, - /** a defined? expression */ + /* a defined? expression */ PM_CONTEXT_DEFINED, - /** a method definition's default parameter */ + /* a method definition's default parameter */ PM_CONTEXT_DEFAULT_PARAMS, - /** an else clause */ + /* an else clause */ PM_CONTEXT_ELSE, - /** an elsif clause */ + /* an elsif clause */ PM_CONTEXT_ELSIF, - /** an interpolated expression */ + /* an interpolated expression */ PM_CONTEXT_EMBEXPR, - /** a for loop */ + /* a for loop */ PM_CONTEXT_FOR, - /** a for loop's index */ + /* a for loop's index */ PM_CONTEXT_FOR_INDEX, - /** an if statement */ + /* an if statement */ PM_CONTEXT_IF, - /** a lambda expression with braces */ + /* a lambda expression with braces */ PM_CONTEXT_LAMBDA_BRACES, - /** a lambda expression with do..end */ + /* a lambda expression with do..end */ PM_CONTEXT_LAMBDA_DO_END, - /** an ensure statement within a lambda expression */ + /* an ensure statement within a lambda expression */ PM_CONTEXT_LAMBDA_ENSURE, - /** a rescue else statement within a lambda expression */ + /* a rescue else statement within a lambda expression */ PM_CONTEXT_LAMBDA_ELSE, - /** a rescue statement within a lambda expression */ + /* a rescue statement within a lambda expression */ PM_CONTEXT_LAMBDA_RESCUE, - /** the predicate clause of a loop statement */ + /* the predicate clause of a loop statement */ PM_CONTEXT_LOOP_PREDICATE, - /** the top level context */ + /* the top level context */ PM_CONTEXT_MAIN, - /** a module declaration */ + /* a module declaration */ PM_CONTEXT_MODULE, - /** an ensure statement within a module statement */ + /* an ensure statement within a module statement */ PM_CONTEXT_MODULE_ENSURE, - /** a rescue else statement within a module statement */ + /* a rescue else statement within a module statement */ PM_CONTEXT_MODULE_ELSE, - /** a rescue statement within a module statement */ + /* a rescue statement within a module statement */ PM_CONTEXT_MODULE_RESCUE, - /** a multiple target expression */ + /* a multiple target expression */ PM_CONTEXT_MULTI_TARGET, - /** a parenthesized expression */ + /* a parenthesized expression */ PM_CONTEXT_PARENS, - /** an END block */ + /* an END block */ PM_CONTEXT_POSTEXE, - /** a predicate inside an if/elsif/unless statement */ + /* a predicate inside an if/elsif/unless statement */ PM_CONTEXT_PREDICATE, - /** a BEGIN block */ + /* a BEGIN block */ PM_CONTEXT_PREEXE, - /** a modifier rescue clause */ + /* a modifier rescue clause */ PM_CONTEXT_RESCUE_MODIFIER, - /** a singleton class definition */ + /* a singleton class definition */ PM_CONTEXT_SCLASS, - /** an ensure statement with a singleton class */ + /* an ensure statement with a singleton class */ PM_CONTEXT_SCLASS_ENSURE, - /** a rescue else statement with a singleton class */ + /* a rescue else statement with a singleton class */ PM_CONTEXT_SCLASS_ELSE, - /** a rescue statement with a singleton class */ + /* a rescue statement with a singleton class */ PM_CONTEXT_SCLASS_RESCUE, - /** a ternary expression */ + /* a ternary expression */ PM_CONTEXT_TERNARY, - /** an unless statement */ + /* an unless statement */ PM_CONTEXT_UNLESS, - /** an until statement */ + /* an until statement */ PM_CONTEXT_UNTIL, - /** a while statement */ + /* a while statement */ PM_CONTEXT_WHILE, } pm_context_t; -/** This is a node in a linked list of contexts. */ +/* This is a node in a linked list of contexts. */ typedef struct pm_context_node { - /** The context that this node represents. */ + /* The context that this node represents. */ pm_context_t context; - /** A pointer to the previous context in the linked list. */ + /* A pointer to the previous context in the linked list. */ struct pm_context_node *prev; } pm_context_node_t; -/** The type of shareable constant value that can be set. */ +/* The type of shareable constant value that can be set. */ typedef uint8_t pm_shareable_constant_value_t; static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0; static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL; static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING; static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY; -/** +/* * This tracks an individual local variable in a certain lexical context, as * well as the number of times is it read. */ typedef struct { - /** The name of the local variable. */ + /* The name of the local variable. */ pm_constant_id_t name; - /** The location of the local variable in the source. */ + /* The location of the local variable in the source. */ pm_location_t location; - /** The index of the local variable in the local table. */ + /* The index of the local variable in the local table. */ uint32_t index; - /** The number of times the local variable is read. */ + /* The number of times the local variable is read. */ uint32_t reads; - /** The hash of the local variable. */ + /* The hash of the local variable. */ uint32_t hash; } pm_local_t; -/** +/* * This is a set of local variables in a certain lexical context (method, class, * module, etc.). We need to track how many times these variables are read in * order to warn if they only get written. */ typedef struct pm_locals { - /** The number of local variables in the set. */ + /* The number of local variables in the set. */ uint32_t size; - /** The capacity of the local variables set. */ + /* The capacity of the local variables set. */ uint32_t capacity; - /** + /* * A bloom filter over constant IDs stored in this set. Used to quickly * reject lookups for names that are definitely not present, avoiding the * cost of a linear scan or hash probe. */ uint32_t bloom; - /** The nullable allocated memory for the local variables in the set. */ + /* The nullable allocated memory for the local variables in the set. */ pm_local_t *locals; } pm_locals_t; -/** The flags about scope parameters that can be set. */ +/* The flags about scope parameters that can be set. */ typedef uint8_t pm_scope_parameters_t; static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NONE = 0x0; static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x1; @@ -509,18 +504,18 @@ static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED = 0x1 static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_INNER = 0x20; static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_FOUND = 0x40; -/** +/* * This struct represents a node in a linked list of scopes. Some scopes can see * into their parent scopes, while others cannot. */ typedef struct pm_scope { - /** A pointer to the previous scope in the linked list. */ + /* A pointer to the previous scope in the linked list. */ struct pm_scope *previous; - /** The IDs of the locals in the given scope. */ + /* The IDs of the locals in the given scope. */ pm_locals_t locals; - /** + /* * This is a list of the implicit parameters contained within the block. * These will be processed after the block is parsed to determine the kind * of parameters node that should be used and to check if any errors need to @@ -528,7 +523,7 @@ typedef struct pm_scope { */ pm_node_list_t implicit_parameters; - /** + /* * This is a bitfield that indicates the parameters that are being used in * this scope. It is a combination of the PM_SCOPE_PARAMETERS_* constants. * There are three different kinds of parameters that can be used in a @@ -549,106 +544,106 @@ typedef struct pm_scope { */ pm_scope_parameters_t parameters; - /** + /* * The current state of constant shareability for this scope. This is * changed by magic shareable_constant_value comments. */ pm_shareable_constant_value_t shareable_constant; - /** + /* * A boolean indicating whether or not this scope can see into its parent. * If closed is true, then the scope cannot see into its parent. */ bool closed; } pm_scope_t; -/** +/* * A struct that represents a stack of boolean values. */ typedef uint32_t pm_state_stack_t; -/** +/* * This struct represents the overall parser. It contains a reference to the * source file, as well as pointers that indicate where in the source it's * currently parsing. It also contains the most recent and current token that * it's considering. */ struct pm_parser_t { - /** The arena used for all AST-lifetime allocations. Caller-owned. */ + /* The arena used for all AST-lifetime allocations. Caller-owned. */ pm_arena_t *arena; - /** The arena used for parser metadata (comments, diagnostics, etc.). */ + /* The arena used for parser metadata (comments, diagnostics, etc.). */ pm_arena_t metadata_arena; - /** + /* * The next node identifier that will be assigned. This is a unique * identifier used to track nodes such that the syntax tree can be dropped * but the node can be found through another parse. */ uint32_t node_id; - /** The current state of the lexer. */ + /* The current state of the lexer. */ pm_lex_state_t lex_state; - /** Tracks the current nesting of (), [], and {}. */ + /* Tracks the current nesting of (), [], and {}. */ int enclosure_nesting; - /** + /* * Used to temporarily track the nesting of enclosures to determine if a { * is the beginning of a lambda following the parameters of a lambda. */ int lambda_enclosure_nesting; - /** + /* * Used to track the nesting of braces to ensure we get the correct value * when we are interpolating blocks with braces. */ int brace_nesting; - /** + /* * The stack used to determine if a do keyword belongs to the predicate of a * while, until, or for loop. */ pm_state_stack_t do_loop_stack; - /** + /* * The stack used to determine if a do keyword belongs to the beginning of a * block. */ pm_state_stack_t accepts_block_stack; - /** A stack of lex modes. */ + /* A stack of lex modes. */ struct { - /** The current mode of the lexer. */ + /* The current mode of the lexer. */ pm_lex_mode_t *current; - /** The stack of lexer modes. */ + /* The stack of lexer modes. */ pm_lex_mode_t stack[PM_LEX_STACK_SIZE]; - /** The current index into the lexer mode stack. */ + /* The current index into the lexer mode stack. */ size_t index; } lex_modes; - /** The pointer to the start of the source. */ + /* The pointer to the start of the source. */ const uint8_t *start; - /** The pointer to the end of the source. */ + /* The pointer to the end of the source. */ const uint8_t *end; - /** The previous token we were considering. */ + /* The previous token we were considering. */ pm_token_t previous; - /** The current token we're considering. */ + /* The current token we're considering. */ pm_token_t current; - /** + /* * This is a special field set on the parser when we need the parser to jump * to a specific location when lexing the next token, as opposed to just * using the end of the previous token. Normally this is NULL. */ const uint8_t *next_start; - /** + /* * This field indicates the end of a heredoc whose identifier was found on * the current line. If another heredoc is found on the same line, then this * will be moved forward to the end of that heredoc. If no heredocs are @@ -656,32 +651,32 @@ struct pm_parser_t { */ const uint8_t *heredoc_end; - /** The list of comments that have been found while parsing. */ + /* The list of comments that have been found while parsing. */ pm_list_t comment_list; - /** The list of magic comments that have been found while parsing. */ + /* The list of magic comments that have been found while parsing. */ pm_list_t magic_comment_list; - /** + /* * An optional location that represents the location of the __END__ marker * and the rest of the content of the file. This content is loaded into the * DATA constant when the file being parsed is the main file being executed. */ pm_location_t data_loc; - /** The list of warnings that have been found while parsing. */ + /* The list of warnings that have been found while parsing. */ pm_list_t warning_list; - /** The list of errors that have been found while parsing. */ + /* The list of errors that have been found while parsing. */ pm_list_t error_list; - /** The current local scope. */ + /* The current local scope. */ pm_scope_t *current_scope; - /** The current parsing context. */ + /* The current parsing context. */ pm_context_node_t *current_context; - /** + /* * The hash keys for the hash that is currently being parsed. This is not * usually necessary because it can pass it down the various call chains, * but in the event that you're parsing a hash that is being directly @@ -690,26 +685,26 @@ struct pm_parser_t { */ pm_static_literals_t *current_hash_keys; - /** + /* * The encoding functions for the current file is attached to the parser as * it's parsing so that it can change with a magic comment. */ const pm_encoding_t *encoding; - /** + /* * When the encoding that is being used to parse the source is changed by * prism, we provide the ability here to call out to a user-defined * function. */ pm_encoding_changed_callback_t encoding_changed_callback; - /** + /* * This pointer indicates where a comment must start if it is to be * considered an encoding comment. */ const uint8_t *encoding_comment_start; - /** + /* * When you are lexing through a file, the lexer needs all of the information * that the parser additionally provides (for example, the local table). So if * you want to properly lex Ruby, you need to actually lex it in the context of @@ -718,14 +713,14 @@ struct pm_parser_t { * callback when each token is lexed. */ struct { - /** + /* * This is the callback that is called when a token is lexed. It is * passed the opaque data pointer, the parser, and the token that was * lexed. */ pm_lex_callback_t callback; - /** + /* * This opaque pointer is used to provide whatever information the user * deemed necessary to the callback. In our case we use it to pass the * array that the tokens get appended into. @@ -733,32 +728,32 @@ struct pm_parser_t { void *data; } lex_callback; - /** + /* * This is the path of the file being parsed. We use the filepath when * constructing SourceFileNodes. */ pm_string_t filepath; - /** + /* * This constant pool keeps all of the constants defined throughout the file * so that we can reference them later. */ pm_constant_pool_t constant_pool; - /** This is the list of line offsets in the source file. */ + /* This is the list of line offsets in the source file. */ pm_line_offset_list_t line_offsets; - /** + /* * State communicated from the lexer to the parser for integer tokens. */ struct { - /** + /* * A flag indicating the base of the integer (binary, octal, decimal, * hexadecimal). Set during lexing and read during node creation. */ pm_node_flags_t base; - /** + /* * When lexing a decimal integer that fits in a uint32_t, we compute * the value during lexing to avoid re-scanning the digits during * parsing. If lexed is true, this holds the result and @@ -766,23 +761,23 @@ struct pm_parser_t { */ uint32_t value; - /** Whether value holds a valid pre-computed integer. */ + /* Whether value holds a valid pre-computed integer. */ bool lexed; } integer; - /** + /* * This string is used to pass information from the lexer to the parser. It * is particularly necessary because of escape sequences. */ pm_string_t current_string; - /** + /* * The line number at the start of the parse. This will be used to offset * the line numbers of all of the locations. */ int32_t start_line; - /** + /* * When a string-like expression is being lexed, any byte or escape sequence * that resolves to a value whose top bit is set (i.e., >= 0x80) will * explicitly set the encoding to the same encoding as the source. @@ -813,7 +808,7 @@ struct pm_parser_t { */ const pm_encoding_t *explicit_encoding; - /** + /* * When parsing block exits (e.g., break, next, redo), we need to validate * that they are in correct contexts. For the most part we can do this by * looking at our parent contexts. However, modifier while and until @@ -826,13 +821,13 @@ struct pm_parser_t { */ pm_node_list_t *current_block_exits; - /** The version of prism that we should use to parse. */ + /* The version of prism that we should use to parse. */ pm_options_version_t version; - /** The command line flags given from the options. */ + /* The command line flags given from the options. */ uint8_t command_line; - /** + /* * Whether or not we have found a frozen_string_literal magic comment with * a true or false value. * May be: @@ -842,33 +837,33 @@ struct pm_parser_t { */ int8_t frozen_string_literal; - /** + /* * Whether or not we are parsing an eval string. This impacts whether or not * we should evaluate if block exits/yields are valid. */ bool parsing_eval; - /** + /* * Whether or not we are parsing a "partial" script, which is a script that * will be evaluated in the context of another script, so we should not * check jumps (next/break/etc.) for validity. */ bool partial_script; - /** Whether or not we're at the beginning of a command. */ + /* Whether or not we're at the beginning of a command. */ bool command_start; - /** + /* * Whether or not we're currently parsing the body of an endless method * definition. In this context, PM_TOKEN_KEYWORD_DO_BLOCK should not be * consumed by commands (it should bubble up to the outer context). */ bool in_endless_def_body; - /** Whether or not we're currently recovering from a syntax error. */ + /* Whether or not we're currently recovering from a syntax error. */ bool recovering; - /** + /* * Whether or not the source being parsed could become valid if more input * were appended. This is set to false when the parser encounters a token * that is definitively wrong (e.g., a stray `end` or `]`) as opposed to @@ -876,7 +871,7 @@ struct pm_parser_t { */ bool continuable; - /** + /* * This is very specialized behavior for when you want to parse in a context * that does not respect encoding comments. Its main use case is translating * into the whitequark/parser AST which re-encodes source files in UTF-8 @@ -884,76 +879,66 @@ struct pm_parser_t { */ bool encoding_locked; - /** + /* * Whether or not the encoding has been changed by a magic comment. We use * this to provide a fast path for the lexer instead of going through the * function pointer. */ bool encoding_changed; - /** + /* * This flag indicates that we are currently parsing a pattern matching * expression and impacts that calculation of newlines. */ bool pattern_matching_newlines; - /** This flag indicates that we are currently parsing a keyword argument. */ + /* This flag indicates that we are currently parsing a keyword argument. */ bool in_keyword_arg; - /** + /* * Whether or not the parser has seen a token that has semantic meaning * (i.e., a token that is not a comment or whitespace). */ bool semantic_token_seen; - /** + /* * By default, Ruby always warns about mismatched indentation. This can be * toggled with a magic comment. */ bool warn_mismatched_indentation; #if defined(PRISM_HAS_NEON) || defined(PRISM_HAS_SSSE3) || defined(PRISM_HAS_SWAR) - /** + /* * Cached lookup tables for pm_strpbrk's SIMD fast path. Avoids rebuilding * the nibble-based tables on every call when the charset hasn't changed * (which is the common case during string/regex/list lexing). */ struct { - /** The cached charset (null-terminated, max 11 chars + NUL). */ + /* The cached charset (null-terminated, max 11 chars + NUL). */ uint8_t charset[12]; - /** Nibble-based low lookup table for SIMD matching. */ + /* Nibble-based low lookup table for SIMD matching. */ uint8_t low_lut[16]; - /** Nibble-based high lookup table for SIMD matching. */ + /* Nibble-based high lookup table for SIMD matching. */ uint8_t high_lut[16]; - /** Scalar fallback table (4 x 64-bit bitmasks covering all ASCII). */ + /* Scalar fallback table (4 x 64-bit bitmasks covering all ASCII). */ uint64_t table[4]; } strpbrk_cache; #endif }; -/** +/* * Initialize a parser with the given start and end pointers. - * - * @param arena The arena to use for all AST-lifetime allocations. It is caller- - * owned and must outlive the parser. - * @param parser The parser to initialize. - * @param source The source to parse. - * @param size The size of the source. - * @param options The optional options to use when parsing. These options must - * live for the whole lifetime of this parser. */ void pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options); -/** +/* * Free the memory held by the given parser. * * This does not free the `pm_options_t` object that was used to initialize the * parser. - * - * @param parser The parser whose held memory should be freed. */ void pm_parser_cleanup(pm_parser_t *parser); diff --git a/include/prism/internal/regexp.h b/include/prism/internal/regexp.h index 7f4731967c..3710c984fc 100644 --- a/include/prism/internal/regexp.h +++ b/include/prism/internal/regexp.h @@ -1,64 +1,40 @@ -/** - * @file internal/regexp.h - * - * A regular expression parser. - */ #ifndef PRISM_INTERNAL_REGEXP_H #define PRISM_INTERNAL_REGEXP_H #include "prism/ast.h" #include "prism/parser.h" -/** +/* * Accumulation state for named capture groups found during regexp parsing. * The caller initializes this with the call node and passes it to * pm_regexp_parse. The regexp parser populates match and names as groups * are found. */ typedef struct { - /** The call node wrapping the regular expression node (for =~). */ + /* The call node wrapping the regular expression node (for =~). */ pm_call_node_t *call; - /** The match write node being built, or NULL if no captures found yet. */ + /* The match write node being built, or NULL if no captures found yet. */ pm_match_write_node_t *match; - /** The list of capture names found so far (for deduplication). */ + /* The list of capture names found so far (for deduplication). */ pm_constant_id_list_t names; } pm_regexp_name_data_t; -/** +/* * Callback invoked by pm_regexp_parse() for each named capture group found. - * - * @param parser The main parser. - * @param name The name of the capture group. - * @param shared Whether the source content is shared (impacts constant storage). - * @param data The accumulation state for named captures. */ typedef void (*pm_regexp_name_callback_t)(pm_parser_t *parser, const pm_string_t *name, bool shared, pm_regexp_name_data_t *data); -/** +/* * Parse a regular expression, validate its encoding, and optionally extract * named capture groups. Returns the encoding flags to set on the node. - * - * @param parser The parser that is currently being used. - * @param node The regular expression node to parse and validate. - * @param name_callback The optional callback to call when a named capture group is found. - * @param name_data The optional accumulation state for named captures. - * @return The encoding flags to set on the node (e.g., FORCED_UTF8_ENCODING). */ PRISM_EXPORTED_FUNCTION pm_node_flags_t pm_regexp_parse(pm_parser_t *parser, pm_regular_expression_node_t *node, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data); -/** +/* * Parse an interpolated regular expression for named capture groups only. * No encoding validation is performed. - * - * @param parser The parser that is currently being used. - * @param source The source content to parse. - * @param size The length of the source content. - * @param shared Whether the source points into the parser's source buffer. - * @param extended_mode Whether or not the regular expression is in extended mode. - * @param name_callback The callback to call when a named capture group is found. - * @param name_data The accumulation state for named captures. */ void pm_regexp_parse_named_captures(pm_parser_t *parser, const uint8_t *source, size_t size, bool shared, bool extended_mode, pm_regexp_name_callback_t name_callback, pm_regexp_name_data_t *name_data); diff --git a/include/prism/internal/serialize.h b/include/prism/internal/serialize.h index c691a1fed9..e611a0374b 100644 --- a/include/prism/internal/serialize.h +++ b/include/prism/internal/serialize.h @@ -1,6 +1,3 @@ -/** - * @file internal/serialize.h - */ #ifndef PRISM_INTERNAL_SERIALIZE_H #define PRISM_INTERNAL_SERIALIZE_H @@ -17,28 +14,18 @@ * PRISM_EXCLUDE_SERIALIZATION define. */ #ifndef PRISM_EXCLUDE_SERIALIZATION -/** +/* * Serialize the given list of comments to the given buffer. - * - * @param list The list of comments to serialize. - * @param buffer The buffer to serialize to. */ void pm_serialize_comment_list(pm_list_t *list, pm_buffer_t *buffer); -/** +/* * Serialize the name of the encoding to the buffer. - * - * @param encoding The encoding to serialize. - * @param buffer The buffer to serialize to. */ void pm_serialize_encoding(const pm_encoding_t *encoding, pm_buffer_t *buffer); -/** +/* * Serialize the encoding, metadata, nodes, and constant pool. - * - * @param parser The parser to serialize. - * @param node The node to serialize. - * @param buffer The buffer to serialize to. */ void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer); diff --git a/include/prism/internal/static_literals.h b/include/prism/internal/static_literals.h index 0512313259..d59002ac0a 100644 --- a/include/prism/internal/static_literals.h +++ b/include/prism/internal/static_literals.h @@ -1,8 +1,3 @@ -/** - * @file internal/static_literals.h - * - * A set of static literal nodes that can be checked for duplicates. - */ #ifndef PRISM_INTERNAL_STATIC_LITERALS_H #define PRISM_INTERNAL_STATIC_LITERALS_H @@ -10,21 +5,21 @@ #include "prism/buffer.h" #include "prism/line_offset_list.h" -/** +/* * An internal hash table for a set of nodes. */ typedef struct { - /** The array of nodes in the hash table. */ + /* The array of nodes in the hash table. */ pm_node_t **nodes; - /** The size of the hash table. */ + /* The size of the hash table. */ uint32_t size; - /** The space that has been allocated in the hash table. */ + /* The space that has been allocated in the hash table. */ uint32_t capacity; } pm_node_hash_t; -/** +/* * Certain sets of nodes (hash keys and when clauses) check for duplicate nodes * to alert the user of potential issues. To do this, we keep a set of the nodes * that have been seen so far, and compare whenever we find a new node. @@ -33,87 +28,70 @@ typedef struct { * that need to be performed. */ typedef struct { - /** + /* * This is the set of IntegerNode and SourceLineNode instances. */ pm_node_hash_t integer_nodes; - /** + /* * This is the set of FloatNode instances. */ pm_node_hash_t float_nodes; - /** + /* * This is the set of RationalNode and ImaginaryNode instances. */ pm_node_hash_t number_nodes; - /** + /* * This is the set of StringNode and SourceFileNode instances. */ pm_node_hash_t string_nodes; - /** + /* * This is the set of RegularExpressionNode instances. */ pm_node_hash_t regexp_nodes; - /** + /* * This is the set of SymbolNode instances. */ pm_node_hash_t symbol_nodes; - /** + /* * A pointer to the last TrueNode instance that was inserted, or NULL. */ pm_node_t *true_node; - /** + /* * A pointer to the last FalseNode instance that was inserted, or NULL. */ pm_node_t *false_node; - /** + /* * A pointer to the last NilNode instance that was inserted, or NULL. */ pm_node_t *nil_node; - /** + /* * A pointer to the last SourceEncodingNode instance that was inserted, or * NULL. */ pm_node_t *source_encoding_node; } pm_static_literals_t; -/** +/* * Add a node to the set of static literals. - * - * @param line_offsets The list of newline offsets to use to calculate lines. - * @param start The start of the source being parsed. - * @param start_line The line number that the parser starts on. - * @param literals The set of static literals to add the node to. - * @param node The node to add to the set. - * @param replace Whether to replace the previous node if one already exists. - * @return A pointer to the node that is being overwritten, if there is one. */ pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace); -/** +/* * Free the internal memory associated with the given static literals set. - * - * @param literals The set of static literals to free. */ void pm_static_literals_free(pm_static_literals_t *literals); -/** +/* * Create a string-based representation of the given static literal. - * - * @param buffer The buffer to write the string to. - * @param line_offsets The list of newline offsets to use to calculate lines. - * @param start The start of the source being parsed. - * @param start_line The line number that the parser starts on. - * @param encoding_name The name of the encoding of the source being parsed. - * @param node The node to create a string representation of. */ void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const char *encoding_name, const pm_node_t *node); diff --git a/include/prism/internal/strings.h b/include/prism/internal/strings.h index f46aa86a81..0199ed8d67 100644 --- a/include/prism/internal/strings.h +++ b/include/prism/internal/strings.h @@ -1,54 +1,35 @@ -/** - * @file internal/strings.h - * - * A generic string type that can have various ownership semantics. - */ #ifndef PRISM_INTERNAL_STRINGS_H #define PRISM_INTERNAL_STRINGS_H #include "prism/strings.h" -/** +/* * Defines an empty string. This is useful for initializing a string that will * be filled in later. */ #define PM_STRING_EMPTY ((pm_string_t) { .type = PM_STRING_CONSTANT, .source = NULL, .length = 0 }) -/** +/* * Initialize a shared string that is based on initial input. - * - * @param string The string to initialize. - * @param start The start of the string. - * @param end The end of the string. */ void pm_string_shared_init(pm_string_t *string, const uint8_t *start, const uint8_t *end); -/** +/* * Initialize an owned string that is responsible for freeing allocated memory. - * - * @param string The string to initialize. - * @param source The source of the string. - * @param length The length of the string. */ void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length); -/** +/* * Ensure the string is owned. If it is not, then reinitialize it as owned and * copy over the previous source. - * - * @param string The string to ensure is owned. */ void pm_string_ensure_owned(pm_string_t *string); -/** +/* * Compare the underlying lengths and bytes of two strings. Returns 0 if the * strings are equal, a negative number if the left string is less than the * right string, and a positive number if the left string is greater than the * right string. - * - * @param left The left string to compare. - * @param right The right string to compare. - * @return The comparison result. */ int pm_string_compare(const pm_string_t *left, const pm_string_t *right); diff --git a/include/prism/internal/strncasecmp.h b/include/prism/internal/strncasecmp.h index c6cabe9c23..775f6a993e 100644 --- a/include/prism/internal/strncasecmp.h +++ b/include/prism/internal/strncasecmp.h @@ -1,15 +1,10 @@ -/** - * @file internal/strncasecmp.h - * - * A custom strncasecmp implementation. - */ #ifndef PRISM_INTERNAL_STRNCASECMP_H #define PRISM_INTERNAL_STRNCASECMP_H #include #include -/** +/* * Compare two strings, ignoring case, up to the given length. Returns 0 if the * strings are equal, a negative number if string1 is less than string2, or a * positive number if string1 is greater than string2. @@ -17,12 +12,6 @@ * Note that this is effectively our own implementation of strncasecmp, but it's * not available on all of the platforms we want to support so we're rolling it * here. - * - * @param string1 The first string to compare. - * @param string2 The second string to compare - * @param length The maximum number of characters to compare. - * @return 0 if the strings are equal, a negative number if string1 is less than - * string2, or a positive number if string1 is greater than string2. */ int pm_strncasecmp(const uint8_t *string1, const uint8_t *string2, size_t length); diff --git a/include/prism/internal/strpbrk.h b/include/prism/internal/strpbrk.h index ca5692d25c..124c528cb3 100644 --- a/include/prism/internal/strpbrk.h +++ b/include/prism/internal/strpbrk.h @@ -1,8 +1,3 @@ -/** - * @file internal/strpbrk.h - * - * A custom strpbrk implementation. - */ #ifndef PRISM_INTERNAL_STRPBRK_H #define PRISM_INTERNAL_STRPBRK_H @@ -11,7 +6,7 @@ #include #include -/** +/* * Here we have rolled our own version of strpbrk. The standard library strpbrk * has undefined behavior when the source string is not null-terminated. We want * to support strings that are not null-terminated because pm_parse does not @@ -29,15 +24,6 @@ * characters that are trailing bytes of multi-byte characters. For example, in * Shift-JIS, the backslash character can be a trailing byte. In that case we * need to take a slower path and iterate one multi-byte character at a time. - * - * @param parser The parser. - * @param source The source to search. - * @param charset The charset to search for. - * @param length The maximum number of bytes to search. - * @param validate Whether to validate that the source string is valid in the - * current encoding of the parser. - * @return A pointer to the first character in the source string that is in the - * charset, or NULL if no such character exists. */ const uint8_t * pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, ptrdiff_t length, bool validate); diff --git a/include/prism/internal/tokens.h b/include/prism/internal/tokens.h index 05651bf5c8..3a983e54ae 100644 --- a/include/prism/internal/tokens.h +++ b/include/prism/internal/tokens.h @@ -1,16 +1,10 @@ -/** - * @file internal/tokens.h - */ #ifndef PRISM_INTERNAL_TOKENS_H #define PRISM_INTERNAL_TOKENS_H #include "prism/ast.h" -/** +/* * Returns the human name of the given token type. - * - * @param token_type The token type to convert to a human name. - * @return The human name of the given token type. */ const char * pm_token_str(pm_token_type_t token_type); diff --git a/include/prism/line_offset_list.h b/include/prism/line_offset_list.h index e839862fea..848bc49139 100644 --- a/include/prism/line_offset_list.h +++ b/include/prism/line_offset_list.h @@ -54,7 +54,7 @@ typedef struct { * @param list The list to search. * @param cursor The offset to search for. * @param start_line The line to start counting from. - * @return The line and column of the given offset. + * @returns The line and column of the given offset. */ PRISM_EXPORTED_FUNCTION pm_line_column_t pm_line_offset_list_line_column(const pm_line_offset_list_t *list, uint32_t cursor, int32_t start_line) PRISM_NONNULL(1); diff --git a/include/prism/magic_comments.h b/include/prism/magic_comments.h index 4941e94885..6d47cda985 100644 --- a/include/prism/magic_comments.h +++ b/include/prism/magic_comments.h @@ -17,17 +17,17 @@ typedef struct pm_magic_comment_t pm_magic_comment_t; /** * Returns the location of the key associated with the given magic comment. * - * @param comment the magic comment whose key location we want to get - * @return the location of the key associated with the given magic comment + * @param magic_comment the magic comment whose key location we want to get + * @returns the location of the key associated with the given magic comment */ -PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_key(const pm_magic_comment_t *comment) PRISM_NONNULL(1); +PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_key(const pm_magic_comment_t *magic_comment) PRISM_NONNULL(1); /** * Returns the location of the value associated with the given magic comment. * - * @param comment the magic comment whose value location we want to get - * @return the location of the value associated with the given magic comment + * @param magic_comment the magic comment whose value location we want to get + * @returns the location of the value associated with the given magic comment */ -PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_value(const pm_magic_comment_t *comment) PRISM_NONNULL(1); +PRISM_EXPORTED_FUNCTION pm_location_t pm_magic_comment_value(const pm_magic_comment_t *magic_comment) PRISM_NONNULL(1); #endif diff --git a/include/prism/node.h b/include/prism/node.h index 7db4dcd891..75bc3c9b2d 100644 --- a/include/prism/node.h +++ b/include/prism/node.h @@ -22,7 +22,7 @@ * Returns a string representation of the given node type. * * @param node_type The node type to convert to a string. - * @return A string representation of the given node type. + * @returns A string representation of the given node type. */ PRISM_EXPORTED_FUNCTION const char * pm_node_type(pm_node_type_t node_type); diff --git a/include/prism/options.h b/include/prism/options.h index 10834f28e7..1c7281d599 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -110,10 +110,8 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20; * Allocate a new options struct. If the options struct cannot be allocated, * this function aborts the process. * - * @return A new options struct with default values. It is the responsibility of - * the caller to free this struct using pm_options_free(). - * - * \public \memberof pm_options + * @returns A new options struct with default values. It is the responsibility + * of the caller to free this struct using pm_options_free(). */ PRISM_EXPORTED_FUNCTION pm_options_t * pm_options_new(void) PRISM_NODISCARD; @@ -121,8 +119,6 @@ PRISM_EXPORTED_FUNCTION pm_options_t * pm_options_new(void) PRISM_NODISCARD; * Free both the held memory of the given options struct and the struct itself. * * @param options The options struct to free. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options) PRISM_NONNULL(1); @@ -133,8 +129,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options) PRISM_NONNUL * @param shebang_callback The shebang callback to set. * @param shebang_callback_data Any additional data that should be passed along * to the callback. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data) PRISM_NONNULL(1); @@ -142,9 +136,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *optio * Get the filepath option on the given options struct. * * @param options The options struct to get the filepath from. - * @return The filepath. - * - * \public \memberof pm_options + * @returns The filepath. */ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath(const pm_options_t *options) PRISM_NONNULL(1); @@ -153,8 +145,6 @@ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_filepath(const pm_options * * @param options The options struct to set the filepath on. * @param filepath The filepath to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath) PRISM_NONNULL(1); @@ -163,8 +153,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, cons * * @param options The options struct to set the line on. * @param line The line to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t line) PRISM_NONNULL(1); @@ -173,8 +161,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t * * @param options The options struct to set the encoding on. * @param encoding The encoding to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding) PRISM_NONNULL(1); @@ -183,8 +169,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, cons * * @param options The options struct to set the encoding_locked value on. * @param encoding_locked The encoding_locked value to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) PRISM_NONNULL(1); @@ -193,8 +177,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *option * * @param options The options struct to set the frozen string literal value on. * @param frozen_string_literal The frozen string literal value to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal) PRISM_NONNULL(1); @@ -203,8 +185,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t * * * @param options The options struct to set the command line option on. * @param command_line The command_line value to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line) PRISM_NONNULL(1); @@ -216,9 +196,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, * @param options The options struct to set the version on. * @param version The version to set. * @param length The length of the version string. - * @return Whether or not the version was parsed successfully. - * - * \public \memberof pm_options + * @returns Whether or not the version was parsed successfully. */ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length) PRISM_NONNULL(1); @@ -227,8 +205,6 @@ PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const * Ruby that prism supports. * * @param options The options struct to set the version on. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_version_set_lowest(pm_options_t *options) PRISM_NONNULL(1); @@ -237,8 +213,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_version_set_lowest(pm_options_t *options * Ruby that prism supports. * * @param options The options struct to set the version on. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_version_set_highest(pm_options_t *options) PRISM_NONNULL(1); @@ -247,8 +221,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_version_set_highest(pm_options_t *option * * @param options The options struct to set the main script value on. * @param main_script The main script value to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, bool main_script) PRISM_NONNULL(1); @@ -257,8 +229,6 @@ PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, b * * @param options The options struct to set the partial script value on. * @param partial_script The partial script value to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script) PRISM_NONNULL(1); @@ -266,8 +236,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options * Get the freeze option on the given options struct. * * @param options The options struct to get the freeze value from. - * - * \public \memberof pm_options + * @returns The freeze value. */ PRISM_EXPORTED_FUNCTION bool pm_options_freeze(const pm_options_t *options) PRISM_NONNULL(1); @@ -276,8 +245,6 @@ PRISM_EXPORTED_FUNCTION bool pm_options_freeze(const pm_options_t *options) PRIS * * @param options The options struct to set the freeze value on. * @param freeze The freeze value to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool freeze) PRISM_NONNULL(1); @@ -286,9 +253,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool f * * @param options The options struct to initialize the scopes array on. * @param scopes_count The number of scopes to allocate. - * @return Whether or not the scopes array was initialized successfully. - * - * \public \memberof pm_options + * @returns Whether or not the scopes array was initialized successfully. */ PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count) PRISM_NONNULL(1); @@ -298,9 +263,7 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_ * * @param options The options struct to get the scope from. * @param index The index of the scope to get. - * @return A constant pointer to the scope at the given index. - * - * \public \memberof pm_options + * @returns A constant pointer to the scope at the given index. */ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope(const pm_options_t *options, size_t index) PRISM_NONNULL(1); @@ -310,9 +273,7 @@ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope(const pm_opt * * @param options The options struct to get the scope from. * @param index The index of the scope to get. - * @return A mutable pointer to the scope at the given index. - * - * \public \memberof pm_options + * @returns A mutable pointer to the scope at the given index. */ PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_mut(pm_options_t *options, size_t index) PRISM_NONNULL(1); @@ -323,8 +284,6 @@ PRISM_EXPORTED_FUNCTION pm_options_scope_t * pm_options_scope_mut(pm_options_t * * * @param scope The scope struct to initialize. * @param locals_count The number of locals to allocate. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) PRISM_NONNULL(1); @@ -334,9 +293,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_scope_init(pm_options_scope_t *scope, si * * @param scope The scope struct to get the local from. * @param index The index of the local to get. - * @return A constant pointer to the local at the given index. - * - * \public \memberof pm_options + * @returns A constant pointer to the local at the given index. */ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local(const pm_options_scope_t *scope, size_t index) PRISM_NONNULL(1); @@ -346,9 +303,7 @@ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local(const pm_opti * * @param scope The scope struct to get the local from. * @param index The index of the local to get. - * @return A mutable pointer to the local at the given index. - * - * \public \memberof pm_options + * @returns A mutable pointer to the local at the given index. */ PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_mut(pm_options_scope_t *scope, size_t index) PRISM_NONNULL(1); @@ -357,8 +312,6 @@ PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_mut(pm_options_scop * * @param scope The scope struct to set the forwarding on. * @param forwarding The forwarding value to set. - * - * \public \memberof pm_options */ PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) PRISM_NONNULL(1); diff --git a/include/prism/parser.h b/include/prism/parser.h index 6d9efa6485..6bf0672a0e 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -30,10 +30,8 @@ typedef struct pm_parser_t pm_parser_t; * @param size The size of the source. * @param options The optional options to use when parsing. These options must * live for the whole lifetime of this parser. - * @return The initialized parser. It is the responsibility of the caller to + * @returns The initialized parser. It is the responsibility of the caller to * free the parser with `pm_parser_free()`. - * - * \public \memberof pm_parser */ PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options) PRISM_NODISCARD PRISM_NONNULL(1); @@ -41,8 +39,6 @@ PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uin * Free both the memory held by the given parser and the parser itself. * * @param parser The parser to free. - * - * \public \memberof pm_parser */ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser) PRISM_NONNULL(1); @@ -64,8 +60,6 @@ typedef void (*pm_lex_callback_t)(pm_parser_t *parser, pm_token_t *token, void * * * @param parser The parser to register the callback with. * @param callback The callback to register. - * - * \public \memberof pm_parser */ PRISM_EXPORTED_FUNCTION void pm_parser_encoding_changed_callback_set(pm_parser_t *parser, pm_encoding_changed_callback_t callback) PRISM_NONNULL(1); @@ -75,8 +69,6 @@ PRISM_EXPORTED_FUNCTION void pm_parser_encoding_changed_callback_set(pm_parser_t * @param parser The parser to register the callback with. * @param data The opaque data to pass to the callback when it is called. * @param callback The callback to register. - * - * \public \memberof pm_parser */ PRISM_EXPORTED_FUNCTION void pm_parser_lex_callback_set(pm_parser_t *parser, pm_lex_callback_t callback, void *data) PRISM_NONNULL(1); @@ -84,7 +76,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_lex_callback_set(pm_parser_t *parser, pm_ * Returns the opaque data that is passed to the lex callback when it is called. * * @param parser The parser whose lex callback data we want to get. - * @return The opaque data that is passed to the lex callback when it is called. + * @returns The opaque data that is passed to the lex callback when it is called. */ PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -92,7 +84,7 @@ PRISM_EXPORTED_FUNCTION void * pm_parser_lex_callback_data(const pm_parser_t *pa * Returns the raw pointer to the start of the source that is being parsed. * * @param parser the parser whose start pointer we want to get - * @return the raw pointer to the start of the source that is being parsed + * @returns the raw pointer to the start of the source that is being parsed */ PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_start(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -100,7 +92,7 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_start(const pm_parser_t *parse * Returns the raw pointer to the end of the source that is being parsed. * * @param parser the parser whose end pointer we want to get - * @return the raw pointer to the end of the source that is being parsed + * @returns the raw pointer to the end of the source that is being parsed */ PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_end(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -108,7 +100,7 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_parser_end(const pm_parser_t *parser) * Returns the line that the parser was considered to have started on. * * @param parser the parser whose start line we want to get - * @return the line that the parser was considered to have started on + * @returns the line that the parser was considered to have started on */ PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -116,7 +108,7 @@ PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser) * Returns the name of the encoding that is being used to parse the source. * * @param parser the parser whose encoding name we want to get - * @return the name of the encoding that is being used to parse the source + * @returns the name of the encoding that is being used to parse the source */ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -124,7 +116,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t * * Returns the line offsets that are associated with the given parser. * * @param parser the parser whose line offsets we want to get - * @return the line offsets that are associated with the given parser + * @returns the line offsets that are associated with the given parser */ PRISM_EXPORTED_FUNCTION const pm_line_offset_list_t * pm_parser_line_offsets(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -133,7 +125,7 @@ PRISM_EXPORTED_FUNCTION const pm_line_offset_list_t * pm_parser_line_offsets(con * given parser. * * @param parser the parser whose data location we want to get - * @return the location of the __DATA__ section that is associated with the + * @returns the location of the __DATA__ section that is associated with the * given parser. If it is unset, then the length will be set to 0. */ PRISM_EXPORTED_FUNCTION const pm_location_t * pm_parser_data_loc(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -143,7 +135,7 @@ PRISM_EXPORTED_FUNCTION const pm_location_t * pm_parser_data_loc(const pm_parser * valid if more input were appended, as opposed to being definitively invalid. * * @param parser the parser whose continuable status we want to get - * @return whether the given parser is continuable + * @returns whether the given parser is continuable */ PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -154,7 +146,7 @@ PRISM_EXPORTED_FUNCTION bool pm_parser_continuable(const pm_parser_t *parser) PR * niche use cases. Most consumers should avoid this function. * * @param parser the parser whose lex state we want to get - * @return the lex state of the parser + * @returns the lex state of the parser */ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -162,7 +154,7 @@ PRISM_EXPORTED_FUNCTION int pm_parser_lex_state(const pm_parser_t *parser) PRISM * Returns the number of comments associated with the given parser. * * @param parser the parser whose comments we want to get the size of - * @return the number of comments associated with the given parser + * @returns the number of comments associated with the given parser */ PRISM_EXPORTED_FUNCTION size_t pm_parser_comments_size(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -188,7 +180,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_comments_each(const pm_parser_t *parser, * Returns the number of magic comments associated with the given parser. * * @param parser the parser whose magic comments we want to get the size of - * @return the number of magic comments associated with the given parser + * @returns the number of magic comments associated with the given parser */ PRISM_EXPORTED_FUNCTION size_t pm_parser_magic_comments_size(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -214,7 +206,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_magic_comments_each(const pm_parser_t *pa * Returns the number of errors associated with the given parser. * * @param parser the parser whose errors we want to get the size of - * @return the number of errors associated with the given parser + * @returns the number of errors associated with the given parser */ PRISM_EXPORTED_FUNCTION size_t pm_parser_errors_size(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -222,7 +214,7 @@ PRISM_EXPORTED_FUNCTION size_t pm_parser_errors_size(const pm_parser_t *parser) * Returns the number of warnings associated with the given parser. * * @param parser the parser whose warnings we want to get the size of - * @return the number of warnings associated with the given parser + * @returns the number of warnings associated with the given parser */ PRISM_EXPORTED_FUNCTION size_t pm_parser_warnings_size(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -264,7 +256,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_warnings_each(const pm_parser_t *parser, * * @param parser the parser whose constant pool constants we want to get the * size of - * @return the number of constants in the constant pool associated with the + * @returns the number of constants in the constant pool associated with the * given parser */ PRISM_EXPORTED_FUNCTION size_t pm_parser_constants_size(const pm_parser_t *parser) PRISM_NONNULL(1); @@ -292,9 +284,7 @@ PRISM_EXPORTED_FUNCTION void pm_parser_constants_each(const pm_parser_t *parser, * Initiate the parser with the given parser. * * @param parser The parser to use. - * @return The AST representing the source. - * - * \public \memberof pm_parser + * @returns The AST representing the source. */ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser) PRISM_NONNULL(1); diff --git a/include/prism/serialize.h b/include/prism/serialize.h index ee94801f6e..dba54d75f1 100644 --- a/include/prism/serialize.h +++ b/include/prism/serialize.h @@ -88,7 +88,7 @@ PRISM_EXPORTED_FUNCTION void pm_serialize_parse_lex(pm_buffer_t *buffer, const u * @param source The source to parse. * @param size The size of the source. * @param data The optional data to pass to the parser. - * @return True if the source parses without errors or warnings. + * @returns True if the source parses without errors or warnings. */ PRISM_EXPORTED_FUNCTION bool pm_serialize_parse_success_p(const uint8_t *source, size_t size, const char *data) PRISM_NONNULL(1); diff --git a/include/prism/stream.h b/include/prism/stream.h index 47325d667d..7bb4271255 100644 --- a/include/prism/stream.h +++ b/include/prism/stream.h @@ -38,7 +38,7 @@ typedef int (pm_parse_stream_feof_t)(void *stream); * @param stream_fgets The function to use to read from the stream. * @param stream_feof The function to use to determine if the stream has hit eof. * @param options The optional options to use when parsing. - * @return The AST representing the source. + * @returns The AST representing the source. */ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) PRISM_NONNULL(1, 2, 3); diff --git a/include/prism/string_query.h b/include/prism/string_query.h index 406aa952a9..6ee1a9d9b6 100644 --- a/include/prism/string_query.h +++ b/include/prism/string_query.h @@ -33,7 +33,7 @@ typedef enum { * @param source The source to check. * @param length The length of the source. * @param encoding_name The name of the encoding of the source. - * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * @returns PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. */ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) PRISM_NONNULL(1, 3); @@ -44,7 +44,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *s * @param source The source to check. * @param length The length of the source. * @param encoding_name The name of the encoding of the source. - * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * @returns PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. */ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) PRISM_NONNULL(1, 3); @@ -55,7 +55,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t * @param source The source to check. * @param length The length of the source. * @param encoding_name The name of the encoding of the source. - * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if + * @returns PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid. */ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) PRISM_NONNULL(1, 3); diff --git a/include/prism/strings.h b/include/prism/strings.h index 48d3f9b0d9..55059eb307 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -45,7 +45,7 @@ typedef struct { * Returns the size of the pm_string_t struct. This is necessary to allocate the * correct amount of memory in the FFI backend. * - * @return The size of the pm_string_t struct. + * @returns The size of the pm_string_t struct. */ PRISM_EXPORTED_FUNCTION size_t pm_string_sizeof(void); @@ -93,9 +93,7 @@ typedef enum { * * @param string The string to initialize. * @param filepath The filepath to read. - * @return The success of the read, indicated by the value of the enum. - * - * \public \memberof pm_string_t + * @returns The success of the read, indicated by the value of the enum. */ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath) PRISM_NONNULL(1, 2); @@ -106,9 +104,7 @@ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_ * * @param string The string to initialize. * @param filepath The filepath to read. - * @return The success of the read, indicated by the value of the enum. - * - * \public \memberof pm_string_t + * @returns The success of the read, indicated by the value of the enum. */ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath) PRISM_NONNULL(1, 2); @@ -116,9 +112,7 @@ PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t * Returns the length associated with the string. * * @param string The string to get the length of. - * @return The length of the string. - * - * \public \memberof pm_string_t + * @returns The length of the string. */ PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string) PRISM_NONNULL(1); @@ -126,9 +120,7 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string) PRISM * Returns the start pointer associated with the string. * * @param string The string to get the start pointer of. - * @return The start pointer of the string. - * - * \public \memberof pm_string_t + * @returns The start pointer of the string. */ PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string) PRISM_NONNULL(1); @@ -136,8 +128,6 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *stri * Free the associated memory of the given string. * * @param string The string to free. - * - * \public \memberof pm_string_t */ PRISM_EXPORTED_FUNCTION void pm_string_cleanup(pm_string_t *string) PRISM_NONNULL(1); diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index e1b233918d..1909618fc1 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -51,7 +51,7 @@ typedef struct { * Returns a string representation of the given token type. * * @param token_type The type of the token to get the string representation of. - * @return A string representation of the given token type. This is meant for + * @returns A string representation of the given token type. This is meant for * debugging purposes and is not guaranteed to be stable across versions. */ PRISM_EXPORTED_FUNCTION const char * pm_token_type(pm_token_type_t token_type); @@ -262,7 +262,7 @@ typedef enum pm_<%= flag.human %> { <%- node.fields.each do |field| -%> * @param <%= field.name %> <%= field.comment ? Prism::Template::Doxygen.verbatim(field.comment.lines.first.strip) : "The #{field.name} field." %> <%- end -%> - * @return The newly allocated and initialized node. + * @returns The newly allocated and initialized node. */ PRISM_EXPORTED_FUNCTION pm_<%= node.human %>_t * pm_<%= node.human %>_new(pm_arena_t *arena, uint32_t node_id, pm_node_flags_t flags, pm_location_t location<%= params.empty? ? "" : ", #{params.join(", ")}" %>); <%- end -%> diff --git a/templates/include/prism/internal/diagnostic.h.erb b/templates/include/prism/internal/diagnostic.h.erb index fcbc2b6a70..ee44ff5382 100644 --- a/templates/include/prism/internal/diagnostic.h.erb +++ b/templates/include/prism/internal/diagnostic.h.erb @@ -1,8 +1,3 @@ -/** - * @file internal/diagnostic.h - * - * A list of diagnostics generated during parsing. - */ #ifndef PRISM_INTERNAL_DIAGNOSTIC_H #define PRISM_INTERNAL_DIAGNOSTIC_H @@ -11,7 +6,7 @@ #include "prism/arena.h" #include "prism/diagnostic.h" -/** +/* * The diagnostic IDs of all of the diagnostics, used to communicate the types * of errors between the parser and the user. */ @@ -27,51 +22,38 @@ typedef enum { <%- end -%> } pm_diagnostic_id_t; -/** +/* * This struct represents a diagnostic generated during parsing. */ struct pm_diagnostic_t { - /** The embedded base node. */ + /* The embedded base node. */ pm_list_node_t node; - /** The location of the diagnostic in the source. */ + /* The location of the diagnostic in the source. */ pm_location_t location; - /** The ID of the diagnostic. */ + /* The ID of the diagnostic. */ pm_diagnostic_id_t diag_id; - /** The message associated with the diagnostic. */ + /* The message associated with the diagnostic. */ const char *message; - /** + /* * The level of the diagnostic, see `pm_error_level_t` and * `pm_warning_level_t` for possible values. */ uint8_t level; }; -/** +/* * Append a diagnostic to the given list of diagnostics that is using shared * memory for its message. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param start The source offset of the start of the diagnostic. - * @param length The length of the diagnostic. - * @param diag_id The diagnostic ID. */ void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id); -/** +/* * Append a diagnostic to the given list of diagnostics that is using a format * string for its message. - * - * @param arena The arena to allocate from. - * @param list The list to append to. - * @param start The source offset of the start of the diagnostic. - * @param length The length of the diagnostic. - * @param diag_id The diagnostic ID. - * @param ... The arguments to the format string for the message. */ void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...); diff --git a/templates/template.rb b/templates/template.rb index 78c8ac1954..8f7734dd43 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -53,7 +53,7 @@ def self.escape(value) module Doxygen # Similar to /verbatim ... /endverbatim but doesn't wrap the result in a code block. def self.verbatim(value) - value.gsub(/[\.*%!`#<>_+-]/, '\\\\\0') + value.gsub(/[*%!`#<>_+@-]/, '\\\\\0') end end From b66fbf9f854a31145cbf689754869f51140c0b79 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 14:54:23 -0400 Subject: [PATCH 229/289] Clean up rake build --- prism.gemspec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/prism.gemspec b/prism.gemspec index 4c9b685427..5db6327813 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -55,6 +55,8 @@ Gem::Specification.new do |spec| "include/prism/compiler/force_inline.h", "include/prism/compiler/format.h", "include/prism/compiler/inline.h", + "include/prism/compiler/nodiscard.h", + "include/prism/compiler/nonnull.h", "include/prism/compiler/unused.h", "include/prism/internal/allocator.h", "include/prism/internal/allocator_debug.h", @@ -81,6 +83,7 @@ Gem::Specification.new do |spec| "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", "include/prism/internal/strpbrk.h", + "include/prism/internal/tokens.h", "include/prism/arena.h", "include/prism/ast.h", "include/prism/buffer.h", @@ -89,12 +92,15 @@ Gem::Specification.new do |spec| "include/prism/diagnostic.h", "include/prism/excludes.h", "include/prism/integer.h", + "include/prism/json.h", "include/prism/line_offset_list.h", "include/prism/magic_comments.h", "include/prism/node.h", "include/prism/options.h", "include/prism/parser.h", "include/prism/prettyprint.h", + "include/prism/serialize.h", + "include/prism/stream.h", "include/prism/string_query.h", "include/prism/strings.h", "include/prism/version.h", @@ -193,6 +199,7 @@ Gem::Specification.new do |spec| "src/diagnostic.c", "src/encoding.c", "src/integer.c", + "src/json.c", "src/line_offset_list.c", "src/list.c", "src/memchr.c", From 26731ccc92962e13de90c2cc029d78e88e11c89d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 15:05:18 -0400 Subject: [PATCH 230/289] Make sure we have at least one declaration in TUs --- include/prism/compiler/unused.h | 4 ++-- src/encoding.c | 2 +- src/json.c | 9 ++++++++- src/prism.c | 4 ++-- src/static_literals.c | 6 +++--- src/strpbrk.c | 2 +- templates/src/prettyprint.c.erb | 9 ++++++++- templates/src/serialize.c.erb | 9 ++++++++- 8 files changed, 33 insertions(+), 12 deletions(-) diff --git a/include/prism/compiler/unused.h b/include/prism/compiler/unused.h index fced007f9b..6a9e125dde 100644 --- a/include/prism/compiler/unused.h +++ b/include/prism/compiler/unused.h @@ -10,9 +10,9 @@ * compiler-agnostic way. */ #if defined(__GNUC__) -# define PRISM_ATTRIBUTE_UNUSED __attribute__((unused)) +# define PRISM_UNUSED __attribute__((unused)) #else -# define PRISM_ATTRIBUTE_UNUSED +# define PRISM_UNUSED #endif #endif diff --git a/src/encoding.c b/src/encoding.c index 0425a2c5b8..c9c2e13056 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -4094,7 +4094,7 @@ pm_encoding_ascii_isupper_char(const uint8_t *b, ptrdiff_t n) { * matter what the codepoint, so this function is shared between them. */ static size_t -pm_encoding_single_char_width(PRISM_ATTRIBUTE_UNUSED const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) { +pm_encoding_single_char_width(PRISM_UNUSED const uint8_t *b, PRISM_UNUSED ptrdiff_t n) { return 1; } diff --git a/src/json.c b/src/json.c index 0d72ca8368..57e3fc07df 100644 --- a/src/json.c +++ b/src/json.c @@ -11,7 +11,14 @@ /* We optionally support dumping to JSON. For systems that don not want or need * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. */ -#ifndef PRISM_EXCLUDE_JSON +#ifdef PRISM_EXCLUDE_JSON + +#include "prism/compiler/unused.h" + +void +pm_dump_json(PRISM_UNUSED pm_buffer_t *buffer, PRISM_UNUSED const pm_parser_t *parser, PRISM_UNUSED const pm_node_t *node) {} + +#else #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" diff --git a/src/prism.c b/src/prism.c index 18249acc71..b6afa8bb15 100644 --- a/src/prism.c +++ b/src/prism.c @@ -454,7 +454,7 @@ lex_state_set(pm_parser_t *parser, pm_lex_state_t state) { #endif #if PM_DEBUG_LOGGING -PRISM_ATTRIBUTE_UNUSED static void +PRISM_UNUSED static void debug_state(pm_parser_t *parser) { fprintf(stderr, "STATE: "); bool first = true; @@ -1073,7 +1073,7 @@ pm_locals_reads(pm_locals_t *locals, pm_constant_id_t name) { * written but not read in certain contexts. */ static void -pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals, pm_constant_id_list_t *list, bool toplevel) { +pm_locals_order(pm_parser_t *parser, pm_locals_t *locals, pm_constant_id_list_t *list, bool toplevel) { pm_constant_id_list_init_capacity(parser->arena, list, locals->size); // If we're still below the threshold for switching to a hash, then we only diff --git a/src/static_literals.c b/src/static_literals.c index c66fa7724a..0a8ef62b2c 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -285,7 +285,7 @@ pm_compare_integer_nodes(const pm_static_literals_metadata_t *metadata, const pm * A comparison function for comparing two FloatNode instances. */ static int -pm_compare_float_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) { +pm_compare_float_nodes(PRISM_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) { const double left_value = ((const pm_float_node_t *) left)->value; const double right_value = ((const pm_float_node_t *) right)->value; return PM_NUMERIC_COMPARISON(left_value, right_value); @@ -344,7 +344,7 @@ pm_string_value(const pm_node_t *node) { * A comparison function for comparing two nodes that have attached strings. */ static int -pm_compare_string_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) { +pm_compare_string_nodes(PRISM_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) { const pm_string_t *left_string = pm_string_value(left); const pm_string_t *right_string = pm_string_value(right); return pm_string_compare(left_string, right_string); @@ -354,7 +354,7 @@ pm_compare_string_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata * A comparison function for comparing two RegularExpressionNode instances. */ static int -pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) { +pm_compare_regular_expression_nodes(PRISM_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) { const pm_regular_expression_node_t *left_regexp = (const pm_regular_expression_node_t *) left; const pm_regular_expression_node_t *right_regexp = (const pm_regular_expression_node_t *) right; diff --git a/src/strpbrk.c b/src/strpbrk.c index 41ab8eec3e..383707eb72 100644 --- a/src/strpbrk.c +++ b/src/strpbrk.c @@ -257,7 +257,7 @@ scan_strpbrk_ascii(pm_parser_t *parser, const uint8_t *source, size_t maximum, c #else static PRISM_INLINE bool -scan_strpbrk_ascii(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, PRISM_ATTRIBUTE_UNUSED const uint8_t *source, PRISM_ATTRIBUTE_UNUSED size_t maximum, PRISM_ATTRIBUTE_UNUSED const uint8_t *charset, size_t *index) { +scan_strpbrk_ascii(PRISM_UNUSED pm_parser_t *parser, PRISM_UNUSED const uint8_t *source, PRISM_UNUSED size_t maximum, PRISM_UNUSED const uint8_t *charset, size_t *index) { *index = 0; return false; } diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index cede4b9d02..9992f51096 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -4,7 +4,14 @@ /* We optionally support pretty printing nodes. For systems that don't want or * need this functionality, it can be turned off with the * PRISM_EXCLUDE_PRETTYPRINT define. */ -#ifndef PRISM_EXCLUDE_PRETTYPRINT +#ifdef PRISM_EXCLUDE_PRETTYPRINT + +#include "prism/compiler/unused.h" + +void +pm_prettyprint(PRISM_UNUSED pm_buffer_t *buffer, PRISM_UNUSED const pm_parser_t *parser, PRISM_UNUSED const pm_node_t *node) {} + +#else #include "prism/compiler/inline.h" #include "prism/internal/buffer.h" diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 0263ef56cc..8c28cb89fc 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -3,7 +3,14 @@ /* We optionally support serializing to a binary string. For systems that do not * want or need this functionality, it can be turned off with the * PRISM_EXCLUDE_SERIALIZATION define. */ -#ifndef PRISM_EXCLUDE_SERIALIZATION +#ifdef PRISM_EXCLUDE_SERIALIZATION + +#include "prism/compiler/unused.h" + +void +pm_serialize_lex(PRISM_UNUSED pm_buffer_t *buffer, PRISM_UNUSED const uint8_t *source, PRISM_UNUSED size_t size, PRISM_UNUSED const char *data) {} + +#else #include "prism/compiler/inline.h" From cab3fd8c03d1334069fe76f170095c93a47189ff Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 15:24:08 -0400 Subject: [PATCH 231/289] Fix up rust side of the build --- include/prism/parser.h | 19 ++++ rust/ruby-prism-sys/build/main.rs | 48 ++++++++-- rust/ruby-prism-sys/tests/node_tests.rs | 24 ++--- rust/ruby-prism-sys/tests/parser_tests.rs | 95 +++++++++---------- rust/ruby-prism-sys/tests/utils_tests.rs | 4 +- rust/ruby-prism/build.rs | 7 +- rust/ruby-prism/src/lib.rs | 42 ++++---- rust/ruby-prism/src/node.rs | 19 ++-- rust/ruby-prism/src/parse_result/comments.rs | 86 ++++++++--------- .../src/parse_result/diagnostics.rs | 48 +++++----- rust/ruby-prism/src/parse_result/mod.rs | 81 ++++++++++------ src/parser.c | 17 ++++ 12 files changed, 292 insertions(+), 198 deletions(-) diff --git a/include/prism/parser.h b/include/prism/parser.h index 6bf0672a0e..78e6c189ac 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -112,6 +112,15 @@ PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser) */ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser) PRISM_NONNULL(1); +/** + * Returns the frozen string literal value of the parser, as determined by the + * frozen_string_literal magic comment or the option set on the parser. + * + * @param parser the parser whose frozen string literal value we want to get + * @returns -1 if disabled, 0 if unset, 1 if enabled + */ +PRISM_EXPORTED_FUNCTION int8_t pm_parser_frozen_string_literal(const pm_parser_t *parser) PRISM_NONNULL(1); + /** * Returns the line offsets that are associated with the given parser. * @@ -280,6 +289,16 @@ typedef void (*pm_constant_callback_t)(const pm_constant_t *constant, void *data */ PRISM_EXPORTED_FUNCTION void pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callback, void *data) PRISM_NONNULL(1); +/** + * Returns a pointer to the constant at the given id in the constant pool + * associated with the given parser. + * + * @param parser the parser whose constant pool we want to look up from + * @param constant_id the id of the constant to look up (1-based) + * @returns a pointer to the constant at the given id + */ +PRISM_EXPORTED_FUNCTION const pm_constant_t * pm_parser_constant(const pm_parser_t *parser, pm_constant_id_t constant_id) PRISM_NONNULL(1); + /** * Initiate the parser with the given parser. * diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index bf9c8e2db7..722da06970 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -128,24 +128,42 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .sort_semantically(true) // Structs .allowlist_type("pm_comment_t") + .allowlist_type("pm_constant_t") .allowlist_type("pm_diagnostic_t") - .allowlist_type("pm_list_t") + .allowlist_type("pm_error_level_t") + .allowlist_type("pm_line_column_t") + .allowlist_type("pm_line_offset_list_t") + .allowlist_type("pm_location_t") .allowlist_type("pm_magic_comment_t") .allowlist_type("pm_node_t") .allowlist_type("pm_node_type") .allowlist_type("pm_options_t") .allowlist_type("pm_options_scope_t") - .allowlist_type("pm_parser_t") .allowlist_type("pm_string_t") + .allowlist_type("pm_warning_level_t") .allowlist_type(r"^pm_\w+_node_t") .allowlist_type(r"^pm_\w+_flags") // Enums .rustified_non_exhaustive_enum("pm_comment_type_t") + .rustified_non_exhaustive_enum("pm_error_level_t") .rustified_non_exhaustive_enum(r"pm_\w+_flags") .rustified_non_exhaustive_enum("pm_node_type") + .rustified_non_exhaustive_enum("pm_warning_level_t") // Functions - .allowlist_function("pm_arena_cleanup") + .allowlist_function("pm_arena_free") + .allowlist_function("pm_arena_new") + .allowlist_function("pm_comment_location") + .allowlist_function("pm_comment_type") + .allowlist_function("pm_constant_length") + .allowlist_function("pm_constant_start") + .allowlist_function("pm_diagnostic_error_level") + .allowlist_function("pm_diagnostic_location") + .allowlist_function("pm_diagnostic_message") + .allowlist_function("pm_diagnostic_type") + .allowlist_function("pm_diagnostic_warning_level") .allowlist_function("pm_line_offset_list_line_column") + .allowlist_function("pm_magic_comment_key") + .allowlist_function("pm_magic_comment_value") .allowlist_function("pm_options_command_line_set") .allowlist_function("pm_options_encoding_locked_set") .allowlist_function("pm_options_encoding_set") @@ -157,17 +175,33 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_function("pm_options_new") .allowlist_function("pm_options_partial_script_set") .allowlist_function("pm_options_scope_forwarding_set") - .allowlist_function("pm_options_scope_mut") .allowlist_function("pm_options_scope_init") .allowlist_function("pm_options_scope_local_mut") + .allowlist_function("pm_options_scope_mut") .allowlist_function("pm_options_scopes_init") .allowlist_function("pm_options_version_set") .allowlist_function("pm_parse") - .allowlist_function("pm_parser_cleanup") - .allowlist_function("pm_parser_init") + .allowlist_function("pm_parser_comments_each") + .allowlist_function("pm_parser_comments_size") + .allowlist_function("pm_parser_constant") + .allowlist_function("pm_parser_constants_each") + .allowlist_function("pm_parser_constants_size") + .allowlist_function("pm_parser_data_loc") + .allowlist_function("pm_parser_errors_each") + .allowlist_function("pm_parser_errors_size") + .allowlist_function("pm_parser_free") + .allowlist_function("pm_parser_frozen_string_literal") + .allowlist_function("pm_parser_line_offsets") + .allowlist_function("pm_parser_magic_comments_each") + .allowlist_function("pm_parser_magic_comments_size") + .allowlist_function("pm_parser_new") + .allowlist_function("pm_parser_start") + .allowlist_function("pm_parser_start_line") + .allowlist_function("pm_parser_warnings_each") + .allowlist_function("pm_parser_warnings_size") .allowlist_function("pm_size_to_native") - .allowlist_function("pm_string_constant_init") .allowlist_function("pm_string_cleanup") + .allowlist_function("pm_string_constant_init") .allowlist_function("pm_string_length") .allowlist_function("pm_string_source") .allowlist_function("pm_version") diff --git a/rust/ruby-prism-sys/tests/node_tests.rs b/rust/ruby-prism-sys/tests/node_tests.rs index 73c8c04d30..31040668b7 100644 --- a/rust/ruby-prism-sys/tests/node_tests.rs +++ b/rust/ruby-prism-sys/tests/node_tests.rs @@ -1,29 +1,25 @@ -use std::{ffi::CString, mem::MaybeUninit}; +use std::ffi::CString; -use ruby_prism_sys::{pm_arena_cleanup, pm_arena_t, pm_node_type}; -use ruby_prism_sys::{pm_parse, pm_parser_cleanup, pm_parser_init, pm_parser_t}; +use ruby_prism_sys::{pm_arena_free, pm_arena_new, pm_node_type}; +use ruby_prism_sys::{pm_parse, pm_parser_free, pm_parser_new}; #[test] fn node_test() { - let mut arena = MaybeUninit::::zeroed(); - let mut parser = MaybeUninit::::uninit(); let code = CString::new("class Foo; end").unwrap(); unsafe { - pm_parser_init( - arena.as_mut_ptr(), - parser.as_mut_ptr(), + let arena = pm_arena_new(); + let parser = pm_parser_new( + arena, code.as_ptr().cast::(), code.as_bytes().len(), std::ptr::null(), ); + let node = pm_parse(parser); - let parser = parser.assume_init_mut(); - let parsed_node = pm_parse(parser); + assert_eq!((*node).type_, pm_node_type::PM_PROGRAM_NODE as u16); - assert_eq!((*parsed_node).type_, pm_node_type::PM_PROGRAM_NODE as u16); - - pm_parser_cleanup(parser); - pm_arena_cleanup(arena.as_mut_ptr()); + pm_parser_free(parser); + pm_arena_free(arena); } } diff --git a/rust/ruby-prism-sys/tests/parser_tests.rs b/rust/ruby-prism-sys/tests/parser_tests.rs index 7efb374ae8..0cfc234de2 100644 --- a/rust/ruby-prism-sys/tests/parser_tests.rs +++ b/rust/ruby-prism-sys/tests/parser_tests.rs @@ -1,14 +1,24 @@ -use std::{ - ffi::{CStr, CString}, - mem::MaybeUninit, - path::Path, -}; +use std::ffi::{CStr, CString}; +use std::path::Path; use ruby_prism_sys::{ - pm_arena_cleanup, pm_arena_t, pm_comment_t, pm_comment_type_t, pm_diagnostic_t, pm_parse, pm_parser_cleanup, - pm_parser_init, pm_parser_t, + pm_arena_free, pm_arena_new, pm_comment_location, pm_comment_type, pm_comment_type_t, pm_diagnostic_location, + pm_diagnostic_message, pm_parse, pm_parser_comments_each, pm_parser_errors_each, pm_parser_free, pm_parser_new, }; +unsafe extern "C" fn collect_comment(comment: *const ruby_prism_sys::pm_comment_t, data: *mut std::ffi::c_void) { + let vec = &mut *(data.cast::>()); + vec.push(comment); +} + +unsafe extern "C" fn collect_diagnostic( + diagnostic: *const ruby_prism_sys::pm_diagnostic_t, + data: *mut std::ffi::c_void, +) { + let vec = &mut *(data.cast::>()); + vec.push(diagnostic); +} + fn ruby_file_contents() -> (CString, usize) { let rust_path = Path::new(env!("CARGO_MANIFEST_DIR")); let ruby_file_path = rust_path.join("../../lib/prism.rb").canonicalize().unwrap(); @@ -22,86 +32,75 @@ fn ruby_file_contents() -> (CString, usize) { fn init_test() { let (ruby_file_contents, len) = ruby_file_contents(); let source = ruby_file_contents.as_ptr().cast::(); - let mut arena = MaybeUninit::::zeroed(); - let mut parser = MaybeUninit::::uninit(); unsafe { - pm_parser_init(arena.as_mut_ptr(), parser.as_mut_ptr(), source, len, std::ptr::null()); - let parser = parser.assume_init_mut(); + let arena = pm_arena_new(); + let parser = pm_parser_new(arena, source, len, std::ptr::null()); - pm_parser_cleanup(parser); - pm_arena_cleanup(arena.as_mut_ptr()); + pm_parser_free(parser); + pm_arena_free(arena); } } #[test] fn comments_test() { let source = CString::new("# Meow!").unwrap(); - let mut arena = MaybeUninit::::zeroed(); - let mut parser = MaybeUninit::::uninit(); unsafe { - pm_parser_init( - arena.as_mut_ptr(), - parser.as_mut_ptr(), + let arena = pm_arena_new(); + let parser = pm_parser_new( + arena, source.as_ptr().cast::(), source.as_bytes().len(), std::ptr::null(), ); - let parser = parser.assume_init_mut(); let _node = pm_parse(parser); - let comment_list = &parser.comment_list; - let comment = comment_list.head as *const pm_comment_t; - assert_eq!((*comment).type_, pm_comment_type_t::PM_COMMENT_INLINE); + let mut comments: Vec<*const ruby_prism_sys::pm_comment_t> = Vec::new(); + pm_parser_comments_each(parser, Some(collect_comment), (&raw mut comments).cast()); + + assert_eq!(comments.len(), 1); + let comment = comments[0]; + assert_eq!(pm_comment_type(comment), pm_comment_type_t::PM_COMMENT_INLINE); - let location = { - let start = (*comment).location.start; - let end = (*comment).location.start + (*comment).location.length; - start..end - }; - assert_eq!(location, 0..7); + let location = pm_comment_location(comment); + assert_eq!(location.start..location.start + location.length, 0..7); - pm_parser_cleanup(parser); - pm_arena_cleanup(arena.as_mut_ptr()); + pm_parser_free(parser); + pm_arena_free(arena); } } #[test] fn diagnostics_test() { let source = CString::new("class Foo;").unwrap(); - let mut arena = MaybeUninit::::zeroed(); - let mut parser = MaybeUninit::::uninit(); unsafe { - pm_parser_init( - arena.as_mut_ptr(), - parser.as_mut_ptr(), + let arena = pm_arena_new(); + let parser = pm_parser_new( + arena, source.as_ptr().cast::(), source.as_bytes().len(), std::ptr::null(), ); - let parser = parser.assume_init_mut(); let _node = pm_parse(parser); - let error_list = &parser.error_list; - assert!(!error_list.head.is_null()); + let mut errors: Vec<*const ruby_prism_sys::pm_diagnostic_t> = Vec::new(); + pm_parser_errors_each(parser, Some(collect_diagnostic), (&raw mut errors).cast()); + + assert!(!errors.is_empty()); + let error = errors[0]; - let error = error_list.head as *const pm_diagnostic_t; - let message = CStr::from_ptr((*error).message); + let message = CStr::from_ptr(pm_diagnostic_message(error)); assert_eq!( message.to_string_lossy(), "unexpected end-of-input, assuming it is closing the parent top level context" ); - let location = { - let start = (*error).location.start; - let end = (*error).location.start + (*error).location.length; - start..end - }; - assert_eq!(location, 10..10); + let location = pm_diagnostic_location(error); + assert_eq!(location.start..location.start + location.length, 10..10); - pm_parser_cleanup(parser); - pm_arena_cleanup(arena.as_mut_ptr()); + pm_parser_free(parser); + pm_arena_free(arena); } } diff --git a/rust/ruby-prism-sys/tests/utils_tests.rs b/rust/ruby-prism-sys/tests/utils_tests.rs index 20cce8ea2e..9b9db446c2 100644 --- a/rust/ruby-prism-sys/tests/utils_tests.rs +++ b/rust/ruby-prism-sys/tests/utils_tests.rs @@ -14,8 +14,8 @@ fn version_test() { mod string { use ruby_prism_sys::{ - pm_string_cleanup, pm_string_length, pm_string_source, pm_string_t, pm_string_t__bindgen_ty_1, PM_STRING_CONSTANT, - PM_STRING_MAPPED, PM_STRING_OWNED, PM_STRING_SHARED, + pm_string_cleanup, pm_string_length, pm_string_source, pm_string_t, pm_string_t__bindgen_ty_1, + PM_STRING_CONSTANT, PM_STRING_MAPPED, PM_STRING_OWNED, PM_STRING_SHARED, }; use super::*; diff --git a/rust/ruby-prism/build.rs b/rust/ruby-prism/build.rs index 8faad957ab..1a3bb45a17 100644 --- a/rust/ruby-prism/build.rs +++ b/rust/ruby-prism/build.rs @@ -235,7 +235,7 @@ fn write_node(file: &mut File, flags: &[Flags], node: &Node) -> Result<(), Box {{", node.name)?; writeln!(file, " /// The pointer to the parser this node came from.")?; - writeln!(file, " parser: NonNull,")?; + writeln!(file, " parser: *const pm_parser_t,")?; writeln!(file)?; writeln!(file, " /// The raw pointer to the node allocated by prism.")?; writeln!(file, " pointer: *mut pm{}_t,", struct_name(&node.name))?; @@ -554,7 +554,6 @@ fn write_bindings(config: &Config) -> Result<(), Box> { file, r" use std::marker::PhantomData; -use std::ptr::NonNull; #[allow(clippy::wildcard_imports)] use ruby_prism_sys::*; @@ -581,7 +580,7 @@ use crate::{{ConstantId, ConstantList, Integer, Location, NodeList}}; writeln!(file, " /// The `{}` node", node.name)?; writeln!(file, " {} {{", node.name)?; writeln!(file, " /// The pointer to the associated parser this node came from.")?; - writeln!(file, " parser: NonNull,")?; + writeln!(file, " parser: *const pm_parser_t,")?; writeln!(file)?; writeln!(file, " /// The raw pointer to the node allocated by prism.")?; writeln!(file, " pointer: *mut pm{}_t,", struct_name(&node.name))?; @@ -606,7 +605,7 @@ impl<'pr> Node<'pr> {{ /// #[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::cast_ptr_alignment)] - pub(crate) fn new(parser: NonNull, node: *mut pm_node_t) -> Self {{ + pub(crate) fn new(parser: *const pm_parser_t, node: *mut pm_node_t) -> Self {{ match unsafe {{ (*node).type_ }} {{" )?; diff --git a/rust/ruby-prism/src/lib.rs b/rust/ruby-prism/src/lib.rs index b841af7807..6337957d20 100644 --- a/rust/ruby-prism/src/lib.rs +++ b/rust/ruby-prism/src/lib.rs @@ -8,6 +8,8 @@ // that doesn't follow the clippy rules. We don't want to see those warnings. #[allow(clippy::too_many_lines, clippy::use_self)] mod bindings { + use std::ptr::NonNull; + // In `build.rs`, we generate bindings based on the config.yml file. Here is // where we pull in those bindings and make them part of our library. include!(concat!(env!("OUT_DIR"), "/bindings.rs")); @@ -18,7 +20,6 @@ mod node_ext; mod parse_result; use std::ffi::CString; -use std::mem::MaybeUninit; use std::ptr::NonNull; pub use self::bindings::*; @@ -27,8 +28,8 @@ pub use self::node_ext::{ConstantPathError, FullName}; pub use self::parse_result::{Comment, CommentType, Comments, Diagnostic, Diagnostics, Location, MagicComment, MagicComments, ParseResult}; use ruby_prism_sys::{ - pm_arena_t, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_free, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_new, pm_options_partial_script_set, pm_options_scope_forwarding_set, - pm_options_scope_mut, pm_options_scope_init, pm_options_scope_local_mut, pm_options_scopes_init, pm_options_t, pm_options_version_set, pm_parse, pm_parser_init, pm_parser_t, pm_string_constant_init, + pm_arena_new, pm_options_command_line_set, pm_options_encoding_locked_set, pm_options_encoding_set, pm_options_filepath_set, pm_options_free, pm_options_frozen_string_literal_set, pm_options_line_set, pm_options_main_script_set, pm_options_new, pm_options_partial_script_set, + pm_options_scope_forwarding_set, pm_options_scope_init, pm_options_scope_local_mut, pm_options_scope_mut, pm_options_scopes_init, pm_options_t, pm_options_version_set, pm_parse, pm_parser_new, pm_string_constant_init, }; /// The version of Ruby syntax to parse with. @@ -51,11 +52,21 @@ impl Version { /// `Latest` passes `NULL` to get the default behavior. unsafe fn set_on(self, opts: *mut pm_options_t) { match self { - Version::Latest => { pm_options_version_set(opts, std::ptr::null(), 0); }, - Version::CRuby3_3 => { pm_options_version_set(opts, c"3.3".as_ptr(), 3); }, - Version::CRuby3_4 => { pm_options_version_set(opts, c"3.4".as_ptr(), 3); }, - Version::CRuby3_5 => { pm_options_version_set(opts, c"3.5".as_ptr(), 3); }, - Version::CRuby4_1 => { pm_options_version_set(opts, c"4.1".as_ptr(), 3); }, + Self::Latest => { + pm_options_version_set(opts, std::ptr::null(), 0); + }, + Self::CRuby3_3 => { + pm_options_version_set(opts, c"3.3".as_ptr(), 3); + }, + Self::CRuby3_4 => { + pm_options_version_set(opts, c"3.4".as_ptr(), 3); + }, + Self::CRuby3_5 => { + pm_options_version_set(opts, c"3.5".as_ptr(), 3); + }, + Self::CRuby4_1 => { + pm_options_version_set(opts, c"4.1".as_ptr(), 3); + }, } } } @@ -335,18 +346,9 @@ impl Drop for ParseOptions { /// /// `options` must be a valid pointer to a `pm_options_t` or null. unsafe fn parse_impl(source: &[u8], options: *const pm_options_t) -> ParseResult<'_> { - let mut arena = Box::new(MaybeUninit::::zeroed().assume_init()); - let uninit = Box::new(MaybeUninit::::uninit()); - let uninit = Box::into_raw(uninit); - - pm_parser_init(arena.as_mut(), (*uninit).as_mut_ptr(), source.as_ptr(), source.len(), options); - - let parser = (*uninit).assume_init_mut(); - let parser = NonNull::new_unchecked(parser); - - let node = pm_parse(parser.as_ptr()); - let node = NonNull::new_unchecked(node); - + let arena = pm_arena_new(); + let parser = pm_parser_new(arena, source.as_ptr(), source.len(), options); + let node = NonNull::new_unchecked(pm_parse(parser)); ParseResult::new(source, arena, parser, node) } diff --git a/rust/ruby-prism/src/node.rs b/rust/ruby-prism/src/node.rs index cf44a119dc..e797c94b2e 100644 --- a/rust/ruby-prism/src/node.rs +++ b/rust/ruby-prism/src/node.rs @@ -18,7 +18,7 @@ use crate::Node; /// An iterator over the nodes in a list. pub struct NodeListIter<'pr> { - pub(crate) parser: NonNull, + pub(crate) parser: *const pm_parser_t, pub(crate) pointer: NonNull, pub(crate) index: usize, pub(crate) marker: PhantomData<&'pr mut pm_node_list>, @@ -40,7 +40,7 @@ impl<'pr> Iterator for NodeListIter<'pr> { /// A list of nodes. pub struct NodeList<'pr> { - pub(crate) parser: NonNull, + pub(crate) parser: *const pm_parser_t, pub(crate) pointer: NonNull, pub(crate) marker: PhantomData<&'pr mut pm_node_list>, } @@ -115,13 +115,13 @@ impl std::fmt::Debug for NodeList<'_> { /// A handle for a constant ID. pub struct ConstantId<'pr> { - pub(crate) parser: NonNull, + pub(crate) parser: *const pm_parser_t, pub(crate) id: pm_constant_id_t, pub(crate) marker: PhantomData<&'pr mut pm_constant_id_t>, } impl<'pr> ConstantId<'pr> { - pub(crate) const fn new(parser: NonNull, id: pm_constant_id_t) -> Self { + pub(crate) const fn new(parser: *const pm_parser_t, id: pm_constant_id_t) -> Self { ConstantId { parser, id, marker: PhantomData } } @@ -133,9 +133,10 @@ impl<'pr> ConstantId<'pr> { #[must_use] pub fn as_slice(&self) -> &'pr [u8] { unsafe { - let pool = &(*self.parser.as_ptr()).constant_pool; - let constant = &(*pool.constants.add((self.id - 1).try_into().unwrap())); - std::slice::from_raw_parts(constant.start, constant.length) + let constant = ruby_prism_sys::pm_parser_constant(self.parser, self.id); + let start = ruby_prism_sys::pm_constant_start(constant); + let length = ruby_prism_sys::pm_constant_length(constant); + std::slice::from_raw_parts(start, length) } } } @@ -148,7 +149,7 @@ impl std::fmt::Debug for ConstantId<'_> { /// An iterator over the constants in a list. pub struct ConstantListIter<'pr> { - pub(crate) parser: NonNull, + pub(crate) parser: *const pm_parser_t, pub(crate) pointer: NonNull, pub(crate) index: usize, pub(crate) marker: PhantomData<&'pr mut pm_constant_id_list_t>, @@ -171,7 +172,7 @@ impl<'pr> Iterator for ConstantListIter<'pr> { /// A list of constants. pub struct ConstantList<'pr> { /// The raw pointer to the parser where this list came from. - pub(crate) parser: NonNull, + pub(crate) parser: *const pm_parser_t, /// The raw pointer to the list allocated by prism. pub(crate) pointer: NonNull, diff --git a/rust/ruby-prism/src/parse_result/comments.rs b/rust/ruby-prism/src/parse_result/comments.rs index 767de6330a..9f6c80f83a 100644 --- a/rust/ruby-prism/src/parse_result/comments.rs +++ b/rust/ruby-prism/src/parse_result/comments.rs @@ -1,9 +1,8 @@ //! Comment handling for the prism parser. use std::marker::PhantomData; -use std::ptr::NonNull; -use ruby_prism_sys::{pm_comment_t, pm_comment_type_t, pm_magic_comment_t, pm_parser_t}; +use ruby_prism_sys::{pm_comment_location, pm_comment_t, pm_comment_type, pm_comment_type_t, pm_magic_comment_key, pm_magic_comment_t, pm_magic_comment_value, pm_parser_start, pm_parser_t}; use super::Location; @@ -19,16 +18,13 @@ pub enum CommentType { /// A comment that was found during parsing. #[derive(Debug)] pub struct Comment<'pr> { - content: NonNull, - parser: NonNull, + raw: *const pm_comment_t, + parser: *const pm_parser_t, marker: PhantomData<&'pr pm_comment_t>, } impl<'pr> Comment<'pr> { /// Returns the text of the comment. - /// - /// # Panics - /// Panics if the end offset is not greater than the start offset. #[must_use] pub fn text(&self) -> &[u8] { self.location().as_slice() @@ -37,7 +33,7 @@ impl<'pr> Comment<'pr> { /// Returns the type of the comment. #[must_use] pub fn type_(&self) -> CommentType { - let type_ = unsafe { self.content.as_ref().type_ }; + let type_ = unsafe { pm_comment_type(self.raw) }; if type_ == pm_comment_type_t::PM_COMMENT_EMBDOC { CommentType::EmbDocComment } else { @@ -47,22 +43,28 @@ impl<'pr> Comment<'pr> { /// The location of the comment in the source. #[must_use] - pub const fn location(&self) -> Location<'pr> { - Location::new(self.parser, unsafe { &self.content.as_ref().location }) + pub fn location(&self) -> Location<'pr> { + let loc = unsafe { pm_comment_location(self.raw) }; + Location { + parser: self.parser, + start: loc.start, + length: loc.length, + marker: PhantomData, + } } } -/// A struct created by the `comments` method on `ParseResult`. It can be used -/// to iterate over the comments in the parse result. +/// An iterator over comments collected from the parse result. pub struct Comments<'pr> { - comment: *mut pm_comment_t, - parser: NonNull, + ptrs: Vec<*const pm_comment_t>, + index: usize, + parser: *const pm_parser_t, marker: PhantomData<&'pr pm_comment_t>, } impl Comments<'_> { - pub(crate) const fn new(comment: *mut pm_comment_t, parser: NonNull) -> Self { - Comments { comment, parser, marker: PhantomData } + pub(crate) const fn new(ptrs: Vec<*const pm_comment_t>, parser: *const pm_parser_t) -> Self { + Comments { ptrs, index: 0, parser, marker: PhantomData } } } @@ -70,14 +72,10 @@ impl<'pr> Iterator for Comments<'pr> { type Item = Comment<'pr>; fn next(&mut self) -> Option { - if let Some(comment) = NonNull::new(self.comment) { - let current = Comment { - content: comment, - parser: self.parser, - marker: PhantomData, - }; - self.comment = unsafe { comment.as_ref().node.next.cast::() }; - Some(current) + if self.index < self.ptrs.len() { + let comment = self.ptrs[self.index]; + self.index += 1; + Some(Comment { raw: comment, parser: self.parser, marker: PhantomData }) } else { None } @@ -87,44 +85,44 @@ impl<'pr> Iterator for Comments<'pr> { /// A magic comment that was found during parsing. #[derive(Debug)] pub struct MagicComment<'pr> { - parser: NonNull, - comment: NonNull, + parser: *const pm_parser_t, + raw: *const pm_magic_comment_t, marker: PhantomData<&'pr pm_magic_comment_t>, } impl MagicComment<'_> { /// Returns the text of the comment's key. #[must_use] - pub const fn key(&self) -> &[u8] { + pub fn key(&self) -> &[u8] { unsafe { - let start = self.parser.as_ref().start.add(self.comment.as_ref().key.start as usize); - let len = self.comment.as_ref().key.length as usize; - std::slice::from_raw_parts(start, len) + let loc = pm_magic_comment_key(self.raw); + let start = pm_parser_start(self.parser).add(loc.start as usize); + std::slice::from_raw_parts(start, loc.length as usize) } } /// Returns the text of the comment's value. #[must_use] - pub const fn value(&self) -> &[u8] { + pub fn value(&self) -> &[u8] { unsafe { - let start = self.parser.as_ref().start.add(self.comment.as_ref().value.start as usize); - let len = self.comment.as_ref().value.length as usize; - std::slice::from_raw_parts(start, len) + let loc = pm_magic_comment_value(self.raw); + let start = pm_parser_start(self.parser).add(loc.start as usize); + std::slice::from_raw_parts(start, loc.length as usize) } } } -/// A struct created by the `magic_comments` method on `ParseResult`. It can be used -/// to iterate over the magic comments in the parse result. +/// An iterator over magic comments collected from the parse result. pub struct MagicComments<'pr> { - parser: NonNull, - comment: *mut pm_magic_comment_t, + ptrs: Vec<*const pm_magic_comment_t>, + index: usize, + parser: *const pm_parser_t, marker: PhantomData<&'pr pm_magic_comment_t>, } impl MagicComments<'_> { - pub(crate) const fn new(parser: NonNull, comment: *mut pm_magic_comment_t) -> Self { - MagicComments { parser, comment, marker: PhantomData } + pub(crate) const fn new(ptrs: Vec<*const pm_magic_comment_t>, parser: *const pm_parser_t) -> Self { + MagicComments { ptrs, index: 0, parser, marker: PhantomData } } } @@ -132,10 +130,10 @@ impl<'pr> Iterator for MagicComments<'pr> { type Item = MagicComment<'pr>; fn next(&mut self) -> Option { - if let Some(comment) = NonNull::new(self.comment) { - let current = MagicComment { parser: self.parser, comment, marker: PhantomData }; - self.comment = unsafe { comment.as_ref().node.next.cast::() }; - Some(current) + if self.index < self.ptrs.len() { + let comment = self.ptrs[self.index]; + self.index += 1; + Some(MagicComment { parser: self.parser, raw: comment, marker: PhantomData }) } else { None } diff --git a/rust/ruby-prism/src/parse_result/diagnostics.rs b/rust/ruby-prism/src/parse_result/diagnostics.rs index 00fc9ffe33..ba231fabb2 100644 --- a/rust/ruby-prism/src/parse_result/diagnostics.rs +++ b/rust/ruby-prism/src/parse_result/diagnostics.rs @@ -1,18 +1,17 @@ //! Diagnostic handling for parse errors and warnings. -use std::ffi::{c_char, CStr}; +use std::ffi::CStr; use std::marker::PhantomData; -use std::ptr::NonNull; -use ruby_prism_sys::{pm_diagnostic_t, pm_parser_t}; +use ruby_prism_sys::{pm_diagnostic_location, pm_diagnostic_message, pm_diagnostic_t, pm_parser_t}; use super::Location; /// A diagnostic message that came back from the parser. #[derive(Debug)] pub struct Diagnostic<'pr> { - diag: NonNull, - parser: NonNull, + raw: *const pm_diagnostic_t, + parser: *const pm_parser_t, marker: PhantomData<&'pr pm_diagnostic_t>, } @@ -21,34 +20,39 @@ impl<'pr> Diagnostic<'pr> { /// /// # Panics /// - /// Panics if the message is not able to be converted into a `CStr`. - /// + /// Panics if the message is not valid UTF-8. #[must_use] pub fn message(&self) -> &str { unsafe { - let message: *mut c_char = self.diag.as_ref().message.cast_mut(); + let message = pm_diagnostic_message(self.raw); CStr::from_ptr(message).to_str().expect("prism allows only UTF-8 for diagnostics.") } } /// The location of the diagnostic in the source. #[must_use] - pub const fn location(&self) -> Location<'pr> { - Location::new(self.parser, unsafe { &self.diag.as_ref().location }) + pub fn location(&self) -> Location<'pr> { + let loc = unsafe { pm_diagnostic_location(self.raw) }; + Location { + parser: self.parser, + start: loc.start, + length: loc.length, + marker: PhantomData, + } } } -/// A struct created by the `errors` or `warnings` methods on `ParseResult`. It -/// can be used to iterate over the diagnostics in the parse result. +/// An iterator over diagnostics collected from the parse result. pub struct Diagnostics<'pr> { - diagnostic: *mut pm_diagnostic_t, - parser: NonNull, + ptrs: Vec<*const pm_diagnostic_t>, + index: usize, + parser: *const pm_parser_t, marker: PhantomData<&'pr pm_diagnostic_t>, } impl Diagnostics<'_> { - pub(crate) const fn new(diagnostic: *mut pm_diagnostic_t, parser: NonNull) -> Self { - Diagnostics { diagnostic, parser, marker: PhantomData } + pub(crate) const fn new(ptrs: Vec<*const pm_diagnostic_t>, parser: *const pm_parser_t) -> Self { + Diagnostics { ptrs, index: 0, parser, marker: PhantomData } } } @@ -56,14 +60,14 @@ impl<'pr> Iterator for Diagnostics<'pr> { type Item = Diagnostic<'pr>; fn next(&mut self) -> Option { - if let Some(diagnostic) = NonNull::new(self.diagnostic) { - let current = Diagnostic { - diag: diagnostic, + if self.index < self.ptrs.len() { + let diagnostic = self.ptrs[self.index]; + self.index += 1; + Some(Diagnostic { + raw: diagnostic, parser: self.parser, marker: PhantomData, - }; - self.diagnostic = unsafe { diagnostic.as_ref().node.next.cast::() }; - Some(current) + }) } else { None } diff --git a/rust/ruby-prism/src/parse_result/mod.rs b/rust/ruby-prism/src/parse_result/mod.rs index 5e071b515b..82cae4b731 100644 --- a/rust/ruby-prism/src/parse_result/mod.rs +++ b/rust/ruby-prism/src/parse_result/mod.rs @@ -1,14 +1,14 @@ //! Parse result types for the prism parser. -//! -//! This module contains types related to the result of parsing, including -//! the main `ParseResult` struct, location tracking, comments, and diagnostics. mod comments; mod diagnostics; use std::ptr::NonNull; -use ruby_prism_sys::{pm_arena_cleanup, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_cleanup, pm_parser_t}; +use ruby_prism_sys::{ + pm_arena_free, pm_arena_t, pm_comment_t, pm_diagnostic_t, pm_line_offset_list_line_column, pm_location_t, pm_magic_comment_t, pm_node_t, pm_parser_comments_each, pm_parser_comments_size, pm_parser_data_loc, pm_parser_errors_each, pm_parser_errors_size, pm_parser_free, + pm_parser_frozen_string_literal, pm_parser_line_offsets, pm_parser_magic_comments_each, pm_parser_magic_comments_size, pm_parser_start, pm_parser_start_line, pm_parser_t, pm_parser_warnings_each, pm_parser_warnings_size, +}; pub use self::comments::{Comment, CommentType, Comments, MagicComment, MagicComments}; pub use self::diagnostics::{Diagnostic, Diagnostics}; @@ -17,7 +17,7 @@ use crate::Node; /// A range in the source file, represented as a start offset and length. pub struct Location<'pr> { - pub(crate) parser: NonNull, + pub(crate) parser: *const pm_parser_t, pub(crate) start: u32, pub(crate) length: u32, marker: std::marker::PhantomData<&'pr [u8]>, @@ -28,14 +28,14 @@ impl<'pr> Location<'pr> { #[must_use] pub fn as_slice(&self) -> &'pr [u8] { unsafe { - let parser_start = (*self.parser.as_ptr()).start; + let parser_start = pm_parser_start(self.parser); std::slice::from_raw_parts(parser_start.add(self.start as usize), self.length as usize) } } /// Return a Location from the given `pm_location_t`. #[must_use] - pub(crate) const fn new(parser: NonNull, location: &'pr pm_location_t) -> Self { + pub(crate) const fn new(parser: *const pm_parser_t, location: &'pr pm_location_t) -> Self { Location { parser, start: location.start, @@ -114,11 +114,10 @@ impl Location<'_> { /// Returns the line and column number for the given byte offset. fn line_column(&self, cursor: u32) -> (i32, u32) { - // SAFETY: We read the line_offsets and start_line from the parser, - // which is valid for the lifetime of this Location. unsafe { - let parser = self.parser.as_ptr(); - let result = pm_line_offset_list_line_column(&raw const (*parser).line_offsets, cursor, (*parser).start_line); + let line_offsets = pm_parser_line_offsets(self.parser); + let start_line = pm_parser_start_line(self.parser); + let result = pm_line_offset_list_line_column(line_offsets, cursor, start_line); (result.line, result.column) } } @@ -141,17 +140,35 @@ impl std::fmt::Debug for Location<'_> { } } +// C callback that collects comment pointers into a Vec +unsafe extern "C" fn collect_comment(comment: *const pm_comment_t, data: *mut std::ffi::c_void) { + let vec = &mut *(data.cast::>()); + vec.push(comment); +} + +// C callback that collects magic comment pointers into a Vec +unsafe extern "C" fn collect_magic_comment(comment: *const pm_magic_comment_t, data: *mut std::ffi::c_void) { + let vec = &mut *(data.cast::>()); + vec.push(comment); +} + +// C callback that collects diagnostic pointers into a Vec +unsafe extern "C" fn collect_diagnostic(diagnostic: *const pm_diagnostic_t, data: *mut std::ffi::c_void) { + let vec = &mut *(data.cast::>()); + vec.push(diagnostic); +} + /// The result of parsing a source string. #[derive(Debug)] pub struct ParseResult<'pr> { source: &'pr [u8], - arena: Box, - parser: NonNull, + arena: *mut pm_arena_t, + parser: *mut pm_parser_t, node: NonNull, } impl<'pr> ParseResult<'pr> { - pub(crate) const unsafe fn new(source: &'pr [u8], arena: Box, parser: NonNull, node: NonNull) -> Self { + pub(crate) const unsafe fn new(source: &'pr [u8], arena: *mut pm_arena_t, parser: *mut pm_parser_t, node: NonNull) -> Self { ParseResult { source, arena, parser, node } } @@ -164,7 +181,7 @@ impl<'pr> ParseResult<'pr> { /// Returns whether we found a `frozen_string_literal` magic comment with a true value. #[must_use] pub fn frozen_string_literals(&self) -> bool { - unsafe { (*self.parser.as_ptr()).frozen_string_literal == 1 } + unsafe { pm_parser_frozen_string_literal(self.parser) == 1 } } /// Returns a slice of the source string that was parsed using the given @@ -181,54 +198,63 @@ impl<'pr> ParseResult<'pr> { #[must_use] pub fn line_offsets(&self) -> &'pr [u32] { unsafe { - let list = &(*self.parser.as_ptr()).line_offsets; + let list = &*pm_parser_line_offsets(self.parser); std::slice::from_raw_parts(list.offsets, list.size) } } + /// Returns an iterator that can be used to iterate over the errors in the /// parse result. #[must_use] pub fn errors(&self) -> Diagnostics<'_> { + let size = unsafe { pm_parser_errors_size(self.parser) }; + let mut ptrs: Vec<*const pm_diagnostic_t> = Vec::with_capacity(size); unsafe { - let list = &mut (*self.parser.as_ptr()).error_list; - Diagnostics::new(list.head.cast::(), self.parser) + pm_parser_errors_each(self.parser, Some(collect_diagnostic), (&raw mut ptrs).cast()); } + Diagnostics::new(ptrs, self.parser) } /// Returns an iterator that can be used to iterate over the warnings in the /// parse result. #[must_use] pub fn warnings(&self) -> Diagnostics<'_> { + let size = unsafe { pm_parser_warnings_size(self.parser) }; + let mut ptrs: Vec<*const pm_diagnostic_t> = Vec::with_capacity(size); unsafe { - let list = &mut (*self.parser.as_ptr()).warning_list; - Diagnostics::new(list.head.cast::(), self.parser) + pm_parser_warnings_each(self.parser, Some(collect_diagnostic), (&raw mut ptrs).cast()); } + Diagnostics::new(ptrs, self.parser) } /// Returns an iterator that can be used to iterate over the comments in the /// parse result. #[must_use] pub fn comments(&self) -> Comments<'_> { + let size = unsafe { pm_parser_comments_size(self.parser) }; + let mut ptrs: Vec<*const pm_comment_t> = Vec::with_capacity(size); unsafe { - let list = &mut (*self.parser.as_ptr()).comment_list; - Comments::new(list.head.cast::(), self.parser) + pm_parser_comments_each(self.parser, Some(collect_comment), (&raw mut ptrs).cast()); } + Comments::new(ptrs, self.parser) } /// Returns an iterator that can be used to iterate over the magic comments in the /// parse result. #[must_use] pub fn magic_comments(&self) -> MagicComments<'_> { + let size = unsafe { pm_parser_magic_comments_size(self.parser) }; + let mut ptrs: Vec<*const pm_magic_comment_t> = Vec::with_capacity(size); unsafe { - let list = &mut (*self.parser.as_ptr()).magic_comment_list; - MagicComments::new(self.parser, list.head.cast::()) + pm_parser_magic_comments_each(self.parser, Some(collect_magic_comment), (&raw mut ptrs).cast()); } + MagicComments::new(ptrs, self.parser) } /// Returns an optional location of the __END__ marker and the rest of the content of the file. #[must_use] pub fn data_loc(&self) -> Option> { - let location = unsafe { &(*self.parser.as_ptr()).data_loc }; + let location = unsafe { &*pm_parser_data_loc(self.parser) }; if location.length == 0 { None } else { @@ -260,9 +286,8 @@ impl<'pr> ParseResult<'pr> { impl Drop for ParseResult<'_> { fn drop(&mut self) { unsafe { - pm_parser_cleanup(self.parser.as_ptr()); - drop(Box::from_raw(self.parser.as_ptr())); - pm_arena_cleanup(self.arena.as_mut()); + pm_parser_free(self.parser); + pm_arena_free(self.arena); } } } diff --git a/src/parser.c b/src/parser.c index b61fb6ce03..a65fc1a9d5 100644 --- a/src/parser.c +++ b/src/parser.c @@ -69,6 +69,14 @@ pm_parser_encoding_name(const pm_parser_t *parser) { return parser->encoding->name; } +/** + * Returns the frozen string literal value of the parser. + */ +int8_t +pm_parser_frozen_string_literal(const pm_parser_t *parser) { + return parser->frozen_string_literal; +} + /** * Returns the line offsets that are associated with the given parser. * @@ -249,3 +257,12 @@ pm_parser_constants_each(const pm_parser_t *parser, pm_constant_callback_t callb callback(constant, data); } } + +/** + * Returns a pointer to the constant at the given id in the constant pool + * associated with the given parser. + */ +const pm_constant_t * +pm_parser_constant(const pm_parser_t *parser, pm_constant_id_t constant_id) { + return pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id); +} From 852bb0476d32881c8fe4bb1f28c5c396a0fbcd3c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 15:28:39 -0400 Subject: [PATCH 232/289] Ensure wasm build is happy --- src/json.c | 5 +---- templates/src/prettyprint.c.erb | 5 +---- templates/src/serialize.c.erb | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/json.c b/src/json.c index 57e3fc07df..68b5ff3ccb 100644 --- a/src/json.c +++ b/src/json.c @@ -13,10 +13,7 @@ */ #ifdef PRISM_EXCLUDE_JSON -#include "prism/compiler/unused.h" - -void -pm_dump_json(PRISM_UNUSED pm_buffer_t *buffer, PRISM_UNUSED const pm_parser_t *parser, PRISM_UNUSED const pm_node_t *node) {} +void pm_dump_json(void) {} #else diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index 9992f51096..f12e55d726 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -6,10 +6,7 @@ * PRISM_EXCLUDE_PRETTYPRINT define. */ #ifdef PRISM_EXCLUDE_PRETTYPRINT -#include "prism/compiler/unused.h" - -void -pm_prettyprint(PRISM_UNUSED pm_buffer_t *buffer, PRISM_UNUSED const pm_parser_t *parser, PRISM_UNUSED const pm_node_t *node) {} +void pm_prettyprint(void) {} #else diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index 8c28cb89fc..c30487bbb0 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -5,10 +5,7 @@ * PRISM_EXCLUDE_SERIALIZATION define. */ #ifdef PRISM_EXCLUDE_SERIALIZATION -#include "prism/compiler/unused.h" - -void -pm_serialize_lex(PRISM_UNUSED pm_buffer_t *buffer, PRISM_UNUSED const uint8_t *source, PRISM_UNUSED size_t size, PRISM_UNUSED const char *data) {} +void pm_serialize_lex(void) {} #else From 149cc9d2a3087b071bfcc5d5e0af8e7fac8b38e5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 15:36:43 -0400 Subject: [PATCH 233/289] Final review --- include/prism/comments.h | 2 ++ include/prism/magic_comments.h | 2 ++ include/prism/options.h | 13 +++++++------ include/prism/version.h | 2 ++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/prism/comments.h b/include/prism/comments.h index 5938f388cd..2270d53889 100644 --- a/include/prism/comments.h +++ b/include/prism/comments.h @@ -1,5 +1,7 @@ /** * @file comments.h + * + * Types and functions related to comments found during parsing. */ #ifndef PRISM_COMMENTS_H #define PRISM_COMMENTS_H diff --git a/include/prism/magic_comments.h b/include/prism/magic_comments.h index 6d47cda985..c9d6b600e8 100644 --- a/include/prism/magic_comments.h +++ b/include/prism/magic_comments.h @@ -1,5 +1,7 @@ /** * @file magic_comments.h + * + * Types and functions related to magic comments found during parsing. */ #ifndef PRISM_MAGIC_COMMENTS_H #define PRISM_MAGIC_COMMENTS_H diff --git a/include/prism/options.h b/include/prism/options.h index 1c7281d599..37a713095e 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -6,6 +6,7 @@ #ifndef PRISM_OPTIONS_H #define PRISM_OPTIONS_H +#include "prism/compiler/exported.h" #include "prism/compiler/nodiscard.h" #include "prism/compiler/nonnull.h" @@ -25,7 +26,7 @@ typedef struct pm_options_scope_t pm_options_scope_t; typedef struct pm_options_t pm_options_t; /** - * String literals should be made frozen. + * String literals should not be frozen. */ #define PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED ((int8_t) -1) @@ -36,23 +37,23 @@ typedef struct pm_options_t pm_options_t; #define PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET ((int8_t) 0) /** - * String literals should be made mutable. + * String literals should be made frozen. */ #define PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED ((int8_t) 1) /** The default value for parameters. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_NONE = 0x0; -/** When the scope is fowarding with the * parameter. */ +/** When the scope is forwarding with the * parameter. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS = 0x1; -/** When the scope is fowarding with the ** parameter. */ +/** When the scope is forwarding with the ** parameter. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS = 0x2; -/** When the scope is fowarding with the & parameter. */ +/** When the scope is forwarding with the & parameter. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_BLOCK = 0x4; -/** When the scope is fowarding with the ... parameter. */ +/** When the scope is forwarding with the ... parameter. */ static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_ALL = 0x8; /** diff --git a/include/prism/version.h b/include/prism/version.h index 99cc99158e..181b398462 100644 --- a/include/prism/version.h +++ b/include/prism/version.h @@ -6,6 +6,8 @@ #ifndef PRISM_VERSION_H #define PRISM_VERSION_H +#include "prism/compiler/exported.h" + /** * The major version of the Prism library as an int. */ From 665bcf30566d33ad5c8fc7bf59ae3b763169c545 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 15:51:33 -0400 Subject: [PATCH 234/289] Rebase --- include/prism/internal/strpbrk.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/prism/internal/strpbrk.h b/include/prism/internal/strpbrk.h index 124c528cb3..d64156c002 100644 --- a/include/prism/internal/strpbrk.h +++ b/include/prism/internal/strpbrk.h @@ -3,6 +3,9 @@ #include "prism/parser.h" +/* The maximum number of bytes in a strpbrk charset. */ +#define PM_STRPBRK_CACHE_SIZE 16 + #include #include From 1c1e94849ef5e39c82e107e3e0914d7268031ba8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 16:48:07 -0400 Subject: [PATCH 235/289] Fix up bindings --- ext/prism/extension.c | 10 +++++ include/prism/internal/bit.h | 43 +++++++++++-------- .../org/jruby/parser/prism/wasm/Prism.java | 6 +-- lib/prism/ffi.rb | 3 ++ src/arena.c | 2 +- src/json.c | 10 ++--- src/prism.c | 1 + templates/ext/prism/api_node.c.erb | 2 + templates/src/json.c.erb | 6 +-- templates/src/prettyprint.c.erb | 4 +- templates/src/serialize.c.erb | 4 +- 11 files changed, 56 insertions(+), 35 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 0c9458e6cf..43e27d68c5 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -4,6 +4,8 @@ #include #endif +#include + // NOTE: this file should contain only bindings. All non-trivial logic should be // in libprism so it can be shared its the various callers. @@ -411,7 +413,11 @@ dump(int argc, VALUE *argv, VALUE self) { if (pm_options_freeze(options)) rb_obj_freeze(value); #ifdef PRISM_BUILD_DEBUG +#ifdef xfree_sized xfree_sized(dup, length); +#else + xfree(dup); +#endif #endif pm_string_cleanup(&input); @@ -968,7 +974,11 @@ parse(int argc, VALUE *argv, VALUE self) { VALUE value = parse_input(&input, options); #ifdef PRISM_BUILD_DEBUG +#ifdef xfree_sized xfree_sized(dup, length); +#else + xfree(dup); +#endif #endif pm_string_cleanup(&input); diff --git a/include/prism/internal/bit.h b/include/prism/internal/bit.h index 4eec494887..b0111a4c2c 100644 --- a/include/prism/internal/bit.h +++ b/include/prism/internal/bit.h @@ -11,27 +11,32 @@ * (matching the behavior of __builtin_ctzll and _BitScanForward64). */ #if defined(__GNUC__) || defined(__clang__) - #define pm_ctzll(v) ((unsigned) __builtin_ctzll(v)) +#define pm_ctzll(v) ((unsigned) __builtin_ctzll(v)) #elif defined(_MSC_VER) - #include - static PRISM_INLINE unsigned pm_ctzll(uint64_t v) { - unsigned long index; - _BitScanForward64(&index, v); - return (unsigned) index; - } +#include +#include + +static PRISM_INLINE unsigned +pm_ctzll(uint64_t v) { + unsigned long index; + _BitScanForward64(&index, v); + return (unsigned) index; +} #else - static PRISM_INLINE unsigned - pm_ctzll(uint64_t v) { - unsigned c = 0; - v &= (uint64_t) (-(int64_t) v); - if (v & 0x00000000FFFFFFFFULL) c += 0; else c += 32; - if (v & 0x0000FFFF0000FFFFULL) c += 0; else c += 16; - if (v & 0x00FF00FF00FF00FFULL) c += 0; else c += 8; - if (v & 0x0F0F0F0F0F0F0F0FULL) c += 0; else c += 4; - if (v & 0x3333333333333333ULL) c += 0; else c += 2; - if (v & 0x5555555555555555ULL) c += 0; else c += 1; - return c; - } +#include + +static PRISM_INLINE unsigned +pm_ctzll(uint64_t v) { + unsigned c = 0; + v &= (uint64_t) (-(int64_t) v); + if (v & 0x00000000FFFFFFFFULL) c += 0; else c += 32; + if (v & 0x0000FFFF0000FFFFULL) c += 0; else c += 16; + if (v & 0x00FF00FF00FF00FFULL) c += 0; else c += 8; + if (v & 0x0F0F0F0F0F0F0F0FULL) c += 0; else c += 4; + if (v & 0x3333333333333333ULL) c += 0; else c += 2; + if (v & 0x5555555555555555ULL) c += 0; else c += 1; + return c; +} #endif #endif diff --git a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java index 67a127276c..71726703c3 100644 --- a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java +++ b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java @@ -40,8 +40,7 @@ public Prism(WasiOptions wasiOpts) { preOptionsPointer = exports.calloc(1, PACKED_OPTIONS_BUFFER_SIZE); preSourcePointer = exports.calloc(1, SOURCE_SIZE); - bufferPointer = exports.calloc(exports.pmBufferSizeof(), 1); - exports.pmBufferInit(bufferPointer); + bufferPointer = exports.pmBufferNew(); } public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { @@ -60,7 +59,8 @@ public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLeng exports.calloc(1, packedOptions.length) : preOptionsPointer; instance.memory().write(optionsPointer, packedOptions); - exports.pmBufferClear(bufferPointer); + exports.pmBufferFree(bufferPointer); + bufferPointer = exports.pmBufferNew(); exports.pmSerializeParse( bufferPointer, sourcePointer, sourceLength, optionsPointer); diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 7b22a1304c..5144ba72c4 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -59,6 +59,9 @@ def self.load_exported_functions_from(header, *functions, callbacks) # We only want to load the functions that we are interested in. next unless functions.any? { |function| line.include?(function) } + # Strip trailing attributes (PRISM_NODISCARD, PRISM_NONNULL(...), etc.) + line = line.sub(/\)(\s+PRISM_\w+(?:\([^)]*\))?)+\s*;/, ");") + # Parse the function declaration. unless /^PRISM_EXPORTED_FUNCTION (?.+) (?\w+)\((?.+)\);$/ =~ line raise "Could not parse #{line}" diff --git a/src/arena.c b/src/arena.c index dd998402f3..7ae02715df 100644 --- a/src/arena.c +++ b/src/arena.c @@ -113,5 +113,5 @@ pm_arena_cleanup(pm_arena_t *arena) { void pm_arena_free(pm_arena_t *arena) { pm_arena_cleanup(arena); - xfree(arena); + xfree(arena); } diff --git a/src/json.c b/src/json.c index 68b5ff3ccb..72975db724 100644 --- a/src/json.c +++ b/src/json.c @@ -8,14 +8,10 @@ #include "prism/json.h" -/* We optionally support dumping to JSON. For systems that don not want or need - * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. - */ -#ifdef PRISM_EXCLUDE_JSON - -void pm_dump_json(void) {} +// Ensure this translation unit is never empty, even when JSON is excluded. +typedef int pm_json_unused_t; -#else +#ifndef PRISM_EXCLUDE_JSON #include "prism/internal/buffer.h" #include "prism/internal/constant_pool.h" diff --git a/src/prism.c b/src/prism.c index b6afa8bb15..39602fbfc2 100644 --- a/src/prism.c +++ b/src/prism.c @@ -30,6 +30,7 @@ #include "prism/excludes.h" #include "prism/serialize.h" +#include "prism/stream.h" #include "prism/version.h" #include diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index 6dd3a59372..506c2e87f8 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -2,6 +2,8 @@ #include "prism/extension.h" #include "prism/internal/allocator.h" +#include + extern VALUE rb_cPrism; extern VALUE rb_cPrismNode; extern VALUE rb_cPrismSource; diff --git a/templates/src/json.c.erb b/templates/src/json.c.erb index 66397b8fcd..5c4ab8d92a 100644 --- a/templates/src/json.c.erb +++ b/templates/src/json.c.erb @@ -1,8 +1,8 @@ #include "prism/json.h" -/* We optionally support dumping to JSON. For systems that don not want or need - * this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define. - */ +// Ensure this translation unit is never empty, even when JSON is excluded. +typedef int pm_json_unused_t; + #ifndef PRISM_EXCLUDE_JSON #include "prism/internal/buffer.h" diff --git a/templates/src/prettyprint.c.erb b/templates/src/prettyprint.c.erb index f12e55d726..f12531d934 100644 --- a/templates/src/prettyprint.c.erb +++ b/templates/src/prettyprint.c.erb @@ -6,7 +6,9 @@ * PRISM_EXCLUDE_PRETTYPRINT define. */ #ifdef PRISM_EXCLUDE_PRETTYPRINT -void pm_prettyprint(void) {} +/* Ensure this translation unit is never empty, even when prettyprint is + * excluded. */ +typedef int pm_prettyprint_unused_t; #else diff --git a/templates/src/serialize.c.erb b/templates/src/serialize.c.erb index c30487bbb0..3d9811e5db 100644 --- a/templates/src/serialize.c.erb +++ b/templates/src/serialize.c.erb @@ -5,7 +5,9 @@ * PRISM_EXCLUDE_SERIALIZATION define. */ #ifdef PRISM_EXCLUDE_SERIALIZATION -void pm_serialize_lex(void) {} +/* Ensure this translation unit is never empty, even when serialization is + * excluded. */ +typedef int pm_serialize_unused_t; #else From 717e4e738dae021e99b7f1df4321021a2c45ddfd Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 20:10:36 -0400 Subject: [PATCH 236/289] Ensure we free options before raising type errors --- ext/prism/extension.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 43e27d68c5..12bd1c4b98 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -312,6 +312,11 @@ string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) VALUE keywords; rb_scan_args(argc, argv, "1:", &string, &keywords); + if (!RB_TYPE_P(string, T_STRING)) { + pm_options_free(options); + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(string)); + } + extract_options(options, Qnil, keywords); input_load_string(input, string); } @@ -325,7 +330,11 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V VALUE keywords; rb_scan_args(argc, argv, "1:", &filepath, &keywords); - Check_Type(filepath, T_STRING); + if (!RB_TYPE_P(filepath, T_STRING)) { + pm_options_free(options); + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(filepath)); + } + *encoded_filepath = rb_str_encode_ospath(filepath); extract_options(options, *encoded_filepath, keywords); From 6ba2c6424e5aa667572f798ae393343e68ff939e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 20:36:01 -0400 Subject: [PATCH 237/289] Add necessary functions for CRuby integration --- include/prism/constant_pool.h | 11 +++++++++++ include/prism/internal/constant_pool.h | 6 ------ include/prism/parser.h | 27 ++++++++++++++++++++++++++ src/parser.c | 25 ++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index 7868c584a7..7ca795a701 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -60,4 +60,15 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *c */ PRISM_EXPORTED_FUNCTION size_t pm_constant_length(const pm_constant_t *constant) PRISM_NONNULL(1); +/** + * Find a constant in a constant pool. Returns the id of the constant, or 0 if + * the constant is not found. + * + * @param pool The constant pool to search. + * @param start A pointer to the start of the string to search for. + * @param length The length of the string to search for. + * @returns The id of the constant, or 0 if the constant is not found. + */ +PRISM_EXPORTED_FUNCTION pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length) PRISM_NONNULL(1, 2); + #endif diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h index 7ca265d594..f82fa4d717 100644 --- a/include/prism/internal/constant_pool.h +++ b/include/prism/internal/constant_pool.h @@ -95,12 +95,6 @@ void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t /* Return a pointer to the constant indicated by the given constant id. */ pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id); -/* - * Find a constant in a constant pool. Returns the id of the constant, or 0 if - * the constant is not found. - */ -pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length); - /* * Insert a constant into a constant pool that is a slice of a source string. * Returns the id of the constant, or 0 if any potential calls to resize fail. diff --git a/include/prism/parser.h b/include/prism/parser.h index 78e6c189ac..c0d0a5b5e4 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -112,6 +112,33 @@ PRISM_EXPORTED_FUNCTION int32_t pm_parser_start_line(const pm_parser_t *parser) */ PRISM_EXPORTED_FUNCTION const char * pm_parser_encoding_name(const pm_parser_t *parser) PRISM_NONNULL(1); +/** + * Returns the width of the character at the given pointer in the encoding that + * is being used to parse the source. + * + * @param parser the parser whose encoding we want to use + * @param start a pointer to the start of the character + * @param remaining the number of bytes remaining in the source + * @returns the width of the character in bytes + */ +PRISM_EXPORTED_FUNCTION size_t pm_parser_encoding_char_width(const pm_parser_t *parser, const uint8_t *start, ptrdiff_t remaining) PRISM_NONNULL(1, 2); + +/** + * Returns whether or not the parser is using the US-ASCII encoding. + * + * @param parser the parser to check + * @returns true if the parser is using US-ASCII encoding, false otherwise + */ +PRISM_EXPORTED_FUNCTION bool pm_parser_encoding_us_ascii(const pm_parser_t *parser) PRISM_NONNULL(1); + +/** + * Returns the filepath that is being used to parse the source. + * + * @param parser the parser whose filepath we want to get + * @returns a pointer to the filepath string + */ +PRISM_EXPORTED_FUNCTION const pm_string_t * pm_parser_filepath(const pm_parser_t *parser) PRISM_NONNULL(1); + /** * Returns the frozen string literal value of the parser, as determined by the * frozen_string_literal magic comment or the option set on the parser. diff --git a/src/parser.c b/src/parser.c index a65fc1a9d5..9743691306 100644 --- a/src/parser.c +++ b/src/parser.c @@ -69,6 +69,31 @@ pm_parser_encoding_name(const pm_parser_t *parser) { return parser->encoding->name; } +/** + * Returns the width of the character at the given pointer in the encoding that + * is being used to parse the source. + */ +size_t +pm_parser_encoding_char_width(const pm_parser_t *parser, const uint8_t *start, ptrdiff_t remaining) { + return parser->encoding->char_width(start, remaining); +} + +/** + * Returns whether or not the parser is using the US-ASCII encoding. + */ +bool +pm_parser_encoding_us_ascii(const pm_parser_t *parser) { + return parser->encoding == PM_ENCODING_US_ASCII_ENTRY; +} + +/** + * Returns the filepath that is being used to parse the source. + */ +const pm_string_t * +pm_parser_filepath(const pm_parser_t *parser) { + return &parser->filepath; +} + /** * Returns the frozen string literal value of the parser. */ From d4a3ef9e435d3d7f330b3f924ce61a6ce754421f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 18 Mar 2026 20:42:50 -0400 Subject: [PATCH 238/289] pm_parser_constant_find --- include/prism/constant_pool.h | 11 ----------- include/prism/internal/constant_pool.h | 6 ++++++ include/prism/parser.h | 11 +++++++++++ src/parser.c | 9 +++++++++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index 7ca795a701..7868c584a7 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -60,15 +60,4 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *c */ PRISM_EXPORTED_FUNCTION size_t pm_constant_length(const pm_constant_t *constant) PRISM_NONNULL(1); -/** - * Find a constant in a constant pool. Returns the id of the constant, or 0 if - * the constant is not found. - * - * @param pool The constant pool to search. - * @param start A pointer to the start of the string to search for. - * @param length The length of the string to search for. - * @returns The id of the constant, or 0 if the constant is not found. - */ -PRISM_EXPORTED_FUNCTION pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length) PRISM_NONNULL(1, 2); - #endif diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h index f82fa4d717..7ca265d594 100644 --- a/include/prism/internal/constant_pool.h +++ b/include/prism/internal/constant_pool.h @@ -95,6 +95,12 @@ void pm_constant_pool_init(pm_arena_t *arena, pm_constant_pool_t *pool, uint32_t /* Return a pointer to the constant indicated by the given constant id. */ pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id); +/* + * Find a constant in a constant pool. Returns the id of the constant, or 0 if + * the constant is not found. + */ +pm_constant_id_t pm_constant_pool_find(const pm_constant_pool_t *pool, const uint8_t *start, size_t length); + /* * Insert a constant into a constant pool that is a slice of a source string. * Returns the id of the constant, or 0 if any potential calls to resize fail. diff --git a/include/prism/parser.h b/include/prism/parser.h index c0d0a5b5e4..cf613c2c77 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -139,6 +139,17 @@ PRISM_EXPORTED_FUNCTION bool pm_parser_encoding_us_ascii(const pm_parser_t *pars */ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_parser_filepath(const pm_parser_t *parser) PRISM_NONNULL(1); +/** + * Find a constant in the parser's constant pool. Returns the id of the + * constant, or 0 if the constant is not found. + * + * @param parser the parser whose constant pool we want to search + * @param start a pointer to the start of the string to search for + * @param length the length of the string to search for + * @returns the id of the constant, or 0 if the constant is not found + */ +PRISM_EXPORTED_FUNCTION pm_constant_id_t pm_parser_constant_find(const pm_parser_t *parser, const uint8_t *start, size_t length) PRISM_NONNULL(1, 2); + /** * Returns the frozen string literal value of the parser, as determined by the * frozen_string_literal magic comment or the option set on the parser. diff --git a/src/parser.c b/src/parser.c index 9743691306..415cd31984 100644 --- a/src/parser.c +++ b/src/parser.c @@ -94,6 +94,15 @@ pm_parser_filepath(const pm_parser_t *parser) { return &parser->filepath; } +/** + * Find a constant in the parser's constant pool. Returns the id of the + * constant, or 0 if the constant is not found. + */ +pm_constant_id_t +pm_parser_constant_find(const pm_parser_t *parser, const uint8_t *start, size_t length) { + return pm_constant_pool_find(&parser->constant_pool, start, length); +} + /** * Returns the frozen string literal value of the parser. */ From a52c48186e626192124392cad83a61573bdf3393 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 10:04:09 -0400 Subject: [PATCH 239/289] Also expose pm_constant_id_list_init, pm_constant_id_list_append, and pm_string_owned_init --- include/prism/constant_pool.h | 18 ++++++++++++++++++ include/prism/internal/constant_pool.h | 6 ------ include/prism/internal/strings.h | 5 ----- include/prism/strings.h | 9 +++++++++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/include/prism/constant_pool.h b/include/prism/constant_pool.h index 7868c584a7..dc03235c70 100644 --- a/include/prism/constant_pool.h +++ b/include/prism/constant_pool.h @@ -14,6 +14,8 @@ #include "prism/compiler/nodiscard.h" #include "prism/compiler/nonnull.h" +#include "prism/arena.h" + #include #include @@ -60,4 +62,20 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_constant_start(const pm_constant_t *c */ PRISM_EXPORTED_FUNCTION size_t pm_constant_length(const pm_constant_t *constant) PRISM_NONNULL(1); +/** + * Initialize a list of constant ids. + * + * @param list The list to initialize. + */ +PRISM_EXPORTED_FUNCTION void pm_constant_id_list_init(pm_constant_id_list_t *list) PRISM_NONNULL(1); + +/** + * Append a constant id to a list of constant ids. + * + * @param arena The arena to use for allocations. + * @param list The list to append to. + * @param id The constant id to append. + */ +PRISM_EXPORTED_FUNCTION void pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id) PRISM_NONNULL(1, 2); + #endif diff --git a/include/prism/internal/constant_pool.h b/include/prism/internal/constant_pool.h index 7ca265d594..fa2be783f5 100644 --- a/include/prism/internal/constant_pool.h +++ b/include/prism/internal/constant_pool.h @@ -74,15 +74,9 @@ struct pm_constant_pool_t { */ #define PM_CONSTANT_ID_UNSET 0 -/* Initialize a list of constant ids. */ -void pm_constant_id_list_init(pm_constant_id_list_t *list); - /* Initialize a list of constant ids with a given capacity. */ void pm_constant_id_list_init_capacity(pm_arena_t *arena, pm_constant_id_list_t *list, size_t capacity); -/* Append a constant id to a list of constant ids. */ -void pm_constant_id_list_append(pm_arena_t *arena, pm_constant_id_list_t *list, pm_constant_id_t id); - /* Insert a constant id into a list of constant ids at the specified index. */ void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_constant_id_t id); diff --git a/include/prism/internal/strings.h b/include/prism/internal/strings.h index 0199ed8d67..573eade290 100644 --- a/include/prism/internal/strings.h +++ b/include/prism/internal/strings.h @@ -14,11 +14,6 @@ */ void pm_string_shared_init(pm_string_t *string, const uint8_t *start, const uint8_t *end); -/* - * Initialize an owned string that is responsible for freeing allocated memory. - */ -void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length); - /* * Ensure the string is owned. If it is not, then reinitialize it as owned and * copy over the previous source. diff --git a/include/prism/strings.h b/include/prism/strings.h index 55059eb307..ac2dd15d1e 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -58,6 +58,15 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_sizeof(void); */ PRISM_EXPORTED_FUNCTION void pm_string_constant_init(pm_string_t *string, const char *source, size_t length) PRISM_NONNULL(1); +/** + * Initialize an owned string that is responsible for freeing allocated memory. + * + * @param string The string to initialize. + * @param source The source of the string. + * @param length The length of the string. + */ +PRISM_EXPORTED_FUNCTION void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length) PRISM_NONNULL(1, 2); + /** * Represents the result of calling pm_string_mapped_init or * pm_string_file_init. We need this additional information because there is From f50c25b5c12ba1cb63784226f0a1b6867e93fdc7 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 13:11:55 -0400 Subject: [PATCH 240/289] Introduce pm_source_t --- ext/prism/extension.c | 174 ++++---- include/prism.h | 1 + include/prism/internal/source.h | 72 ++++ include/prism/internal/strings.h | 11 +- include/prism/serialize.h | 11 +- include/prism/source.h | 138 +++++++ include/prism/stream.h | 23 +- include/prism/strings.h | 75 +--- lib/prism/ffi.rb | 104 ++--- rust/ruby-prism-sys/build/main.rs | 1 - rust/ruby-prism-sys/tests/utils_tests.rs | 92 +---- src/options.c | 1 + src/prism.c | 71 +--- src/source.c | 483 +++++++++++++++++++++++ src/strings.c | 311 +-------------- 15 files changed, 849 insertions(+), 719 deletions(-) create mode 100644 include/prism/internal/source.h create mode 100644 include/prism/source.h create mode 100644 src/source.c diff --git a/ext/prism/extension.c b/ext/prism/extension.c index 12bd1c4b98..a3ff4a1632 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -66,18 +66,6 @@ check_string(VALUE value) { return RSTRING_PTR(value); } -/** - * Load the contents and size of the given string into the given pm_string_t. - */ -static void -input_load_string(pm_string_t *input, VALUE string) { - // Check if the string is a string. If it's not, then raise a type error. - if (!RB_TYPE_P(string, T_STRING)) { - rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(string)); - } - - pm_string_constant_init(input, RSTRING_PTR(string), RSTRING_LEN(string)); -} /******************************************************************************/ /* Building C options from Ruby options */ @@ -306,8 +294,8 @@ extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) { /** * Read options for methods that look like (source, **options). */ -static void -string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) { +static VALUE +string_options(int argc, VALUE *argv, pm_options_t *options) { VALUE string; VALUE keywords; rb_scan_args(argc, argv, "1:", &string, &keywords); @@ -318,14 +306,14 @@ string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) } extract_options(options, Qnil, keywords); - input_load_string(input, string); + return string; } /** * Read options for methods that look like (filepath, **options). */ -static void -file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, VALUE *encoded_filepath) { +static pm_source_t * +file_options(int argc, VALUE *argv, pm_options_t *options, VALUE *encoded_filepath) { VALUE filepath; VALUE keywords; rb_scan_args(argc, argv, "1:", &filepath, &keywords); @@ -339,12 +327,13 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V extract_options(options, *encoded_filepath, keywords); const char *source = (const char *) pm_string_source(pm_options_filepath(options)); - pm_string_init_result_t result; + pm_source_init_result_t result; + pm_source_t *pm_src = pm_source_file_new(source, &result); - switch (result = pm_string_file_init(input, source)) { - case PM_STRING_INIT_SUCCESS: + switch (result) { + case PM_SOURCE_INIT_SUCCESS: break; - case PM_STRING_INIT_ERROR_GENERIC: { + case PM_SOURCE_INIT_ERROR_GENERIC: { pm_options_free(options); #ifdef _WIN32 @@ -356,7 +345,7 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V rb_syserr_fail(e, source); break; } - case PM_STRING_INIT_ERROR_DIRECTORY: + case PM_SOURCE_INIT_ERROR_DIRECTORY: pm_options_free(options); rb_syserr_fail(EISDIR, source); break; @@ -365,6 +354,8 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V rb_raise(rb_eRuntimeError, "Unknown error (%d) initializing file: %s", result, source); break; } + + return pm_src; } #ifndef PRISM_EXCLUDE_SERIALIZATION @@ -377,14 +368,14 @@ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, V * Dump the AST corresponding to the given input to a string. */ static VALUE -dump_input(pm_string_t *input, const pm_options_t *options) { +dump_input(const uint8_t *input, size_t input_length, const pm_options_t *options) { pm_buffer_t *buffer = pm_buffer_new(); if (!buffer) { rb_raise(rb_eNoMemError, "failed to allocate memory"); } pm_arena_t *arena = pm_arena_new(); - pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(arena, input, input_length, options); pm_node_t *node = pm_parse(parser); pm_serialize(parser, node, buffer); @@ -407,18 +398,19 @@ dump_input(pm_string_t *input, const pm_options_t *options) { */ static VALUE dump(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); - string_options(argc, argv, &input, options); + VALUE string = string_options(argc, argv, options); + + const uint8_t *source = (const uint8_t *) RSTRING_PTR(string); + size_t length = RSTRING_LEN(string); #ifdef PRISM_BUILD_DEBUG - size_t length = pm_string_length(&input); char* dup = xmalloc(length); - memcpy(dup, pm_string_source(&input), length); - pm_string_constant_init(&input, dup, length); + memcpy(dup, source, length); + source = (const uint8_t *) dup; #endif - VALUE value = dump_input(&input, options); + VALUE value = dump_input(source, length, options); if (pm_options_freeze(options)) rb_obj_freeze(value); #ifdef PRISM_BUILD_DEBUG @@ -429,7 +421,6 @@ dump(int argc, VALUE *argv, VALUE self) { #endif #endif - pm_string_cleanup(&input); pm_options_free(options); return value; @@ -445,14 +436,13 @@ dump(int argc, VALUE *argv, VALUE self) { */ static VALUE dump_file(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, options, &encoded_filepath); + pm_source_t *src = file_options(argc, argv, options, &encoded_filepath); - VALUE value = dump_input(&input, options); - pm_string_cleanup(&input); + VALUE value = dump_input(pm_source_source(src), pm_source_length(src), options); + pm_source_free(src); pm_options_free(options); return value; @@ -791,12 +781,12 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) { * the nodes and tokens. */ static VALUE -parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nodes) { +parse_lex_input(const uint8_t *input, size_t input_length, const pm_options_t *options, bool return_nodes) { pm_arena_t *arena = pm_arena_new(); - pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(arena, input, input_length, options); pm_parser_encoding_changed_callback_set(parser, parse_lex_encoding_changed_callback); - VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input)); + VALUE source_string = rb_str_new((const char *) input, input_length); VALUE offsets = rb_ary_new_capa(pm_parser_line_offsets(parser)->size); VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(pm_parser_start_line(parser)), offsets); @@ -858,12 +848,10 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod */ static VALUE lex(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); - string_options(argc, argv, &input, options); + VALUE string = string_options(argc, argv, options); - VALUE result = parse_lex_input(&input, options, false); - pm_string_cleanup(&input); + VALUE result = parse_lex_input((const uint8_t *) RSTRING_PTR(string), RSTRING_LEN(string), options, false); pm_options_free(options); return result; @@ -879,14 +867,13 @@ lex(int argc, VALUE *argv, VALUE self) { */ static VALUE lex_file(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, options, &encoded_filepath); + pm_source_t *src = file_options(argc, argv, options, &encoded_filepath); - VALUE value = parse_lex_input(&input, options, false); - pm_string_cleanup(&input); + VALUE value = parse_lex_input(pm_source_source(src), pm_source_length(src), options, false); + pm_source_free(src); pm_options_free(options); return value; @@ -900,9 +887,9 @@ lex_file(int argc, VALUE *argv, VALUE self) { * Parse the given input and return a ParseResult instance. */ static VALUE -parse_input(pm_string_t *input, const pm_options_t *options) { +parse_input(const uint8_t *input, size_t input_length, const pm_options_t *options) { pm_arena_t *arena = pm_arena_new(); - pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(arena, input, input_length, options); pm_node_t *node = pm_parse(parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); @@ -969,18 +956,19 @@ parse_input(pm_string_t *input, const pm_options_t *options) { */ static VALUE parse(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); - string_options(argc, argv, &input, options); + VALUE string = string_options(argc, argv, options); + + const uint8_t *source = (const uint8_t *) RSTRING_PTR(string); + size_t length = RSTRING_LEN(string); #ifdef PRISM_BUILD_DEBUG - size_t length = pm_string_length(&input); char* dup = xmalloc(length); - memcpy(dup, pm_string_source(&input), length); - pm_string_constant_init(&input, dup, length); + memcpy(dup, source, length); + source = (const uint8_t *) dup; #endif - VALUE value = parse_input(&input, options); + VALUE value = parse_input(source, length, options); #ifdef PRISM_BUILD_DEBUG #ifdef xfree_sized @@ -990,7 +978,6 @@ parse(int argc, VALUE *argv, VALUE self) { #endif #endif - pm_string_cleanup(&input); pm_options_free(options); return value; } @@ -1005,14 +992,13 @@ parse(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_file(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, options, &encoded_filepath); + pm_source_t *src = file_options(argc, argv, options, &encoded_filepath); - VALUE value = parse_input(&input, options); - pm_string_cleanup(&input); + VALUE value = parse_input(pm_source_source(src), pm_source_length(src), options); + pm_source_free(src); pm_options_free(options); return value; @@ -1022,9 +1008,9 @@ parse_file(int argc, VALUE *argv, VALUE self) { * Parse the given input and return nothing. */ static void -profile_input(pm_string_t *input, const pm_options_t *options) { +profile_input(const uint8_t *input, size_t input_length, const pm_options_t *options) { pm_arena_t *arena = pm_arena_new(); - pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(arena, input, input_length, options); pm_parse(parser); pm_parser_free(parser); @@ -1042,12 +1028,10 @@ profile_input(pm_string_t *input, const pm_options_t *options) { */ static VALUE profile(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); + VALUE string = string_options(argc, argv, options); - string_options(argc, argv, &input, options); - profile_input(&input, options); - pm_string_cleanup(&input); + profile_input((const uint8_t *) RSTRING_PTR(string), RSTRING_LEN(string), options); pm_options_free(options); return Qnil; @@ -1064,14 +1048,13 @@ profile(int argc, VALUE *argv, VALUE self) { */ static VALUE profile_file(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, options, &encoded_filepath); + pm_source_t *src = file_options(argc, argv, options, &encoded_filepath); - profile_input(&input, options); - pm_string_cleanup(&input); + profile_input(pm_source_source(src), pm_source_length(src), options); + pm_source_free(src); pm_options_free(options); return Qnil; @@ -1123,18 +1106,18 @@ parse_stream(int argc, VALUE *argv, VALUE self) { pm_options_t *options = pm_options_new(); extract_options(options, Qnil, keywords); + pm_source_t *src = pm_source_stream_new((void *) stream, parse_stream_fgets, parse_stream_eof); pm_arena_t *arena = pm_arena_new(); pm_parser_t *parser; - pm_buffer_t *buffer = pm_buffer_new(); - pm_node_t *node = pm_parse_stream(&parser, arena, buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, options); + pm_node_t *node = pm_parse_stream(&parser, arena, src, options); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); VALUE source = pm_source_new(parser, encoding, pm_options_freeze(options)); VALUE value = pm_ast_new(parser, node, encoding, source, pm_options_freeze(options)); VALUE result = parse_result_create(rb_cPrismParseResult, parser, value, encoding, source, pm_options_freeze(options)); - pm_buffer_free(buffer); + pm_source_free(src); pm_parser_free(parser); pm_arena_free(arena); pm_options_free(options); @@ -1146,9 +1129,9 @@ parse_stream(int argc, VALUE *argv, VALUE self) { * Parse the given input and return an array of Comment objects. */ static VALUE -parse_input_comments(pm_string_t *input, const pm_options_t *options) { +parse_input_comments(const uint8_t *input, size_t input_length, const pm_options_t *options) { pm_arena_t *arena = pm_arena_new(); - pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(arena, input, input_length, options); pm_parse(parser); rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); @@ -1172,12 +1155,10 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) { */ static VALUE parse_comments(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); - string_options(argc, argv, &input, options); + VALUE string = string_options(argc, argv, options); - VALUE result = parse_input_comments(&input, options); - pm_string_cleanup(&input); + VALUE result = parse_input_comments((const uint8_t *) RSTRING_PTR(string), RSTRING_LEN(string), options); pm_options_free(options); return result; @@ -1193,14 +1174,13 @@ parse_comments(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_file_comments(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, options, &encoded_filepath); + pm_source_t *src = file_options(argc, argv, options, &encoded_filepath); - VALUE value = parse_input_comments(&input, options); - pm_string_cleanup(&input); + VALUE value = parse_input_comments(pm_source_source(src), pm_source_length(src), options); + pm_source_free(src); pm_options_free(options); return value; @@ -1223,12 +1203,10 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_lex(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); - string_options(argc, argv, &input, options); + VALUE string = string_options(argc, argv, options); - VALUE value = parse_lex_input(&input, options, true); - pm_string_cleanup(&input); + VALUE value = parse_lex_input((const uint8_t *) RSTRING_PTR(string), RSTRING_LEN(string), options, true); pm_options_free(options); return value; @@ -1251,14 +1229,13 @@ parse_lex(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_lex_file(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, options, &encoded_filepath); + pm_source_t *src = file_options(argc, argv, options, &encoded_filepath); - VALUE value = parse_lex_input(&input, options, true); - pm_string_cleanup(&input); + VALUE value = parse_lex_input(pm_source_source(src), pm_source_length(src), options, true); + pm_source_free(src); pm_options_free(options); return value; @@ -1268,9 +1245,9 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) { * Parse the given input and return true if it parses without errors. */ static VALUE -parse_input_success_p(pm_string_t *input, const pm_options_t *options) { +parse_input_success_p(const uint8_t *input, size_t input_length, const pm_options_t *options) { pm_arena_t *arena = pm_arena_new(); - pm_parser_t *parser = pm_parser_new(arena, pm_string_source(input), pm_string_length(input), options); + pm_parser_t *parser = pm_parser_new(arena, input, input_length, options); pm_parse(parser); @@ -1291,12 +1268,10 @@ parse_input_success_p(pm_string_t *input, const pm_options_t *options) { */ static VALUE parse_success_p(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); - string_options(argc, argv, &input, options); + VALUE string = string_options(argc, argv, options); - VALUE result = parse_input_success_p(&input, options); - pm_string_cleanup(&input); + VALUE result = parse_input_success_p((const uint8_t *) RSTRING_PTR(string), RSTRING_LEN(string), options); pm_options_free(options); return result; @@ -1325,14 +1300,13 @@ parse_failure_p(int argc, VALUE *argv, VALUE self) { */ static VALUE parse_file_success_p(int argc, VALUE *argv, VALUE self) { - pm_string_t input; pm_options_t *options = pm_options_new(); VALUE encoded_filepath; - file_options(argc, argv, &input, options, &encoded_filepath); + pm_source_t *src = file_options(argc, argv, options, &encoded_filepath); - VALUE result = parse_input_success_p(&input, options); - pm_string_cleanup(&input); + VALUE result = parse_input_success_p(pm_source_source(src), pm_source_length(src), options); + pm_source_free(src); pm_options_free(options); return result; diff --git a/include/prism.h b/include/prism.h index d082e2f655..b342bb32c6 100644 --- a/include/prism.h +++ b/include/prism.h @@ -20,6 +20,7 @@ extern "C" { #include "prism/parser.h" #include "prism/prettyprint.h" #include "prism/serialize.h" +#include "prism/source.h" #include "prism/stream.h" #include "prism/string_query.h" #include "prism/version.h" diff --git a/include/prism/internal/source.h b/include/prism/internal/source.h new file mode 100644 index 0000000000..b3c2b55be3 --- /dev/null +++ b/include/prism/internal/source.h @@ -0,0 +1,72 @@ +#ifndef PRISM_INTERNAL_SOURCE_H +#define PRISM_INTERNAL_SOURCE_H + +#include "prism/source.h" +#include "prism/buffer.h" + +#include + +/* + * The type of source, which determines cleanup behavior. + */ +typedef enum { + /* Wraps existing constant memory, no cleanup. */ + PM_SOURCE_CONSTANT, + + /* Wraps existing shared memory (non-owning slice), no cleanup. */ + PM_SOURCE_SHARED, + + /* Owns a heap-allocated buffer, freed on cleanup. */ + PM_SOURCE_OWNED, + + /* Memory-mapped file, unmapped on cleanup. */ + PM_SOURCE_MAPPED, + + /* Stream source backed by a pm_buffer_t. */ + PM_SOURCE_STREAM +} pm_source_type_t; + +/* + * The internal representation of a source. + */ +struct pm_source_t { + /* A pointer to the start of the source data. */ + const uint8_t *source; + + /* The length of the source data in bytes. */ + size_t length; + + /* The type of the source. */ + pm_source_type_t type; + + /* Stream-specific data, only used for PM_SOURCE_STREAM sources. */ + struct { + /* The buffer that holds the accumulated stream data. */ + pm_buffer_t *buffer; + + /* The stream object to read from. */ + void *stream; + + /* The function to use to read from the stream. */ + pm_source_stream_fgets_t *fgets; + + /* The function to use to check if the stream is at EOF. */ + pm_source_stream_feof_t *feof; + + /* Whether the stream has reached EOF. */ + bool eof; + } stream; +}; + +/* + * Read from a stream into the source's internal buffer. This is used by + * pm_parse_stream to incrementally read the source. + */ +bool pm_source_stream_read(pm_source_t *source); + +/* + * Returns whether the stream source has reached EOF. + */ +bool pm_source_stream_eof(const pm_source_t *source); + +#endif diff --git a/include/prism/internal/strings.h b/include/prism/internal/strings.h index 573eade290..71b02020e3 100644 --- a/include/prism/internal/strings.h +++ b/include/prism/internal/strings.h @@ -14,12 +14,6 @@ */ void pm_string_shared_init(pm_string_t *string, const uint8_t *start, const uint8_t *end); -/* - * Ensure the string is owned. If it is not, then reinitialize it as owned and - * copy over the previous source. - */ -void pm_string_ensure_owned(pm_string_t *string); - /* * Compare the underlying lengths and bytes of two strings. Returns 0 if the * strings are equal, a negative number if the left string is less than the @@ -28,4 +22,9 @@ void pm_string_ensure_owned(pm_string_t *string); */ int pm_string_compare(const pm_string_t *left, const pm_string_t *right); +/* + * Free the associated memory of the given string. + */ +void pm_string_cleanup(pm_string_t *string); + #endif diff --git a/include/prism/serialize.h b/include/prism/serialize.h index dba54d75f1..786a1514bc 100644 --- a/include/prism/serialize.h +++ b/include/prism/serialize.h @@ -18,6 +18,7 @@ #include "prism/buffer.h" #include "prism/parser.h" +#include "prism/source.h" #include "prism/stream.h" /** @@ -40,16 +41,14 @@ PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, PRISM_EXPORTED_FUNCTION void pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data) PRISM_NONNULL(1, 2); /** - * Parse and serialize the AST represented by the source that is read out of the - * given stream into to the given buffer. + * Parse and serialize the AST represented by the given source into the given + * buffer. * * @param buffer The buffer to serialize to. - * @param stream The stream to parse. - * @param stream_fgets The function to use to read from the stream. - * @param stream_feof The function to use to tell if the stream has hit eof. + * @param source The source to parse. * @param data The optional data to pass to the parser. */ -PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) PRISM_NONNULL(1, 2); +PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, pm_source_t *source, const char *data) PRISM_NONNULL(1, 2); /** * Parse and serialize the comments in the given source to the given buffer. diff --git a/include/prism/source.h b/include/prism/source.h new file mode 100644 index 0000000000..897ce4b880 --- /dev/null +++ b/include/prism/source.h @@ -0,0 +1,138 @@ +/** + * @file source.h + * + * An opaque type representing the source code being parsed, regardless of + * origin (constant memory, file, memory-mapped file, or stream). + */ +#ifndef PRISM_SOURCE_H +#define PRISM_SOURCE_H + +#include "prism/compiler/exported.h" +#include "prism/compiler/filesystem.h" +#include "prism/compiler/nodiscard.h" +#include "prism/compiler/nonnull.h" + +#include +#include + +/** + * An opaque type representing source code being parsed. + */ +typedef struct pm_source_t pm_source_t; + +/** + * This function is used to retrieve a line of input from a stream. It closely + * mirrors that of fgets so that fgets can be used as the default + * implementation. + */ +typedef char * (pm_source_stream_fgets_t)(char *string, int size, void *stream); + +/** + * This function is used to check whether a stream is at EOF. It closely mirrors + * that of feof so that feof can be used as the default implementation. + */ +typedef int (pm_source_stream_feof_t)(void *stream); + +/** + * Represents the result of initializing a source from a file. + */ +typedef enum { + /** Indicates that the source was successfully initialized. */ + PM_SOURCE_INIT_SUCCESS = 0, + + /** + * Indicates a generic error from a source init function, where the type + * of error should be read from `errno` or `GetLastError()`. + */ + PM_SOURCE_INIT_ERROR_GENERIC = 1, + + /** + * Indicates that the file that was attempted to be opened was a directory. + */ + PM_SOURCE_INIT_ERROR_DIRECTORY = 2, + + /** + * Indicates that the file is not a regular file (e.g. a pipe or character + * device) and the caller should handle reading it. + */ + PM_SOURCE_INIT_ERROR_NON_REGULAR = 3 +} pm_source_init_result_t; + +/** + * Create a new source that wraps existing constant memory. The memory is not + * owned and will not be freed. + * + * @param data The pointer to the source data. + * @param length The length of the source data in bytes. + * @returns A new source, or NULL on allocation failure. + */ +PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_constant_new(const uint8_t *data, size_t length) PRISM_NODISCARD; + +/** + * Create a new source that wraps existing shared memory. The memory is not + * owned and will not be freed. Semantically a "slice" of another source. + * + * @param data The pointer to the source data. + * @param length The length of the source data in bytes. + * @returns A new source, or NULL on allocation failure. + */ +PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_shared_new(const uint8_t *data, size_t length) PRISM_NODISCARD; + +/** + * Create a new source by reading a file into a heap-allocated buffer. + * + * @param filepath The path to the file to read. + * @param result Out parameter for the result of the initialization. + * @returns A new source, or NULL on error (with result written to out param). + */ +PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_file_new(const char *filepath, pm_source_init_result_t *result) PRISM_NODISCARD PRISM_NONNULL(1, 2); + +/** + * Create a new source by memory-mapping a file. Falls back to file reading on + * platforms without mmap support. + * + * If the file is a non-regular file (e.g. a pipe or character device), + * PM_SOURCE_INIT_ERROR_NON_REGULAR is returned, allowing the caller to handle + * it appropriately (e.g. by reading it through their own I/O layer). + * + * @param filepath The path to the file to read. + * @param open_flags Additional flags to pass to open(2) (e.g. O_NONBLOCK). + * @param result Out parameter for the result of the initialization. + * @returns A new source, or NULL on error (with result written to out param). + */ +PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_mapped_new(const char *filepath, int open_flags, pm_source_init_result_t *result) PRISM_NODISCARD PRISM_NONNULL(1, 3); + +/** + * Create a new source by reading from a stream using the provided callbacks. + * + * @param stream The stream to read from. + * @param fgets The function to use to read from the stream. + * @param feof The function to use to check if the stream is at EOF. + * @returns A new source, or NULL on allocation failure. + */ +PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_stream_new(void *stream, pm_source_stream_fgets_t *fgets, pm_source_stream_feof_t *feof) PRISM_NODISCARD; + +/** + * Free the given source and any memory it owns. + * + * @param source The source to free. + */ +PRISM_EXPORTED_FUNCTION void pm_source_free(pm_source_t *source) PRISM_NONNULL(1); + +/** + * Returns the length of the source data in bytes. + * + * @param source The source to get the length of. + * @returns The length of the source data. + */ +PRISM_EXPORTED_FUNCTION size_t pm_source_length(const pm_source_t *source) PRISM_NONNULL(1); + +/** + * Returns a pointer to the source data. + * + * @param source The source to get the data of. + * @returns A pointer to the source data. + */ +PRISM_EXPORTED_FUNCTION const uint8_t * pm_source_source(const pm_source_t *source) PRISM_NONNULL(1); + +#endif diff --git a/include/prism/stream.h b/include/prism/stream.h index 7bb4271255..678322b442 100644 --- a/include/prism/stream.h +++ b/include/prism/stream.h @@ -10,36 +10,19 @@ #include "prism/compiler/nonnull.h" #include "prism/arena.h" -#include "prism/buffer.h" #include "prism/options.h" #include "prism/parser.h" - -/** - * This function is used in pm_parse_stream() to retrieve a line of input from a - * stream. It closely mirrors that of fgets so that fgets can be used as the - * default implementation. - */ -typedef char * (pm_parse_stream_fgets_t)(char *string, int size, void *stream); - -/** - * This function is used in pm_parse_stream to check whether a stream is EOF. - * It closely mirrors that of feof so that feof can be used as the - * default implementation. - */ -typedef int (pm_parse_stream_feof_t)(void *stream); +#include "prism/source.h" /** * Parse a stream of Ruby source and return the tree. * * @param parser The out parameter to write the parser to. * @param arena The arena to use for all AST-lifetime allocations. - * @param buffer The buffer to use. - * @param stream The stream to parse. - * @param stream_fgets The function to use to read from the stream. - * @param stream_feof The function to use to determine if the stream has hit eof. + * @param source The source to use, created via pm_source_stream_new. * @param options The optional options to use when parsing. * @returns The AST representing the source. */ -PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) PRISM_NONNULL(1, 2, 3); +PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_source_t *source, const pm_options_t *options) PRISM_NONNULL(1, 2, 3); #endif diff --git a/include/prism/strings.h b/include/prism/strings.h index ac2dd15d1e..c2f120d07a 100644 --- a/include/prism/strings.h +++ b/include/prism/strings.h @@ -7,7 +7,6 @@ #define PRISM_STRINGS_H #include "prism/compiler/exported.h" -#include "prism/compiler/filesystem.h" #include "prism/compiler/nonnull.h" #include @@ -31,24 +30,11 @@ typedef struct { /** This is a slice of another string, and should not be freed. */ PM_STRING_SHARED, - /** This string owns its memory, and should be freed using `pm_string_cleanup()`. */ - PM_STRING_OWNED, - -#ifdef PRISM_HAS_MMAP - /** This string is a memory-mapped file, and should be freed using `pm_string_cleanup()`. */ - PM_STRING_MAPPED -#endif + /** This string owns its memory, and should be freed internally. */ + PM_STRING_OWNED } type; } pm_string_t; -/** - * Returns the size of the pm_string_t struct. This is necessary to allocate the - * correct amount of memory in the FFI backend. - * - * @returns The size of the pm_string_t struct. - */ -PRISM_EXPORTED_FUNCTION size_t pm_string_sizeof(void); - /** * Initialize a constant string that doesn't own its memory source. * @@ -67,56 +53,6 @@ PRISM_EXPORTED_FUNCTION void pm_string_constant_init(pm_string_t *string, const */ PRISM_EXPORTED_FUNCTION void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length) PRISM_NONNULL(1, 2); -/** - * Represents the result of calling pm_string_mapped_init or - * pm_string_file_init. We need this additional information because there is - * not a platform-agnostic way to indicate that the file that was attempted to - * be opened was a directory. - */ -typedef enum { - /** Indicates that the string was successfully initialized. */ - PM_STRING_INIT_SUCCESS = 0, - - /** - * Indicates a generic error from a string_*_init function, where the type - * of error should be read from `errno` or `GetLastError()`. - */ - PM_STRING_INIT_ERROR_GENERIC = 1, - - /** - * Indicates that the file that was attempted to be opened was a directory. - */ - PM_STRING_INIT_ERROR_DIRECTORY = 2 -} pm_string_init_result_t; - -/** - * Read the file indicated by the filepath parameter into source and load its - * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_cleanup` when it is no longer used. - * - * We want to use demand paging as much as possible in order to avoid having to - * read the entire file into memory (which could be detrimental to performance - * for large files). This means that if we're on windows we'll use - * `MapViewOfFile`, on POSIX systems that have access to `mmap` we'll use - * `mmap`, and on other POSIX systems we'll use `read`. - * - * @param string The string to initialize. - * @param filepath The filepath to read. - * @returns The success of the read, indicated by the value of the enum. - */ -PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath) PRISM_NONNULL(1, 2); - -/** - * Read the file indicated by the filepath parameter into source and load its - * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_cleanup` when it is no longer used. - * - * @param string The string to initialize. - * @param filepath The filepath to read. - * @returns The success of the read, indicated by the value of the enum. - */ -PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath) PRISM_NONNULL(1, 2); - /** * Returns the length associated with the string. * @@ -133,11 +69,4 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string) PRISM */ PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string) PRISM_NONNULL(1); -/** - * Free the associated memory of the given string. - * - * @param string The string to free. - */ -PRISM_EXPORTED_FUNCTION void pm_string_cleanup(pm_string_t *string) PRISM_NONNULL(1); - #endif diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 5144ba72c4..163dafef32 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -88,9 +88,9 @@ def self.load_exported_functions_from(header, *functions, callbacks) raise "Could not find functions #{functions.inspect}" unless functions.empty? end - callback :pm_parse_stream_fgets_t, [:pointer, :int, :pointer], :pointer - callback :pm_parse_stream_feof_t, [:pointer], :int - enum :pm_string_init_result_t, %i[PM_STRING_INIT_SUCCESS PM_STRING_INIT_ERROR_GENERIC PM_STRING_INIT_ERROR_DIRECTORY] + callback :pm_source_stream_fgets_t, [:pointer, :int, :pointer], :pointer + callback :pm_source_stream_feof_t, [:pointer], :int + enum :pm_source_init_result_t, %i[PM_SOURCE_INIT_SUCCESS PM_SOURCE_INIT_ERROR_GENERIC PM_SOURCE_INIT_ERROR_DIRECTORY PM_SOURCE_INIT_ERROR_NON_REGULAR] enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE] load_exported_functions_from( @@ -107,7 +107,7 @@ def self.load_exported_functions_from(header, *functions, callbacks) "pm_serialize_lex", "pm_serialize_parse_lex", "pm_serialize_parse_success_p", - [:pm_parse_stream_fgets_t, :pm_parse_stream_feof_t] + [] ) load_exported_functions_from( @@ -128,13 +128,14 @@ def self.load_exported_functions_from(header, *functions, callbacks) ) load_exported_functions_from( - "prism/strings.h", - "pm_string_mapped_init", - "pm_string_cleanup", - "pm_string_source", - "pm_string_length", - "pm_string_sizeof", - [] + "prism/source.h", + "pm_source_file_new", + "pm_source_mapped_new", + "pm_source_stream_new", + "pm_source_free", + "pm_source_source", + "pm_source_length", + [:pm_source_stream_fgets_t, :pm_source_stream_feof_t] ) # This object represents a pm_buffer_t. We only use it as an opaque pointer, @@ -172,11 +173,9 @@ def self.with 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 # :nodoc: - SIZEOF = LibRubyParser.pm_string_sizeof - + # This object represents source code to be parsed. For strings it wraps a + # pointer directly; for files it uses a pm_source_t under the hood. + class PrismSource # :nodoc: PLATFORM_EXPECTS_UTF8 = RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i) @@ -193,7 +192,7 @@ def read @pointer.read_string(@length) end - # Yields a pm_string_t pointer to the given block. + # Yields a PrismSource backed by the given string to the block. def self.with_string(string) raise TypeError unless string.is_a?(String) @@ -207,32 +206,39 @@ def self.with_string(string) end end - # Yields a pm_string_t pointer to the given block. + # Yields a PrismSource to the given block, backed by a pm_source_t. def self.with_file(filepath) raise TypeError unless filepath.is_a?(String) # On Windows and Mac, it's expected that filepaths will be encoded in # UTF-8. If they are not, we need to convert them to UTF-8 before - # passing them into pm_string_mapped_init. + # passing them into pm_source_mapped_new. if PLATFORM_EXPECTS_UTF8 && (encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8 filepath = filepath.encode(Encoding::UTF_8) end - FFI::MemoryPointer.new(SIZEOF) do |pm_string| - case (result = LibRubyParser.pm_string_mapped_init(pm_string, filepath)) - when :PM_STRING_INIT_SUCCESS - pointer = LibRubyParser.pm_string_source(pm_string) - length = LibRubyParser.pm_string_length(pm_string) + FFI::MemoryPointer.new(:int) do |result_ptr| + pm_source = LibRubyParser.pm_source_mapped_new(filepath, 0, result_ptr) + result = LibRubyParser.enum_type(:pm_source_init_result_t)[result_ptr.read_int] + + case result + when :PM_SOURCE_INIT_SUCCESS + pointer = LibRubyParser.pm_source_source(pm_source) + length = LibRubyParser.pm_source_length(pm_source) return yield new(pointer, length, false) - when :PM_STRING_INIT_ERROR_GENERIC + when :PM_SOURCE_INIT_ERROR_GENERIC raise SystemCallError.new(filepath, FFI.errno) - when :PM_STRING_INIT_ERROR_DIRECTORY + when :PM_SOURCE_INIT_ERROR_DIRECTORY raise Errno::EISDIR.new(filepath) + when :PM_SOURCE_INIT_ERROR_NON_REGULAR + # Fall back to reading the file through Ruby IO for non-regular + # files (pipes, character devices, etc.) + return with_string(File.read(filepath)) { |string| yield string } else - raise "Unknown error initializing pm_string_t: #{result.inspect}" + raise "Unknown error initializing pm_source_t: #{result.inspect}" end ensure - LibRubyParser.pm_string_cleanup(pm_string) + LibRubyParser.pm_source_free(pm_source) if pm_source && !pm_source.null? end end end @@ -248,29 +254,29 @@ def self.with_file(filepath) class << self # Mirror the Prism.dump API by using the serialization API. def dump(source, **options) - LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) } + LibRubyParser::PrismSource.with_string(source) { |string| dump_common(string, options) } end # Mirror the Prism.dump_file API by using the serialization API. def dump_file(filepath, **options) options[:filepath] = filepath - LibRubyParser::PrismString.with_file(filepath) { |string| dump_common(string, options) } + LibRubyParser::PrismSource.with_file(filepath) { |string| dump_common(string, options) } end # Mirror the Prism.lex API by using the serialization API. def lex(code, **options) - LibRubyParser::PrismString.with_string(code) { |string| lex_common(string, code, options) } + LibRubyParser::PrismSource.with_string(code) { |string| lex_common(string, code, options) } end # Mirror the Prism.lex_file API by using the serialization API. def lex_file(filepath, **options) options[:filepath] = filepath - LibRubyParser::PrismString.with_file(filepath) { |string| lex_common(string, string.read, options) } + LibRubyParser::PrismSource.with_file(filepath) { |string| lex_common(string, string.read, options) } end # Mirror the Prism.parse API by using the serialization API. def parse(code, **options) - LibRubyParser::PrismString.with_string(code) { |string| parse_common(string, code, options) } + LibRubyParser::PrismSource.with_string(code) { |string| parse_common(string, code, options) } end # Mirror the Prism.parse_file API by using the serialization API. This uses @@ -278,7 +284,7 @@ def parse(code, **options) # when it is available. def parse_file(filepath, **options) options[:filepath] = filepath - LibRubyParser::PrismString.with_file(filepath) { |string| parse_common(string, string.read, options) } + LibRubyParser::PrismSource.with_file(filepath) { |string| parse_common(string, string.read, options) } end # Mirror the Prism.parse_stream API by using the serialization API. @@ -296,19 +302,19 @@ def parse_stream(stream, **options) eof_callback = -> (_) { stream.eof? } - # In the pm_serialize_parse_stream function it accepts a pointer to the - # IO object as a void* and then passes it through to the callback as the - # third argument, but it never touches it itself. As such, since we have - # 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, eof_callback, dump_options(options)) - Prism.load(source, buffer.read, options.fetch(:freeze, false)) + pm_source = LibRubyParser.pm_source_stream_new(nil, callback, eof_callback) + begin + LibRubyParser.pm_serialize_parse_stream(buffer.pointer, pm_source, dump_options(options)) + Prism.load(source, buffer.read, options.fetch(:freeze, false)) + ensure + LibRubyParser.pm_source_free(pm_source) if pm_source && !pm_source.null? + end end end # Mirror the Prism.parse_comments API by using the serialization API. def parse_comments(code, **options) - LibRubyParser::PrismString.with_string(code) { |string| parse_comments_common(string, code, options) } + LibRubyParser::PrismSource.with_string(code) { |string| parse_comments_common(string, code, options) } end # Mirror the Prism.parse_file_comments API by using the serialization @@ -316,23 +322,23 @@ def parse_comments(code, **options) # to use mmap when it is available. def parse_file_comments(filepath, **options) options[:filepath] = filepath - LibRubyParser::PrismString.with_file(filepath) { |string| parse_comments_common(string, string.read, options) } + LibRubyParser::PrismSource.with_file(filepath) { |string| parse_comments_common(string, string.read, options) } end # Mirror the Prism.parse_lex API by using the serialization API. def parse_lex(code, **options) - LibRubyParser::PrismString.with_string(code) { |string| parse_lex_common(string, code, options) } + LibRubyParser::PrismSource.with_string(code) { |string| parse_lex_common(string, code, options) } end # Mirror the Prism.parse_lex_file API by using the serialization API. def parse_lex_file(filepath, **options) options[:filepath] = filepath - LibRubyParser::PrismString.with_file(filepath) { |string| parse_lex_common(string, string.read, options) } + LibRubyParser::PrismSource.with_file(filepath) { |string| parse_lex_common(string, string.read, options) } end # Mirror the Prism.parse_success? API by using the serialization API. def parse_success?(code, **options) - LibRubyParser::PrismString.with_string(code) { |string| parse_file_success_common(string, options) } + LibRubyParser::PrismSource.with_string(code) { |string| parse_file_success_common(string, options) } end # Mirror the Prism.parse_failure? API by using the serialization API. @@ -343,7 +349,7 @@ def parse_failure?(code, **options) # Mirror the Prism.parse_file_success? API by using the serialization API. def parse_file_success?(filepath, **options) options[:filepath] = filepath - LibRubyParser::PrismString.with_file(filepath) { |string| parse_file_success_common(string, options) } + LibRubyParser::PrismSource.with_file(filepath) { |string| parse_file_success_common(string, options) } end # Mirror the Prism.parse_file_failure? API by using the serialization API. @@ -353,7 +359,7 @@ def parse_file_failure?(filepath, **options) # Mirror the Prism.profile API by using the serialization API. def profile(source, **options) - LibRubyParser::PrismString.with_string(source) do |string| + LibRubyParser::PrismSource.with_string(source) do |string| LibRubyParser::PrismBuffer.with do |buffer| LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options)) nil @@ -363,7 +369,7 @@ def profile(source, **options) # Mirror the Prism.profile_file API by using the serialization API. def profile_file(filepath, **options) - LibRubyParser::PrismString.with_file(filepath) do |string| + LibRubyParser::PrismSource.with_file(filepath) do |string| LibRubyParser::PrismBuffer.with do |buffer| options[:filepath] = filepath LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options)) diff --git a/rust/ruby-prism-sys/build/main.rs b/rust/ruby-prism-sys/build/main.rs index 722da06970..594c01ad9c 100644 --- a/rust/ruby-prism-sys/build/main.rs +++ b/rust/ruby-prism-sys/build/main.rs @@ -200,7 +200,6 @@ fn generate_bindings(ruby_include_path: &Path) -> bindgen::Bindings { .allowlist_function("pm_parser_warnings_each") .allowlist_function("pm_parser_warnings_size") .allowlist_function("pm_size_to_native") - .allowlist_function("pm_string_cleanup") .allowlist_function("pm_string_constant_init") .allowlist_function("pm_string_length") .allowlist_function("pm_string_source") diff --git a/rust/ruby-prism-sys/tests/utils_tests.rs b/rust/ruby-prism-sys/tests/utils_tests.rs index 9b9db446c2..c619765c63 100644 --- a/rust/ruby-prism-sys/tests/utils_tests.rs +++ b/rust/ruby-prism-sys/tests/utils_tests.rs @@ -1,4 +1,4 @@ -use std::ffi::{CStr, CString}; +use std::ffi::CStr; #[test] fn version_test() { @@ -11,93 +11,3 @@ fn version_test() { assert_eq!(&cstring.to_string_lossy(), "1.9.0"); } - -mod string { - use ruby_prism_sys::{ - pm_string_cleanup, pm_string_length, pm_string_source, pm_string_t, pm_string_t__bindgen_ty_1, - PM_STRING_CONSTANT, PM_STRING_MAPPED, PM_STRING_OWNED, PM_STRING_SHARED, - }; - - use super::*; - - struct S { - c_string: CString, - pm_string: pm_string_t, - } - - impl S { - fn start_ptr(&self) -> *const u8 { - self.c_string.as_ptr().cast::() - } - } - - fn make_string(string_type: pm_string_t__bindgen_ty_1) -> S { - let c_string = CString::new("0123456789012345").unwrap(); - - let pm_string = pm_string_t { - type_: string_type, - source: c_string.as_ptr().cast::(), - length: c_string.as_bytes().len(), - }; - - S { c_string, pm_string } - } - - #[test] - fn shared_string_test() { - let mut s = make_string(PM_STRING_SHARED); - - unsafe { - let len = pm_string_length(&raw const s.pm_string); - assert_eq!(len, 16); - - let result_start = pm_string_source(&raw const s.pm_string); - assert_eq!(s.start_ptr(), result_start); - - pm_string_cleanup(&raw mut s.pm_string); - } - } - - #[test] - fn owned_string_test() { - let s = make_string(PM_STRING_OWNED); - - unsafe { - let result_len = pm_string_length(&raw const s.pm_string); - assert_eq!(result_len, 16); - - let result_start = pm_string_source(&raw const s.pm_string); - assert_eq!(s.pm_string.source, result_start); - - // Don't drop the pm_string--we don't own it anymore! - } - } - - #[test] - fn constant_string_test() { - let mut s = make_string(PM_STRING_CONSTANT); - - unsafe { - let result_len = pm_string_length(&raw const s.pm_string); - assert_eq!(result_len, 16); - - let result_start = pm_string_source(&raw const s.pm_string); - assert_eq!(s.pm_string.source, result_start); - - pm_string_cleanup(&raw mut s.pm_string); - } - } - - #[test] - fn mapped_string_test() { - let s = make_string(PM_STRING_MAPPED); - - unsafe { - let result_len = pm_string_length(&raw const s.pm_string); - assert_eq!(result_len, 16); - - let result_start = pm_string_source(&raw const s.pm_string); - assert_eq!(s.pm_string.source, result_start); - } - } -} diff --git a/src/options.c b/src/options.c index 59f1dd4f17..314335be97 100644 --- a/src/options.c +++ b/src/options.c @@ -4,6 +4,7 @@ #include "prism/internal/allocator.h" #include "prism/internal/char.h" +#include "prism/internal/strings.h" #include #include diff --git a/src/prism.c b/src/prism.c index 39602fbfc2..514891a8b6 100644 --- a/src/prism.c +++ b/src/prism.c @@ -22,6 +22,7 @@ #include "prism/internal/parser.h" #include "prism/internal/regexp.h" #include "prism/internal/serialize.h" +#include "prism/internal/source.h" #include "prism/internal/static_literals.h" #include "prism/internal/strings.h" #include "prism/internal/strncasecmp.h" @@ -22699,60 +22700,6 @@ pm_parse(pm_parser_t *parser) { return node; } -/** - * Read into the stream until the gets callback returns false. If the last read - * line from the stream matches an __END__ marker, then halt and return false, - * otherwise return true. - */ -static bool -pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof) { -#define LINE_SIZE 4096 - char line[LINE_SIZE]; - - while (memset(line, '\n', LINE_SIZE), stream_fgets(line, LINE_SIZE, stream) != NULL) { - size_t length = LINE_SIZE; - while (length > 0 && line[length - 1] == '\n') length--; - - if (length == LINE_SIZE) { - // If we read a line that is the maximum size and it doesn't end - // with a newline, then we'll just append it to the buffer and - // continue reading. - length--; - pm_buffer_append_string(buffer, line, length); - continue; - } - - // Append the line to the buffer. - length--; - pm_buffer_append_string(buffer, line, length); - - // Check if the line matches the __END__ marker. If it does, then stop - // reading and return false. In most circumstances, this means we should - // stop reading from the stream so that the DATA constant can pick it - // up. - switch (length) { - case 7: - if (strncmp(line, "__END__", 7) == 0) return false; - break; - case 8: - if (strncmp(line, "__END__\n", 8) == 0) return false; - break; - case 9: - if (strncmp(line, "__END__\r\n", 9) == 0) return false; - break; - } - - // All data should be read via gets. If the string returned by gets - // _doesn't_ end with a newline, then we assume we hit EOF condition. - if (stream_feof(stream)) { - break; - } - } - - return true; -#undef LINE_SIZE -} - /** * Parse a stream of Ruby source and return the tree. * @@ -22760,19 +22707,19 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t * can stream stdin in to Ruby so we need to support a streaming API. */ pm_node_t * -pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) { - bool eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); +pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_source_t *source, const pm_options_t *options) { + bool eof = pm_source_stream_read(source); - pm_parser_t *tmp = pm_parser_new(arena, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + pm_parser_t *tmp = pm_parser_new(arena, pm_source_source(source), pm_source_length(source), options); pm_node_t *node = pm_parse(tmp); while (!eof && tmp->error_list.size > 0) { - eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof); + eof = pm_source_stream_read(source); pm_parser_free(tmp); pm_arena_cleanup(arena); - tmp = pm_parser_new(arena, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options); + tmp = pm_parser_new(arena, pm_source_source(source), pm_source_length(source), options); node = pm_parse(tmp); } @@ -22838,19 +22785,17 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons * given stream into to the given buffer. */ void -pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) { +pm_serialize_parse_stream(pm_buffer_t *buffer, pm_source_t *source, const char *data) { pm_arena_t arena = { 0 }; pm_parser_t *parser; pm_options_t options = { 0 }; pm_options_read(&options, data); - pm_buffer_t *parser_buffer = pm_buffer_new(); - pm_node_t *node = pm_parse_stream(&parser, &arena, parser_buffer, stream, stream_fgets, stream_feof, &options); + pm_node_t *node = pm_parse_stream(&parser, &arena, source, &options); pm_serialize_header(buffer); pm_serialize_content(parser, node, buffer); pm_buffer_append_byte(buffer, '\0'); - pm_buffer_free(parser_buffer); pm_parser_free(parser); pm_arena_cleanup(&arena); pm_options_cleanup(&options); diff --git a/src/source.c b/src/source.c new file mode 100644 index 0000000000..42f24ae82f --- /dev/null +++ b/src/source.c @@ -0,0 +1,483 @@ +#include "prism/internal/source.h" + +#include "prism/internal/allocator.h" +#include "prism/internal/buffer.h" + +#include +#include + +/* The following headers are necessary to read files using demand paging. */ +#ifdef _WIN32 +#include +#elif defined(_POSIX_MAPPED_FILES) +#include +#include +#include +#elif defined(PRISM_HAS_FILESYSTEM) +#include +#include +#endif + +static const uint8_t empty_source[] = ""; + +/** + * Allocate and initialize a pm_source_t with the given fields. + */ +static pm_source_t * +pm_source_alloc(const uint8_t *source, size_t length, pm_source_type_t type) { + pm_source_t *result = xmalloc(sizeof(pm_source_t)); + if (result == NULL) abort(); + + *result = (struct pm_source_t) { + .source = source, + .length = length, + .type = type + }; + + return result; +} + +/** + * Create a new source that wraps existing constant memory. + */ +pm_source_t * +pm_source_constant_new(const uint8_t *data, size_t length) { + return pm_source_alloc(data, length, PM_SOURCE_CONSTANT); +} + +/** + * Create a new source that wraps existing shared memory. + */ +pm_source_t * +pm_source_shared_new(const uint8_t *data, size_t length) { + return pm_source_alloc(data, length, PM_SOURCE_SHARED); +} + +#ifdef _WIN32 +/** + * Represents a file handle on Windows, where the path will need to be freed + * when the file is closed. + */ +typedef struct { + /** The path to the file, which will become allocated memory. */ + WCHAR *path; + + /** The size of the allocated path in bytes. */ + size_t path_size; + + /** The handle to the file, which will start as uninitialized memory. */ + HANDLE file; +} pm_source_file_handle_t; + +/** + * Open the file indicated by the filepath parameter for reading on Windows. + */ +static pm_source_init_result_t +pm_source_file_handle_open(pm_source_file_handle_t *handle, const char *filepath) { + int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0); + if (length == 0) return PM_SOURCE_INIT_ERROR_GENERIC; + + handle->path_size = sizeof(WCHAR) * ((size_t) length); + handle->path = xmalloc(handle->path_size); + if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) { + xfree_sized(handle->path, handle->path_size); + return PM_SOURCE_INIT_ERROR_GENERIC; + } + + handle->file = CreateFileW(handle->path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if (handle->file == INVALID_HANDLE_VALUE) { + pm_source_init_result_t result = PM_SOURCE_INIT_ERROR_GENERIC; + + if (GetLastError() == ERROR_ACCESS_DENIED) { + DWORD attributes = GetFileAttributesW(handle->path); + if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = PM_SOURCE_INIT_ERROR_DIRECTORY; + } + } + + xfree_sized(handle->path, handle->path_size); + return result; + } + + return PM_SOURCE_INIT_SUCCESS; +} + +/** + * Close the file handle and free the path. + */ +static void +pm_source_file_handle_close(pm_source_file_handle_t *handle) { + xfree_sized(handle->path, handle->path_size); + CloseHandle(handle->file); +} +#endif + +/** + * Create a new source by memory-mapping a file. + */ +pm_source_t * +pm_source_mapped_new(const char *filepath, int open_flags, pm_source_init_result_t *result) { +#ifdef _WIN32 + (void) open_flags; + + /* Open the file for reading. */ + pm_source_file_handle_t handle; + *result = pm_source_file_handle_open(&handle, filepath); + if (*result != PM_SOURCE_INIT_SUCCESS) return NULL; + + /* Get the file size. */ + DWORD file_size = GetFileSize(handle.file, NULL); + if (file_size == INVALID_FILE_SIZE) { + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* If the file is empty, then return a constant source. */ + if (file_size == 0) { + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(empty_source, 0, PM_SOURCE_CONSTANT); + } + + /* Create a mapping of the file. */ + HANDLE mapping = CreateFileMapping(handle.file, NULL, PAGE_READONLY, 0, 0, NULL); + if (mapping == NULL) { + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* Map the file into memory. */ + uint8_t *source = (uint8_t *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); + CloseHandle(mapping); + pm_source_file_handle_close(&handle); + + if (source == NULL) { + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(source, (size_t) file_size, PM_SOURCE_MAPPED); +#elif defined(_POSIX_MAPPED_FILES) + /* Open the file for reading. */ + int fd = open(filepath, O_RDONLY | open_flags); + if (fd == -1) { + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* Stat the file to get the file size. */ + struct stat sb; + if (fstat(fd, &sb) == -1) { + close(fd); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* Ensure it is a file and not a directory. */ + if (S_ISDIR(sb.st_mode)) { + close(fd); + *result = PM_SOURCE_INIT_ERROR_DIRECTORY; + return NULL; + } + + /* + * For non-regular files (pipes, character devices), return a specific + * error so the caller can handle reading through their own I/O layer. + */ + if (!S_ISREG(sb.st_mode)) { + close(fd); + *result = PM_SOURCE_INIT_ERROR_NON_REGULAR; + return NULL; + } + + /* mmap the file descriptor to virtually get the contents. */ + size_t size = (size_t) sb.st_size; + + if (size == 0) { + close(fd); + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(empty_source, 0, PM_SOURCE_CONSTANT); + } + + uint8_t *source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (source == MAP_FAILED) { + close(fd); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + close(fd); + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(source, size, PM_SOURCE_MAPPED); +#else + (void) open_flags; + return pm_source_file_new(filepath, result); +#endif +} + +/** + * Create a new source by reading a file into a heap-allocated buffer. + */ +pm_source_t * +pm_source_file_new(const char *filepath, pm_source_init_result_t *result) { +#ifdef _WIN32 + /* Open the file for reading. */ + pm_source_file_handle_t handle; + *result = pm_source_file_handle_open(&handle, filepath); + if (*result != PM_SOURCE_INIT_SUCCESS) return NULL; + + /* Get the file size. */ + const DWORD file_size = GetFileSize(handle.file, NULL); + if (file_size == INVALID_FILE_SIZE) { + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* If the file is empty, return a constant source. */ + if (file_size == 0) { + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(empty_source, 0, PM_SOURCE_CONSTANT); + } + + /* Create a buffer to read the file into. */ + uint8_t *source = xmalloc(file_size); + if (source == NULL) { + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* Read the contents of the file. */ + DWORD bytes_read; + if (!ReadFile(handle.file, source, file_size, &bytes_read, NULL)) { + xfree_sized(source, file_size); + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* Check the number of bytes read. */ + if (bytes_read != file_size) { + xfree_sized(source, file_size); + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + pm_source_file_handle_close(&handle); + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(source, (size_t) file_size, PM_SOURCE_OWNED); +#elif defined(PRISM_HAS_FILESYSTEM) + /* Open the file for reading. */ + int fd = open(filepath, O_RDONLY); + if (fd == -1) { + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* Stat the file to get the file size. */ + struct stat sb; + if (fstat(fd, &sb) == -1) { + close(fd); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + /* Ensure it is a file and not a directory. */ + if (S_ISDIR(sb.st_mode)) { + close(fd); + *result = PM_SOURCE_INIT_ERROR_DIRECTORY; + return NULL; + } + + /* Check the size to see if it's empty. */ + size_t size = (size_t) sb.st_size; + if (size == 0) { + close(fd); + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(empty_source, 0, PM_SOURCE_CONSTANT); + } + + const size_t length = (size_t) size; + uint8_t *source = xmalloc(length); + if (source == NULL) { + close(fd); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + ssize_t bytes_read = read(fd, source, length); + close(fd); + + if (bytes_read == -1 || (size_t) bytes_read != length) { + xfree_sized(source, length); + *result = PM_SOURCE_INIT_ERROR_GENERIC; + return NULL; + } + + *result = PM_SOURCE_INIT_SUCCESS; + return pm_source_alloc(source, length, PM_SOURCE_OWNED); +#else + (void) filepath; + *result = PM_SOURCE_INIT_ERROR_GENERIC; + perror("pm_source_file_new is not implemented for this platform"); + return NULL; +#endif +} + +/** + * Create a new source by reading from a stream. This allocates the source + * but does not read from the stream yet. Use pm_source_stream_read to read + * data. + */ +pm_source_t * +pm_source_stream_new(void *stream, pm_source_stream_fgets_t *fgets, pm_source_stream_feof_t *feof) { + pm_source_t *source = pm_source_alloc(NULL, 0, PM_SOURCE_STREAM); + source->stream.buffer = pm_buffer_new(); + source->stream.stream = stream; + source->stream.fgets = fgets; + source->stream.feof = feof; + source->stream.eof = false; + + return source; +} + +/** + * Read from the stream into the source's internal buffer until __END__ is + * encountered or EOF is reached. Updates the source pointer and length. + * + * Returns true if EOF was reached, false if __END__ was encountered. + */ +bool +pm_source_stream_read(pm_source_t *source) { + pm_buffer_t *buffer = source->stream.buffer; + +#define LINE_SIZE 4096 + char line[LINE_SIZE]; + + while (memset(line, '\n', LINE_SIZE), source->stream.fgets(line, LINE_SIZE, source->stream.stream) != NULL) { + size_t length = LINE_SIZE; + while (length > 0 && line[length - 1] == '\n') length--; + + if (length == LINE_SIZE) { + /* + * If we read a line that is the maximum size and it doesn't end + * with a newline, then we'll just append it to the buffer and + * continue reading. + */ + length--; + pm_buffer_append_string(buffer, line, length); + continue; + } + + /* Append the line to the buffer. */ + length--; + pm_buffer_append_string(buffer, line, length); + + /* + * Check if the line matches the __END__ marker. If it does, then stop + * reading and return false. In most circumstances, this means we should + * stop reading from the stream so that the DATA constant can pick it + * up. + */ + switch (length) { + case 7: + if (strncmp(line, "__END__", 7) == 0) { + source->source = (const uint8_t *) pm_buffer_value(buffer); + source->length = pm_buffer_length(buffer); + return false; + } + break; + case 8: + if (strncmp(line, "__END__\n", 8) == 0) { + source->source = (const uint8_t *) pm_buffer_value(buffer); + source->length = pm_buffer_length(buffer); + return false; + } + break; + case 9: + if (strncmp(line, "__END__\r\n", 9) == 0) { + source->source = (const uint8_t *) pm_buffer_value(buffer); + source->length = pm_buffer_length(buffer); + return false; + } + break; + } + + /* + * All data should be read via gets. If the string returned by gets + * _doesn't_ end with a newline, then we assume we hit EOF condition. + */ + if (source->stream.feof(source->stream.stream)) { + break; + } + } + +#undef LINE_SIZE + + source->stream.eof = true; + source->source = (const uint8_t *) pm_buffer_value(buffer); + source->length = pm_buffer_length(buffer); + return true; +} + +/** + * Returns whether the stream source has reached EOF. + */ +bool +pm_source_stream_eof(const pm_source_t *source) { + return source->stream.eof; +} + +/** + * Free the given source and any memory it owns. + */ +void +pm_source_free(pm_source_t *source) { + switch (source->type) { + case PM_SOURCE_CONSTANT: + case PM_SOURCE_SHARED: + /* No cleanup needed for the data. */ + break; + case PM_SOURCE_OWNED: + xfree_sized((void *) source->source, source->length); + break; + case PM_SOURCE_MAPPED: +#if defined(_WIN32) + if (source->length > 0) { + UnmapViewOfFile((void *) source->source); + } +#elif defined(_POSIX_MAPPED_FILES) + if (source->length > 0) { + munmap((void *) source->source, source->length); + } +#endif + break; + case PM_SOURCE_STREAM: + pm_buffer_free(source->stream.buffer); + break; + } + + xfree_sized(source, sizeof(pm_source_t)); +} + +/** + * Returns the length of the source data in bytes. + */ +size_t +pm_source_length(const pm_source_t *source) { + return source->length; +} + +/** + * Returns a pointer to the source data. + */ +const uint8_t * +pm_source_source(const pm_source_t *source) { + return source->source; +} diff --git a/src/strings.c b/src/strings.c index 88bb5ad24f..1a37a9d80e 100644 --- a/src/strings.c +++ b/src/strings.c @@ -6,29 +6,6 @@ #include #include -/* The following headers are necessary to read files using demand paging. */ -#ifdef _WIN32 -#include -#elif defined(_POSIX_MAPPED_FILES) -#include -#include -#include -#elif defined(PRISM_HAS_FILESYSTEM) -#include -#include -#endif - -static const uint8_t empty_source[] = ""; - -/** - * Returns the size of the pm_string_t struct. This is necessary to allocate the - * correct amount of memory in the FFI backend. - */ -size_t -pm_string_sizeof(void) { - return sizeof(pm_string_t); -} - /** * Initialize a shared string that is based on initial input. */ @@ -67,282 +44,6 @@ pm_string_constant_init(pm_string_t *string, const char *source, size_t length) }; } -#ifdef _WIN32 -/** - * Represents a file handle on Windows, where the path will need to be freed - * when the file is closed. - */ -typedef struct { - /** The path to the file, which will become allocated memory. */ - WCHAR *path; - - /** The handle to the file, which will start as uninitialized memory. */ - HANDLE file; -} pm_string_file_handle_t; - -/** - * Open the file indicated by the filepath parameter for reading on Windows. - * Perform any kind of normalization that needs to happen on the filepath. - */ -static pm_string_init_result_t -pm_string_file_handle_open(pm_string_file_handle_t *handle, const char *filepath) { - int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0); - if (length == 0) return PM_STRING_INIT_ERROR_GENERIC; - - const size_t path_size = sizeof(WCHAR) * ((size_t) length); - handle->path = xmalloc(path_size); - if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) { - xfree_sized(handle->path, path_size); - return PM_STRING_INIT_ERROR_GENERIC; - } - - handle->file = CreateFileW(handle->path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); - if (handle->file == INVALID_HANDLE_VALUE) { - pm_string_init_result_t result = PM_STRING_INIT_ERROR_GENERIC; - - if (GetLastError() == ERROR_ACCESS_DENIED) { - DWORD attributes = GetFileAttributesW(handle->path); - if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { - result = PM_STRING_INIT_ERROR_DIRECTORY; - } - } - - xfree_sized(handle->path, path_size); - return result; - } - - return PM_STRING_INIT_SUCCESS; -} - -/** - * Close the file handle and free the path. - */ -static void -pm_string_file_handle_close(pm_string_file_handle_t *handle) { - xfree(handle->path); - CloseHandle(handle->file); -} -#endif - -/** - * Read the file indicated by the filepath parameter into source and load its - * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_cleanup` when it is no longer used. - * - * We want to use demand paging as much as possible in order to avoid having to - * read the entire file into memory (which could be detrimental to performance - * for large files). This means that if we're on windows we'll use - * `MapViewOfFile`, on POSIX systems that have access to `mmap` we'll use - * `mmap`, and on other POSIX systems we'll use `read`. - */ -pm_string_init_result_t -pm_string_mapped_init(pm_string_t *string, const char *filepath) { -#ifdef _WIN32 - // Open the file for reading. - pm_string_file_handle_t handle; - pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath); - if (result != PM_STRING_INIT_SUCCESS) return result; - - // Get the file size. - DWORD file_size = GetFileSize(handle.file, NULL); - if (file_size == INVALID_FILE_SIZE) { - pm_string_file_handle_close(&handle); - return PM_STRING_INIT_ERROR_GENERIC; - } - - // If the file is empty, then we don't need to do anything else, we'll set - // the source to a constant empty string and return. - if (file_size == 0) { - pm_string_file_handle_close(&handle); - *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 }; - return PM_STRING_INIT_SUCCESS; - } - - // Create a mapping of the file. - HANDLE mapping = CreateFileMapping(handle.file, NULL, PAGE_READONLY, 0, 0, NULL); - if (mapping == NULL) { - pm_string_file_handle_close(&handle); - return PM_STRING_INIT_ERROR_GENERIC; - } - - // Map the file into memory. - uint8_t *source = (uint8_t *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); - CloseHandle(mapping); - pm_string_file_handle_close(&handle); - - if (source == NULL) { - return PM_STRING_INIT_ERROR_GENERIC; - } - - *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = (size_t) file_size }; - return PM_STRING_INIT_SUCCESS; -#elif defined(_POSIX_MAPPED_FILES) - // Open the file for reading - int fd = open(filepath, O_RDONLY); - if (fd == -1) { - return PM_STRING_INIT_ERROR_GENERIC; - } - - // Stat the file to get the file size - struct stat sb; - if (fstat(fd, &sb) == -1) { - close(fd); - return PM_STRING_INIT_ERROR_GENERIC; - } - - // Ensure it is a file and not a directory - if (S_ISDIR(sb.st_mode)) { - close(fd); - return PM_STRING_INIT_ERROR_DIRECTORY; - } - - // mmap the file descriptor to virtually get the contents - size_t size = (size_t) sb.st_size; - uint8_t *source = NULL; - - if (size == 0) { - close(fd); - *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 }; - return PM_STRING_INIT_SUCCESS; - } - - source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - if (source == MAP_FAILED) { - close(fd); - return PM_STRING_INIT_ERROR_GENERIC; - } - - close(fd); - *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = size }; - return PM_STRING_INIT_SUCCESS; -#else - return pm_string_file_init(string, filepath); -#endif -} - -/** - * Read the file indicated by the filepath parameter into source and load its - * contents and size into the given `pm_string_t`. The given `pm_string_t` - * should be freed using `pm_string_cleanup` when it is no longer used. - */ -pm_string_init_result_t -pm_string_file_init(pm_string_t *string, const char *filepath) { -#ifdef _WIN32 - // Open the file for reading. - pm_string_file_handle_t handle; - pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath); - if (result != PM_STRING_INIT_SUCCESS) return result; - - // Get the file size. - const DWORD file_size = GetFileSize(handle.file, NULL); - if (file_size == INVALID_FILE_SIZE) { - pm_string_file_handle_close(&handle); - return PM_STRING_INIT_ERROR_GENERIC; - } - - // If the file is empty, then we don't need to do anything else, we'll set - // the source to a constant empty string and return. - if (file_size == 0) { - pm_string_file_handle_close(&handle); - *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 }; - return PM_STRING_INIT_SUCCESS; - } - - // Create a buffer to read the file into. - uint8_t *source = xmalloc(file_size); - if (source == NULL) { - pm_string_file_handle_close(&handle); - return PM_STRING_INIT_ERROR_GENERIC; - } - - // Read the contents of the file - DWORD bytes_read; - if (!ReadFile(handle.file, source, file_size, &bytes_read, NULL)) { - pm_string_file_handle_close(&handle); - return PM_STRING_INIT_ERROR_GENERIC; - } - - // Check the number of bytes read - if (bytes_read != file_size) { - xfree_sized(source, file_size); - pm_string_file_handle_close(&handle); - return PM_STRING_INIT_ERROR_GENERIC; - } - - pm_string_file_handle_close(&handle); - *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size }; - return PM_STRING_INIT_SUCCESS; -#elif defined(PRISM_HAS_FILESYSTEM) - // Open the file for reading - int fd = open(filepath, O_RDONLY); - if (fd == -1) { - return PM_STRING_INIT_ERROR_GENERIC; - } - - // Stat the file to get the file size - struct stat sb; - if (fstat(fd, &sb) == -1) { - close(fd); - return PM_STRING_INIT_ERROR_GENERIC; - } - - // Ensure it is a file and not a directory - if (S_ISDIR(sb.st_mode)) { - close(fd); - return PM_STRING_INIT_ERROR_DIRECTORY; - } - - // Check the size to see if it's empty - size_t size = (size_t) sb.st_size; - if (size == 0) { - close(fd); - *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 }; - return PM_STRING_INIT_SUCCESS; - } - - const size_t length = (size_t) size; - uint8_t *source = xmalloc(length); - if (source == NULL) { - close(fd); - return PM_STRING_INIT_ERROR_GENERIC; - } - - long bytes_read = (long) read(fd, source, length); - close(fd); - - if (bytes_read == -1) { - xfree_sized(source, length); - return PM_STRING_INIT_ERROR_GENERIC; - } - - *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = length }; - return PM_STRING_INIT_SUCCESS; -#else - (void) string; - (void) filepath; - perror("pm_string_file_init is not implemented for this platform"); - return PM_STRING_INIT_ERROR_GENERIC; -#endif -} - -/** - * Ensure the string is owned. If it is not, then reinitialize it as owned and - * copy over the previous source. - */ -void -pm_string_ensure_owned(pm_string_t *string) { - if (string->type == PM_STRING_OWNED) return; - - size_t length = pm_string_length(string); - const uint8_t *source = pm_string_source(string); - - uint8_t *memory = xmalloc(length); - if (!memory) return; - - pm_string_owned_init(string, memory, length); - memcpy((void *) string->source, source, length); -} - /** * Compare the underlying lengths and bytes of two strings. Returns 0 if the * strings are equal, a negative number if the left string is less than the @@ -384,17 +85,7 @@ pm_string_source(const pm_string_t *string) { */ void pm_string_cleanup(pm_string_t *string) { - void *memory = (void *) string->source; - if (string->type == PM_STRING_OWNED) { - xfree(memory); -#ifdef PRISM_HAS_MMAP - } else if (string->type == PM_STRING_MAPPED && string->length) { -#if defined(_WIN32) - UnmapViewOfFile(memory); -#elif defined(_POSIX_MAPPED_FILES) - munmap(memory, string->length); -#endif -#endif /* PRISM_HAS_MMAP */ + xfree((void *) string->source); } } From 603e482c105368f949dd27fed104f1e97257a0e8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 13:23:03 -0400 Subject: [PATCH 241/289] Use xfree_sized everywhere possible --- src/arena.c | 2 +- src/integer.c | 2 +- src/options.c | 2 +- src/prism.c | 4 ++-- src/strings.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/arena.c b/src/arena.c index 7ae02715df..64a731649d 100644 --- a/src/arena.c +++ b/src/arena.c @@ -113,5 +113,5 @@ pm_arena_cleanup(pm_arena_t *arena) { void pm_arena_free(pm_arena_t *arena) { pm_arena_cleanup(arena); - xfree(arena); + xfree_sized(arena, sizeof(pm_arena_t)); } diff --git a/src/integer.c b/src/integer.c index 1b69dbdceb..2190ae6e26 100644 --- a/src/integer.c +++ b/src/integer.c @@ -17,7 +17,7 @@ static void pm_integer_free(pm_integer_t *integer) { if (integer->values) { - xfree(integer->values); + xfree_sized(integer->values, integer->length * sizeof(uint32_t)); } } diff --git a/src/options.c b/src/options.c index 314335be97..8973c933f8 100644 --- a/src/options.c +++ b/src/options.c @@ -49,7 +49,7 @@ pm_options_cleanup(pm_options_t *options) { void pm_options_free(pm_options_t *options) { pm_options_cleanup(options); - xfree(options); + xfree_sized(options, sizeof(pm_options_t)); } /** diff --git a/src/prism.c b/src/prism.c index 514891a8b6..b43b8ddc1d 100644 --- a/src/prism.c +++ b/src/prism.c @@ -2285,7 +2285,7 @@ pm_integer_arena_move(pm_arena_t *arena, pm_integer_t *integer) { size_t byte_size = integer->length * sizeof(uint32_t); uint32_t *old_values = integer->values; integer->values = (uint32_t *) pm_arena_memdup(arena, old_values, byte_size, PRISM_ALIGNOF(uint32_t)); - xfree(old_values); + xfree_sized(old_values, byte_size); } } @@ -22525,7 +22525,7 @@ pm_parser_cleanup(pm_parser_t *parser) { void pm_parser_free(pm_parser_t *parser) { pm_parser_cleanup(parser); - xfree(parser); + xfree_sized(parser, sizeof(pm_parser_t)); } /** diff --git a/src/strings.c b/src/strings.c index 1a37a9d80e..f140b82ad9 100644 --- a/src/strings.c +++ b/src/strings.c @@ -86,6 +86,6 @@ pm_string_source(const pm_string_t *string) { void pm_string_cleanup(pm_string_t *string) { if (string->type == PM_STRING_OWNED) { - xfree((void *) string->source); + xfree_sized((void *) string->source, string->length); } } From 0c6494a3e1cfd00fde7b7d6bb70467b106980e98 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 14:24:47 -0400 Subject: [PATCH 242/289] pm_source_owned_new --- include/prism/source.h | 16 +++++++++++++--- src/source.c | 8 ++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/prism/source.h b/include/prism/source.h index 897ce4b880..2f29845578 100644 --- a/include/prism/source.h +++ b/include/prism/source.h @@ -64,7 +64,7 @@ typedef enum { * * @param data The pointer to the source data. * @param length The length of the source data in bytes. - * @returns A new source, or NULL on allocation failure. + * @returns A new source. Aborts on allocation failure. */ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_constant_new(const uint8_t *data, size_t length) PRISM_NODISCARD; @@ -74,10 +74,20 @@ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_constant_new(const uint8_t *data * * @param data The pointer to the source data. * @param length The length of the source data in bytes. - * @returns A new source, or NULL on allocation failure. + * @returns A new source. Aborts on allocation failure. */ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_shared_new(const uint8_t *data, size_t length) PRISM_NODISCARD; +/** + * Create a new source that owns its memory. The memory will be freed with + * xfree when the source is freed. + * + * @param data The pointer to the heap-allocated source data. + * @param length The length of the source data in bytes. + * @returns A new source. Aborts on allocation failure. + */ +PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_owned_new(uint8_t *data, size_t length) PRISM_NODISCARD; + /** * Create a new source by reading a file into a heap-allocated buffer. * @@ -108,7 +118,7 @@ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_mapped_new(const char *filepath, * @param stream The stream to read from. * @param fgets The function to use to read from the stream. * @param feof The function to use to check if the stream is at EOF. - * @returns A new source, or NULL on allocation failure. + * @returns A new source. Aborts on allocation failure. */ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_stream_new(void *stream, pm_source_stream_fgets_t *fgets, pm_source_stream_feof_t *feof) PRISM_NODISCARD; diff --git a/src/source.c b/src/source.c index 42f24ae82f..f61cb19c1b 100644 --- a/src/source.c +++ b/src/source.c @@ -53,6 +53,14 @@ pm_source_shared_new(const uint8_t *data, size_t length) { return pm_source_alloc(data, length, PM_SOURCE_SHARED); } +/** + * Create a new source that owns its memory. + */ +pm_source_t * +pm_source_owned_new(uint8_t *data, size_t length) { + return pm_source_alloc(data, length, PM_SOURCE_OWNED); +} + #ifdef _WIN32 /** * Represents a file handle on Windows, where the path will need to be freed From eb398af793177e78447f142a9b824227aecbde94 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 14:39:34 -0400 Subject: [PATCH 243/289] Revert xfree_sized for integer --- src/integer.c | 2 +- src/prism.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/integer.c b/src/integer.c index 2190ae6e26..1b69dbdceb 100644 --- a/src/integer.c +++ b/src/integer.c @@ -17,7 +17,7 @@ static void pm_integer_free(pm_integer_t *integer) { if (integer->values) { - xfree_sized(integer->values, integer->length * sizeof(uint32_t)); + xfree(integer->values); } } diff --git a/src/prism.c b/src/prism.c index b43b8ddc1d..db2a331c00 100644 --- a/src/prism.c +++ b/src/prism.c @@ -2285,7 +2285,7 @@ pm_integer_arena_move(pm_arena_t *arena, pm_integer_t *integer) { size_t byte_size = integer->length * sizeof(uint32_t); uint32_t *old_values = integer->values; integer->values = (uint32_t *) pm_arena_memdup(arena, old_values, byte_size, PRISM_ALIGNOF(uint32_t)); - xfree_sized(old_values, byte_size); + xfree(old_values); } } From 75eb63e10261b6f7e0ecf04ecea48331e24f9abd Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 14:41:16 -0400 Subject: [PATCH 244/289] Fix up gemspec build --- prism.gemspec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/prism.gemspec b/prism.gemspec index 5db6327813..47f96fffc3 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -79,6 +79,7 @@ Gem::Specification.new do |spec| "include/prism/internal/parser.h", "include/prism/internal/regexp.h", "include/prism/internal/serialize.h", + "include/prism/internal/source.h", "include/prism/internal/static_literals.h", "include/prism/internal/strncasecmp.h", "include/prism/internal/strings.h", @@ -100,6 +101,7 @@ Gem::Specification.new do |spec| "include/prism/parser.h", "include/prism/prettyprint.h", "include/prism/serialize.h", + "include/prism/source.h", "include/prism/stream.h", "include/prism/string_query.h", "include/prism/strings.h", @@ -210,6 +212,7 @@ Gem::Specification.new do |spec| "src/prism.c", "src/regexp.c", "src/serialize.c", + "src/source.c", "src/static_literals.c", "src/string_query.c", "src/strings.c", From b5683c8708feb032728fa90295b3a0986aedba11 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 15:16:12 -0400 Subject: [PATCH 245/289] Fix up FFI in Ractors reading internal ivar --- lib/prism/ffi.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 163dafef32..6b9bde51ea 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -90,9 +90,14 @@ def self.load_exported_functions_from(header, *functions, callbacks) callback :pm_source_stream_fgets_t, [:pointer, :int, :pointer], :pointer callback :pm_source_stream_feof_t, [:pointer], :int - enum :pm_source_init_result_t, %i[PM_SOURCE_INIT_SUCCESS PM_SOURCE_INIT_ERROR_GENERIC PM_SOURCE_INIT_ERROR_DIRECTORY PM_SOURCE_INIT_ERROR_NON_REGULAR] + pm_source_init_result_values = %i[PM_SOURCE_INIT_SUCCESS PM_SOURCE_INIT_ERROR_GENERIC PM_SOURCE_INIT_ERROR_DIRECTORY PM_SOURCE_INIT_ERROR_NON_REGULAR] + enum :pm_source_init_result_t, pm_source_init_result_values enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE] + # Ractor-safe lookup table for pm_source_init_result_t, since FFI's + # enum_type accesses module instance variables that are not shareable. + SOURCE_INIT_RESULT = pm_source_init_result_values.freeze + load_exported_functions_from( "prism/version.h", "pm_version", @@ -219,9 +224,8 @@ def self.with_file(filepath) FFI::MemoryPointer.new(:int) do |result_ptr| pm_source = LibRubyParser.pm_source_mapped_new(filepath, 0, result_ptr) - result = LibRubyParser.enum_type(:pm_source_init_result_t)[result_ptr.read_int] - case result + case SOURCE_INIT_RESULT[result_ptr.read_int] when :PM_SOURCE_INIT_SUCCESS pointer = LibRubyParser.pm_source_source(pm_source) length = LibRubyParser.pm_source_length(pm_source) @@ -235,7 +239,7 @@ def self.with_file(filepath) # files (pipes, character devices, etc.) return with_string(File.read(filepath)) { |string| yield string } else - raise "Unknown error initializing pm_source_t: #{result.inspect}" + raise "Unknown error initializing pm_source_t: #{result_ptr.read_int}" end ensure LibRubyParser.pm_source_free(pm_source) if pm_source && !pm_source.null? From eb1d518736f5b497a6c10b8fee2a175a1d5c61da Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 15:58:26 -0400 Subject: [PATCH 246/289] Rename strings to stringy because of linux conflicts --- include/prism/internal/{strings.h => stringy.h} | 6 +++--- include/prism/options.h | 2 +- include/prism/{strings.h => stringy.h} | 6 +++--- prism.gemspec | 6 +++--- src/options.c | 2 +- src/prism.c | 2 +- src/regexp.c | 2 +- src/static_literals.c | 2 +- src/{strings.c => stringy.c} | 2 +- templates/include/prism/ast.h.erb | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) rename include/prism/internal/{strings.h => stringy.h} (89%) rename include/prism/{strings.h => stringy.h} (96%) rename src/{strings.c => stringy.c} (98%) diff --git a/include/prism/internal/strings.h b/include/prism/internal/stringy.h similarity index 89% rename from include/prism/internal/strings.h rename to include/prism/internal/stringy.h index 71b02020e3..1aaa23ea75 100644 --- a/include/prism/internal/strings.h +++ b/include/prism/internal/stringy.h @@ -1,7 +1,7 @@ -#ifndef PRISM_INTERNAL_STRINGS_H -#define PRISM_INTERNAL_STRINGS_H +#ifndef PRISM_INTERNAL_STRINGY_H +#define PRISM_INTERNAL_STRINGY_H -#include "prism/strings.h" +#include "prism/stringy.h" /* * Defines an empty string. This is useful for initializing a string that will diff --git a/include/prism/options.h b/include/prism/options.h index 37a713095e..2b823aebff 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -10,7 +10,7 @@ #include "prism/compiler/nodiscard.h" #include "prism/compiler/nonnull.h" -#include "prism/strings.h" +#include "prism/stringy.h" #include #include diff --git a/include/prism/strings.h b/include/prism/stringy.h similarity index 96% rename from include/prism/strings.h rename to include/prism/stringy.h index c2f120d07a..0d64387ac3 100644 --- a/include/prism/strings.h +++ b/include/prism/stringy.h @@ -1,10 +1,10 @@ /** - * @file strings.h + * @file stringy.h * * A generic string type that can have various ownership semantics. */ -#ifndef PRISM_STRINGS_H -#define PRISM_STRINGS_H +#ifndef PRISM_STRINGY_H +#define PRISM_STRINGY_H #include "prism/compiler/exported.h" #include "prism/compiler/nonnull.h" diff --git a/prism.gemspec b/prism.gemspec index 47f96fffc3..d489a37af4 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -82,7 +82,7 @@ Gem::Specification.new do |spec| "include/prism/internal/source.h", "include/prism/internal/static_literals.h", "include/prism/internal/strncasecmp.h", - "include/prism/internal/strings.h", + "include/prism/internal/stringy.h", "include/prism/internal/strpbrk.h", "include/prism/internal/tokens.h", "include/prism/arena.h", @@ -104,7 +104,7 @@ Gem::Specification.new do |spec| "include/prism/source.h", "include/prism/stream.h", "include/prism/string_query.h", - "include/prism/strings.h", + "include/prism/stringy.h", "include/prism/version.h", "lib/prism.rb", "lib/prism/compiler.rb", @@ -215,7 +215,7 @@ Gem::Specification.new do |spec| "src/source.c", "src/static_literals.c", "src/string_query.c", - "src/strings.c", + "src/stringy.c", "src/strncasecmp.c", "src/strpbrk.c", "src/tokens.c" diff --git a/src/options.c b/src/options.c index 8973c933f8..b589865a2a 100644 --- a/src/options.c +++ b/src/options.c @@ -4,7 +4,7 @@ #include "prism/internal/allocator.h" #include "prism/internal/char.h" -#include "prism/internal/strings.h" +#include "prism/internal/stringy.h" #include #include diff --git a/src/prism.c b/src/prism.c index db2a331c00..53c33cee39 100644 --- a/src/prism.c +++ b/src/prism.c @@ -24,7 +24,7 @@ #include "prism/internal/serialize.h" #include "prism/internal/source.h" #include "prism/internal/static_literals.h" -#include "prism/internal/strings.h" +#include "prism/internal/stringy.h" #include "prism/internal/strncasecmp.h" #include "prism/internal/strpbrk.h" #include "prism/internal/tokens.h" diff --git a/src/regexp.c b/src/regexp.c index 05ef3b6b41..cc17aa4d09 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -8,7 +8,7 @@ #include "prism/internal/encoding.h" #include "prism/internal/memchr.h" #include "prism/internal/parser.h" -#include "prism/internal/strings.h" +#include "prism/internal/stringy.h" #include "prism/internal/strncasecmp.h" #include diff --git a/src/static_literals.c b/src/static_literals.c index 0a8ef62b2c..9af1eadf5d 100644 --- a/src/static_literals.c +++ b/src/static_literals.c @@ -7,7 +7,7 @@ #include "prism/internal/buffer.h" #include "prism/internal/integer.h" #include "prism/internal/isinf.h" -#include "prism/internal/strings.h" +#include "prism/internal/stringy.h" #include #include diff --git a/src/strings.c b/src/stringy.c similarity index 98% rename from src/strings.c rename to src/stringy.c index f140b82ad9..d6f4c4a777 100644 --- a/src/strings.c +++ b/src/stringy.c @@ -1,4 +1,4 @@ -#include "prism/internal/strings.h" +#include "prism/internal/stringy.h" #include "prism/internal/allocator.h" diff --git a/templates/include/prism/ast.h.erb b/templates/include/prism/ast.h.erb index 1909618fc1..3b3be25e76 100644 --- a/templates/include/prism/ast.h.erb +++ b/templates/include/prism/ast.h.erb @@ -14,7 +14,7 @@ #include "prism/arena.h" #include "prism/constant_pool.h" #include "prism/integer.h" -#include "prism/strings.h" +#include "prism/stringy.h" #include #include From ba16ae22561179998e4208e4c37262b47f693c11 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 16:49:16 -0400 Subject: [PATCH 247/289] Move PRISM_NODISCARD to the correct position --- include/prism/arena.h | 2 +- include/prism/buffer.h | 2 +- include/prism/options.h | 2 +- include/prism/parser.h | 2 +- include/prism/source.h | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/prism/arena.h b/include/prism/arena.h index a637e9cef3..e1fa8fc6ad 100644 --- a/include/prism/arena.h +++ b/include/prism/arena.h @@ -25,7 +25,7 @@ typedef struct pm_arena_t pm_arena_t; * the caller to free the arena using pm_arena_free when it is no longer * needed. */ -PRISM_EXPORTED_FUNCTION pm_arena_t * pm_arena_new(void) PRISM_NODISCARD; +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_arena_t * pm_arena_new(void); /** * Frees both the held memory and the arena itself. diff --git a/include/prism/buffer.h b/include/prism/buffer.h index 12844d60ff..24b572d2c3 100644 --- a/include/prism/buffer.h +++ b/include/prism/buffer.h @@ -24,7 +24,7 @@ typedef struct pm_buffer_t pm_buffer_t; * @returns A pointer to the initialized buffer. The caller is responsible for * freeing the buffer with pm_buffer_free. */ -PRISM_EXPORTED_FUNCTION pm_buffer_t * pm_buffer_new(void) PRISM_NODISCARD; +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_buffer_t * pm_buffer_new(void); /** * Free both the memory held by the buffer and the buffer itself. diff --git a/include/prism/options.h b/include/prism/options.h index 2b823aebff..1b6ff4af1f 100644 --- a/include/prism/options.h +++ b/include/prism/options.h @@ -114,7 +114,7 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20; * @returns A new options struct with default values. It is the responsibility * of the caller to free this struct using pm_options_free(). */ -PRISM_EXPORTED_FUNCTION pm_options_t * pm_options_new(void) PRISM_NODISCARD; +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_options_t * pm_options_new(void); /** * Free both the held memory of the given options struct and the struct itself. diff --git a/include/prism/parser.h b/include/prism/parser.h index cf613c2c77..2c8c4b3a7a 100644 --- a/include/prism/parser.h +++ b/include/prism/parser.h @@ -33,7 +33,7 @@ typedef struct pm_parser_t pm_parser_t; * @returns The initialized parser. It is the responsibility of the caller to * free the parser with `pm_parser_free()`. */ -PRISM_EXPORTED_FUNCTION pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options) PRISM_NODISCARD PRISM_NONNULL(1); +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_parser_t * pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_options_t *options) PRISM_NONNULL(1); /** * Free both the memory held by the given parser and the parser itself. diff --git a/include/prism/source.h b/include/prism/source.h index 2f29845578..c79987d3fb 100644 --- a/include/prism/source.h +++ b/include/prism/source.h @@ -66,7 +66,7 @@ typedef enum { * @param length The length of the source data in bytes. * @returns A new source. Aborts on allocation failure. */ -PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_constant_new(const uint8_t *data, size_t length) PRISM_NODISCARD; +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_source_t * pm_source_constant_new(const uint8_t *data, size_t length); /** * Create a new source that wraps existing shared memory. The memory is not @@ -76,7 +76,7 @@ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_constant_new(const uint8_t *data * @param length The length of the source data in bytes. * @returns A new source. Aborts on allocation failure. */ -PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_shared_new(const uint8_t *data, size_t length) PRISM_NODISCARD; +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_source_t * pm_source_shared_new(const uint8_t *data, size_t length); /** * Create a new source that owns its memory. The memory will be freed with @@ -86,7 +86,7 @@ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_shared_new(const uint8_t *data, * @param length The length of the source data in bytes. * @returns A new source. Aborts on allocation failure. */ -PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_owned_new(uint8_t *data, size_t length) PRISM_NODISCARD; +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_source_t * pm_source_owned_new(uint8_t *data, size_t length); /** * Create a new source by reading a file into a heap-allocated buffer. @@ -95,7 +95,7 @@ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_owned_new(uint8_t *data, size_t * @param result Out parameter for the result of the initialization. * @returns A new source, or NULL on error (with result written to out param). */ -PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_file_new(const char *filepath, pm_source_init_result_t *result) PRISM_NODISCARD PRISM_NONNULL(1, 2); +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_source_t * pm_source_file_new(const char *filepath, pm_source_init_result_t *result) PRISM_NONNULL(1, 2); /** * Create a new source by memory-mapping a file. Falls back to file reading on @@ -110,7 +110,7 @@ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_file_new(const char *filepath, p * @param result Out parameter for the result of the initialization. * @returns A new source, or NULL on error (with result written to out param). */ -PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_mapped_new(const char *filepath, int open_flags, pm_source_init_result_t *result) PRISM_NODISCARD PRISM_NONNULL(1, 3); +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_source_t * pm_source_mapped_new(const char *filepath, int open_flags, pm_source_init_result_t *result) PRISM_NONNULL(1, 3); /** * Create a new source by reading from a stream using the provided callbacks. @@ -120,7 +120,7 @@ PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_mapped_new(const char *filepath, * @param feof The function to use to check if the stream is at EOF. * @returns A new source. Aborts on allocation failure. */ -PRISM_EXPORTED_FUNCTION pm_source_t * pm_source_stream_new(void *stream, pm_source_stream_fgets_t *fgets, pm_source_stream_feof_t *feof) PRISM_NODISCARD; +PRISM_EXPORTED_FUNCTION PRISM_NODISCARD pm_source_t * pm_source_stream_new(void *stream, pm_source_stream_fgets_t *fgets, pm_source_stream_feof_t *feof); /** * Free the given source and any memory it owns. From 5b523dfe6e9cd7c00433d8a95b10961368b16ce6 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:06:55 +0100 Subject: [PATCH 248/289] Remove currently deprecated functionality The method for marking something as deprecated is currently unused but seems fine leave as is. --- lib/prism/node_ext.rb | 259 ------------------------------- rbi/generated/prism/node_ext.rbi | 148 ------------------ sig/generated/prism/node_ext.rbs | 172 -------------------- 3 files changed, 579 deletions(-) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 4457c26fbe..8a5691848f 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -176,20 +176,6 @@ class RationalNode < Node def value Rational(numerator, denominator) end - - # Returns the value of the node as an IntegerNode or a FloatNode. This - # method is deprecated in favor of #value or #numerator/#denominator. - #-- - #: () -> (IntegerNode | FloatNode) - def numeric - deprecated("value", "numerator", "denominator") - - if denominator == 1 - IntegerNode.new(source, -1, location.chop, flags, numerator) - else - FloatNode.new(source, -1, location.chop, 0, numerator.to_f / denominator) - end - end end class ConstantReadNode < Node @@ -271,21 +257,6 @@ def full_name_parts def full_name full_name_parts.join("::") end - - # Previously, we had a child node on this class that contained either a - # constant read or a missing node. To not cause a breaking change, we - # continue to supply that API. - #-- - #: () -> (ConstantReadNode | MissingNode) - def child - deprecated("name", "name_loc") - - if (name = self.name) - ConstantReadNode.new(source, -1, name_loc, 0, name) - else - MissingNode.new(source, -1, location, 0) - end - end end class ConstantPathTargetNode < Node @@ -318,21 +289,6 @@ def full_name_parts def full_name full_name_parts.join("::") end - - # Previously, we had a child node on this class that contained either a - # constant read or a missing node. To not cause a breaking change, we - # continue to supply that API. - #-- - #: () -> (ConstantReadNode | MissingNode) - def child - deprecated("name", "name_loc") - - if (name = self.name) - ConstantReadNode.new(source, -1, name_loc, 0, name) - else - MissingNode.new(source, -1, location, 0) - end - end end class ConstantTargetNode < Node @@ -432,219 +388,4 @@ def full_message_loc attribute_write? ? message_loc&.adjoin("=") : message_loc end end - - class CallOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class ClassVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class ConstantOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class ConstantPathOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class GlobalVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class IndexOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class InstanceVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class LocalVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - #-- - #: () -> Symbol - def operator - deprecated("binary_operator") - binary_operator - end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - #-- - #: () -> Location - def operator_loc - deprecated("binary_operator_loc") - binary_operator_loc - end - end - - class CaseMatchNode < Node - # Returns the else clause of the case match node. This method is deprecated - # in favor of #else_clause. - #-- - #: () -> ElseNode? - def consequent - deprecated("else_clause") - else_clause - end - end - - class CaseNode < Node - # Returns the else clause of the case node. This method is deprecated in - # favor of #else_clause. - #-- - #: () -> ElseNode? - def consequent - deprecated("else_clause") - else_clause - end - end - - class IfNode < Node - # Returns the subsequent if/elsif/else clause of the if node. This method is - # deprecated in favor of #subsequent. - #-- - #: () -> (IfNode | ElseNode)? - def consequent - deprecated("subsequent") - subsequent - end - end - - class RescueNode < Node - # Returns the subsequent rescue clause of the rescue node. This method is - # deprecated in favor of #subsequent. - #-- - #: () -> RescueNode? - def consequent - deprecated("subsequent") - subsequent - end - end - - class UnlessNode < Node - # Returns the else clause of the unless node. This method is deprecated in - # favor of #else_clause. - #-- - #: () -> ElseNode? - def consequent - deprecated("else_clause") - else_clause - end - end end diff --git a/rbi/generated/prism/node_ext.rbi b/rbi/generated/prism/node_ext.rbi index 25255d073b..3177dca76f 100644 --- a/rbi/generated/prism/node_ext.rbi +++ b/rbi/generated/prism/node_ext.rbi @@ -93,11 +93,6 @@ module Prism # Returns the value of the node as a Ruby Rational. sig { returns(Rational) } def value; end - - # Returns the value of the node as an IntegerNode or a FloatNode. This - # method is deprecated in favor of #value or #numerator/#denominator. - sig { returns(::T.any(IntegerNode, FloatNode)) } - def numeric; end end class ConstantReadNode < Node @@ -144,12 +139,6 @@ module Prism # Returns the full name of this constant path. For example: "Foo::Bar" sig { returns(String) } def full_name; end - - # Previously, we had a child node on this class that contained either a - # constant read or a missing node. To not cause a breaking change, we - # continue to supply that API. - sig { returns(::T.any(ConstantReadNode, MissingNode)) } - def child; end end class ConstantPathTargetNode < Node @@ -161,12 +150,6 @@ module Prism # Returns the full name of this constant path. For example: "Foo::Bar" sig { returns(String) } def full_name; end - - # Previously, we had a child node on this class that contained either a - # constant read or a missing node. To not cause a breaking change, we - # continue to supply that API. - sig { returns(::T.any(ConstantReadNode, MissingNode)) } - def child; end end class ConstantTargetNode < Node @@ -199,135 +182,4 @@ module Prism sig { returns(::T.nilable(Location)) } def full_message_loc; end end - - class CallOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class ClassVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class ConstantOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class ConstantPathOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class GlobalVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class IndexOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class InstanceVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class LocalVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - sig { returns(Symbol) } - def operator; end - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - sig { returns(Location) } - def operator_loc; end - end - - class CaseMatchNode < Node - # Returns the else clause of the case match node. This method is deprecated - # in favor of #else_clause. - sig { returns(::T.nilable(ElseNode)) } - def consequent; end - end - - class CaseNode < Node - # Returns the else clause of the case node. This method is deprecated in - # favor of #else_clause. - sig { returns(::T.nilable(ElseNode)) } - def consequent; end - end - - class IfNode < Node - # Returns the subsequent if/elsif/else clause of the if node. This method is - # deprecated in favor of #subsequent. - sig { returns(::T.nilable(::T.any(IfNode, ElseNode))) } - def consequent; end - end - - class RescueNode < Node - # Returns the subsequent rescue clause of the rescue node. This method is - # deprecated in favor of #subsequent. - sig { returns(::T.nilable(RescueNode)) } - def consequent; end - end - - class UnlessNode < Node - # Returns the else clause of the unless node. This method is deprecated in - # favor of #else_clause. - sig { returns(::T.nilable(ElseNode)) } - def consequent; end - end end diff --git a/sig/generated/prism/node_ext.rbs b/sig/generated/prism/node_ext.rbs index 273e591eb8..db2be11684 100644 --- a/sig/generated/prism/node_ext.rbs +++ b/sig/generated/prism/node_ext.rbs @@ -109,12 +109,6 @@ module Prism # -- # : () -> Rational def value: () -> Rational - - # Returns the value of the node as an IntegerNode or a FloatNode. This - # method is deprecated in favor of #value or #numerator/#denominator. - # -- - # : () -> (IntegerNode | FloatNode) - def numeric: () -> (IntegerNode | FloatNode) end class ConstantReadNode < Node @@ -169,13 +163,6 @@ module Prism # -- # : () -> String def full_name: () -> String - - # Previously, we had a child node on this class that contained either a - # constant read or a missing node. To not cause a breaking change, we - # continue to supply that API. - # -- - # : () -> (ConstantReadNode | MissingNode) - def child: () -> (ConstantReadNode | MissingNode) end class ConstantPathTargetNode < Node @@ -189,13 +176,6 @@ module Prism # -- # : () -> String def full_name: () -> String - - # Previously, we had a child node on this class that contained either a - # constant read or a missing node. To not cause a breaking change, we - # continue to supply that API. - # -- - # : () -> (ConstantReadNode | MissingNode) - def child: () -> (ConstantReadNode | MissingNode) end class ConstantTargetNode < Node @@ -232,156 +212,4 @@ module Prism # : () -> Location? def full_message_loc: () -> Location? end - - class CallOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class ClassVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class ConstantOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class ConstantPathOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class GlobalVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class IndexOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class InstanceVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class LocalVariableOperatorWriteNode < Node - # Returns the binary operator used to modify the receiver. This method is - # deprecated in favor of #binary_operator. - # -- - # : () -> Symbol - def operator: () -> Symbol - - # Returns the location of the binary operator used to modify the receiver. - # This method is deprecated in favor of #binary_operator_loc. - # -- - # : () -> Location - def operator_loc: () -> Location - end - - class CaseMatchNode < Node - # Returns the else clause of the case match node. This method is deprecated - # in favor of #else_clause. - # -- - # : () -> ElseNode? - def consequent: () -> ElseNode? - end - - class CaseNode < Node - # Returns the else clause of the case node. This method is deprecated in - # favor of #else_clause. - # -- - # : () -> ElseNode? - def consequent: () -> ElseNode? - end - - class IfNode < Node - # Returns the subsequent if/elsif/else clause of the if node. This method is - # deprecated in favor of #subsequent. - # -- - # : () -> (IfNode | ElseNode)? - def consequent: () -> (IfNode | ElseNode)? - end - - class RescueNode < Node - # Returns the subsequent rescue clause of the rescue node. This method is - # deprecated in favor of #subsequent. - # -- - # : () -> RescueNode? - def consequent: () -> RescueNode? - end - - class UnlessNode < Node - # Returns the else clause of the unless node. This method is deprecated in - # favor of #else_clause. - # -- - # : () -> ElseNode? - def consequent: () -> ElseNode? - end end From 5a3198b7d4a61dab0020407dd70c36d23877bdc8 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 23 Feb 2026 15:41:45 -0600 Subject: [PATCH 249/289] Ignore prism wasm build in java-wasm resources --- .gitignore | 1 + java-wasm/src/test/resources/prism.wasm | Bin 668333 -> 0 bytes 2 files changed, 1 insertion(+) delete mode 100755 java-wasm/src/test/resources/prism.wasm diff --git a/.gitignore b/.gitignore index 5bce199577..471c5006a7 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ out.svg /java/org/ruby_lang/prism/AbstractNodeVisitor.java /java/org/ruby_lang/prism/Loader.java /java/org/ruby_lang/prism/Nodes.java +/java-wasm/src/test/resources/prism.wasm /lib/prism/compiler.rb /lib/prism/dispatcher.rb /lib/prism/dot_visitor.rb diff --git a/java-wasm/src/test/resources/prism.wasm b/java-wasm/src/test/resources/prism.wasm deleted file mode 100755 index 6d712590fc3e6c7c539131271e344beb0aafda18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 668333 zcmeEv34k3%wRTtcU1sLqJ9CqnERX;_Lm-1D3K9YWN*Y;3#JBl;@BKOq$%M?3naM0c z{C#8+St6TZ-y!T_lYpS02mw(RK@iylgb0YBsK}y#0{?f;sp{?ay>llEpnn3%?XEs` z>TGrD)T!!ft9@{xvMfve#oqp4d&v^DkxshBWk_=c`5`fD9rCk6B` z3Ivs9z^sF%vVK})U;!ya9C5H;#*Bakd&$?C*&~i%uJA8`;)j|R;<%1a&=L4UV)*(J z^>t#EF29aTmekiZN&IMu`d^Y3t{ElE3%5rAhLBK8gv!3BFmvKz?Sq|dgT3wjgA4kG z+WH4N7I$_WwnI((z@dX}hjt8ERvCzTh8XPpT1RELTu1NX&Vjz(ipa(ppwaOa=Jxc> z?QR zmKdOtH4(s2M^8`LCP>V}ZaHoy^tTT!XqyX;hdSE8Qpen(zJbHb3UC~QN9?De4E2+u zpn**k%T%c43O${@-PX8@AbtHEz1H|LAO*%k8e~k3Wx#~*fsTcJi>u)~r?IkimBX25 zpuxiza?9o9Qe>#%UIOBtSXS7%{=S}`w!YquzWMX5atf^NALyIg*74QOAxo9vH8(hS zLC3td!#g{A=2=Z;fa(U?d*}5ntmu|6B_M+xz4NSc zQYtW(!3D!Z^ZE|!wJhho%sZJ04HHs@RH^|{h2tQyi2X?@ia~rBZ!=aVqcWLPI-Sno zfBxg(U!oNcCZ;Ad*-mDX<)rP5!k?6KGIlCuWgOc|Wm1Jqrm^6pl|9LJ@COf+W2G|| z!8z8r6zXNHR4O$otaG&-9Vn4*SM z8f`nNg5{(d9IH@Zc%mTP&;T;hctE0eQjrSS=Fz8iT~0-?PQ)( z%}bQG_QKlS63esvf8Jb~rt1}Nr0D0=AMww~n>O7kA4(T!C|&3I>lk?Lv5bL%P5qHP zRn?8HIF|vgzL0-b%g+t+^Pv1hpPeg(`e)=kt~XLcC?A$bYt0XHgGbq8c7MyxEX43I zaJX%aYimOoy|8UA!o)TjAP23Pxwg*U&Y{ls9*T-SUTA9*;I>2B2Roda&D!u-hSRqB z!@YBdIuRicwI9;cp{!cK4)^p8bc&wYCSw z_QAo90Yrc8ojumGna!e*J)MI?ZSDOS3g=lnWQel9xz_XPdO(FA-IaFB)@z&JH?XjM z$eLBVc(AvBptE;qzV%)vvruq7lTOVa=;*MXO;1X|z>jvCiYFbtbNl9X_8!_cJT$*; zm$tbJ+6USW>zp^Vz?z-#xV@);K|2FkI}=Ai?cPq{=@20~wTV>`P)XHYw~SQfhC2s` zA&mh6*sT}_m=9f8OKp4n8JAoWe55Ww~nzV zqX^Xz+4c^RVK7k)zB*0d&{xNyV3>>UWX+>0X@X0hNc)rw9o`SY_7U^eH|+xIVnWn8 z#JpO^+QgI;%w5pgGmnc0t>bKx&b;A;{cT-?eZAK4Hrc@;!}I5(O))$|i1w`I=?Nu| z4mlh__Hk@G(K_1bj!Bb>G{J*?!vk|WtjEJ;JsrJ=!iXMAK%v1`q)C)U44RfT>8()c z%dNk!uZM&O?oF9>J%jZ1Q>Pqk8(h$FNIQf^UFeW@#5agkt#2{2287~WiS6)cg`GiD zpw7BDOA^s680_p8tY0wIroM0Fg!&|#jJM;`sx8 zU+d^Kt@mI`Gtl0{aHrZ+LU42Y7Q&y9^=LGw+2nH!_Qf3ogXEj2-P4(A@H5!o+cvLb zZYMkeoYSEQEiX!EQQk|v=928@q52EkJ5hP=KxaQDh`@1%y+!D0fBOKr$S}Z}Hra}4 zo-Fli!roaCx(4SW${!SAp3N3&s_+vIQ_qQ@l5%p&*12|=M0r5-`yQ@#o=p}KMF*oi ztbKsp7;$kv_eTT5-RXiz5zi1;a#!jnn*pOp4P0oaI|c@N`%=2<9LDNp55W?+ zH%)4YSK#3U;dIA5>w9Ukg5GdNJ(%3bojLMkZcj)1fc4Wf*_AerPMW`Tv>mnphBpWi zbXe!4X}p}fV8A*j%U7_KbF(v0g@rSK3GtyAv%s9+9WYk(9txv3UC+8EECUw%w^_$g zM)<+arJQs51L+#mq;^^6k0d2FJ%&mw~qFO)}2g+_F62?WelWC7Pt2d zcUa$GU!{w*uR1b4-n88|IE-o1;9y(7^%HiaXjKObcd6{B=$2eo%Cr!vmv}m|v;P5u?d)ECtqCv(qM9BkR3qNC@6?wL>V`xDi z1|!PnJRpN1g%+KIG1qiOI^BLq-vD}jhJpr;KLAu}py#t;o97|RJuh90irRSZVJJ<> zAXCFCc+t&X z!p-Vu(yD%PVVcHqUwGOlljIOmkl9!_rdt3JRo}1^* zpWD|nys+2$SsIbeJd9vYLw3HN4?NHFjwmwN{a`;5h1T1tI_}yXkiuf?xeNtHLw)nC zld=@snZQh_`ab(cT{Z}c=M7`fxGkNY-#-k;^qUL?7(;!-J=Pgnp`ZOkNAKY9Ku4Pl zT91n5l^XTjo?*nz*0ss@tOvGhINawkl2h3~Nhi9zVN%NR;ZCiC-LG{F^r4ZX5+2R# z8^+YmI#J?R-}&}*eAW8BXu~g)k%pf9f&IOa5}Ya?by&BuIY1WVB~9Tk!{ZMu1+`BL zk3TY~S*Np%L;i-H=esG=hBiauyl=iW66Re`W2gsEG=EYUGc-%{my^Q;NH}mx7;J#* z_FJbKA4$F}a7)&i+??N6%w&fB>Q&;FjZ(QE@r3O=+$QU*V`2Z$;TTGP9H@{-ySqi; zA}r0?gJB20kaVXV_`~dtwPY!z7ytc8I>ia)TQceSWarlJ(`i}h`C~f8ao)?+F9s;G zS(&YCYg^FK-j5h&o>R=}8=muzOAV4c|8=Imzi+Vft2CYEK*U3pxkz^!pibHPkaG4n=L5hzKiIy?qPewXE|p$ZpWGVyG!B zcEGa&*Oi%c+uoFnegYSqm3|^KQNXeA6@4PfF@RDB)258?3@qpIb_`wDV#Sn)Ym!Ry4i?PEF!eN^oR7+5CQ#t z{lh)9n1fzT1~6znl^Gu2GO_9Gk{HOE;4Ha7sekE;?nx$P@O#ZXc zDEf!23R9<)1>{%LO&XOf-I^8N*Zd}=++WgtJzWea)N8nJ_|3wYxHr+F?O(#B{u=C? zeuHFq!J_M1Y28)WAf+6WEWOJ5c3P`5_Eayc{w?yjWO?)*ql<{K6Lwh-eb*N;Xo7~Y z0Q#QKzZ8)V;(6+bu^hq$Sbl&WAR+P6Oh`I>zs9I8Rc$uk_830W)~^U;wKT3|dT zT*51g%fsd&ONighXgkBCB5BR=*o^MZ@;tIgcw9z%mDsaDGROP;Fm~!a)(O!vcGD+j zj2SVU>1o!tqSTeF?5*&7fv(46<4KuDZDU+&*6vO=PC>{GFV>wB;0dkHof=T;FUOtc zLx$JiPWN>bT5vlf01d6Mo#`VDmekIQmhl?e*}h1ki)QC!wif0>jyhB@uu$CpC7EfV zQW-iz1;RXh)y0_%X#iJOWoiQ#c6FxCC;^YI$z-*gw!WRI4Mw1AQN>jX%EJXcWdg`Luo42#|{nXWuhw6rYK}3B96+G;KW{ai>J5 z8CHIn$;jYf-Ae81b>!PJDGmuyBDA}#A4T2aDe5(PRF5REK249Nv&;uZuy&`xu##k6mUGq?*N zR~{RjNs|(uGy2KEF}R?obD{N3vedx^7`5kG#}Yj~bBExO2Cdg znabm~xx)k2>zUMi(%JFZG(yv__FHd3pomHj>9vl_W)GW-dECN7tiK`x!(th(-XsJN z55ysn#veqonDHV6?wE&_W`5o`JS6v<2jb-CQ{bhgK82JpvyOR~U%z0mU}b~$(fm1R zMnu8ugnlvrfTpx*lCWvFyV@Lo)eNyYUH16t~QqUJEC>(|^53`nMYZjY% z^4l<9ss6i6Jx^)d(B(O&kGUbC4AM}NP`PYB@_y73fe}3t|{`-Ia&zHZ_c5wS4bLVx; zKXgH7S9j0C-oE}tm>dr;KJ2T9f9?N%{eO>GGNP8MW$GL1NOhDtS{0 zb%HukeM_xSC#jRwDe6>pnmS#bq0Urisk7BN>Rff6I$vF&R;mltMe1U8iMmu>rY={j z)D`MVb(OkWU8BCOu2rkmb?SQc9d(1cQGHi^Pu-+$R^L}YP`9Wbs$11ZkKT&t7yVX7FUiDLTpSoZDOg*3;R6kb_sb8pv)g$Ur^_Y4bOa4!&C)HExSL$i? zj9ROHt)5lSspr*i)C=mj>P7XE`knf{dRhHJ{Zai%y`uiCURAHD*VP;9FY2%AP4$*~ zTm4P_UA?2;Rqv@0`;X4$smD_fr(RC|DfQ>ntEtygucv;H`9tPUnLlSnvPWg>-dxu7 zPR6!!*nN=O!LsLUy=-J;#PW_j@2C;0tJSvl#x{psq|j5dZL4?4LFkoFL@mHU#im)LVW)QfS_Fiq}(P&1pA<>+jI@uGR$Hq-WbjDw}QR@ng@nYw!c=Qm*Buigyu)oSX8j zeRD@*pUE6e>OqE7Z|$SHd54>C0kg`r8Z^7$&7j4B zX|YCN8qJEdH`8kJ)V?4JAVr}o=UQ^%s%9&1<#M@;m2zN3uJV?A4xq||O?avOr!?D; ziG#neh-T%?VS}(;wGV(&UTR1i`N-R3y)9%zs%xfY@n1L9<&D^M*^+{dC@zyq@WfM2!VqMYX+JG(a@El z?@dPT5HX%weOeA~)k@h6cD67;rv8x5sEG<62c%~YqTb4XF=p8<~j zzBgZ`mw;}E&Czz91A!br-JV+PI$hooi&|36X%Yl%2wtou17mfq16s1+AmgRTt-01g z1>3co(=Zr<>T&rDRk`I3KFNMnr(3ko`MT7?qJDh#l+#d_^IQa zxP;u81HXiRvdFtg?O#Bb1+nC+xadN4Ao#SoBRCkY0sO5c>`MvgLR0|ynU?K611%Gd zr(w312NwtPw_&Ea-J|THSV4g7p&-D(Lm5f=9tut}x5qkF7IUWh7by%4LOv6(Z zZ|A{pNmspXDbNUJ_bV9n8#0W-Shfvts!|)p-mi}6s!wAVr?TP9Sy+1r@0+8?=1rLq z$mIP|XryWioA+noKuXv}Ng87kT?G$D$_r_XByMW$0co@G*$^8p9B*XFzW8_LlKmI4 zYFwdX>H$WLF?!FpX3_%0Oapr%pP$|VW<`?WUci2mjXU|4+}RdqOM zDb&eCA7naE&{Ey{8VtP>BAKAg??AlBG-_K$9 zGKQ0HA;UqRXmQrGAV4B#1M8u&lS*ayWOsuR?9(En^ou!1OxZ_mr0r2ecN!7vgvC4~P!XRmc&&0;^t$TSb^{#*E9EmH_c(ih))eptJ_E zy^L;Nc@2xaA~$a%i16x$1_(tO*L;zp=ZGu3k&#rFafoTqLG(D99@Ej+`UKe?B3aF! z6K;T!D&3Mnn)0?1G1VVXAoGNrU?LEd??Z5V0h}@#qG)ZAcN;})0ox={(;y=kfm%d- zUN|D|AY1@ipbT5XH(prDhD1(iqlT5YE12YH)=ic=N?4p221Qs%iXlGyVbG{7tV0;| zfrmSr2!l9xEJ1YL^b5tU+r-plCUdp+ALbl6N+OO?Kbn zXQjwTu*ia&6NaIO>TCGma|>5|&~IkMNntAUO@t6AH6$c|J#&9e_k`a#`U z?n3;Y1bk3|5+!UgrVDOm`ju{m6oRBD8-le6Nls4P{^Ls?*yA*eUi{;nD@ z?!y;{K!ARVd@=@uZjwSDL*Du5Yqs%U=*ad5KR^G#?Q;_WnJz?v9rMFPHAEdg=BN(97UD-v*A zwFJZgD-jTbtw_KL)e;Z~tVBQzwju#nRZBn|uo3|=*op*vt6Bo$fRzY{!B!;TifRdn z12O?qESdfIOJpQ*DEBz)Bp)U@LNbO0@*U0V@#@gRMxwY1I-C2dqRu47MTxXH-i-9Iz4r zG1!U(oK-CWallFh#9%8Da89)Z!~rW25QD8qz_ry95C^P8Kn!*h0h=VSNdlWB@Zpv~ zJgz9a`zQ{`o^b3j->tB(UR0qbD(v3X$Gna-LxU?q-YuoXFu zh3Mr8hyzw4AO>5JfLL@?o`5)DB?4lw9})s?pN&OcSGiU=E8Hoi08}8|HaOmF?BiYMLXvP4Je$4bLq_R?15m7$92l2K5|oWj(ec>0K#OM7yT2 z5JsCdWtlPgUs_7Fyw7&k?^&q#|5(bdcj{C1>H184w!XfmzP`3DSDzpCIhv&Z(ClJt zja0>A5wB(7F1>G|!7z&D#gRWV8-~>eEZl20Cewy0EfD~|v6cbrG{5x$;Pz3#yB}uZ z)oZ{)07w`E&Oyu9yXy059L`%EXOF`lXI!|!Tlkd?FQf4k13a+??|qaTG@1yp@TL_d z?NQNL0uL)x6!Q1NL_;YPameFeV!704$b3NND#97?tF`feyXtFj*z9=xvB!t`{o#|$ zMph$A`-mcHc<70UY0~yjt*^B)X77B33CnAIA+f|E|0c{DNviyi-gbNxGURt(EW!G=z?vQ(vh>^Wj(33ykRz+NZP zO@O_-1ok=6a02Yw64^8PNTd#Hb7h}kfw`OfV}00 z^dgmK#<<1+=b28F_3H()Ru4M#7M5Lxbd+_uf`q=-RiCk@Pq$U$^k_u$a9JNv z8vUFrtecJ)Vy86vxvMPR(&*>$vOcRc`gyIa?=FpgPK^pRMDK$oQPrzuX?U>&_Oi0P zl}0~n%hFpK{Tx*mwlw-VrYvuz(a)7-$EDIy|EaR$QfZ|0o3b)1jg;OhD>IIiLSxP8 z(N42%s4GyM6oPy}^3NjI1e~wLaQ;>x6L7{MUlaK!;9Oo4 z<>)1WOu!k3yi|so1e_~lIL{Ht1e|fm?~3jdaNZQdd9^?$;EY4wCN`3Q^T8O-8wD}} zXB_f3VoM1)UyR{=QXms>#vxBGi*uwls-xv)amFF95lc37hGw>B#&BLNkcQ5tz~xaBnCLseU9M<^JgVBb0`^=b16c=ZibcFxJAIa51f zA7He-&G#+Tg%Gchgze_qrG+%{N+BwAuEZc$XB1i6IufpVwsl&LUdhQR^V~S??eS2 zV)-WGAcXU(sK7(KJ{W^sE)K#7Jk;%9G*W>)hWRW8Cn}4di!6*63dtgFQ};%Piclk^ zNx7w>CNsYeVJ%HZoh5^60&HnI>LLj`6JSfzQ8&rJngCmxj{2SOmH=Ctjv6ToTbhnK zMh3V9yrt==8zitwfQ_f4o|bUQK!$p^q@!%|UH;-1mU>PVGE6EUqz*E8yqvzHK2X9_ z#c$x0F*;hz#eX;<2d{mpE`GPZ6=!(i9D$)OIwuOJHpRJ*o zD{0UU357_~m>>uyP~$yMuo!TvIz-H=N5C>KlsV#y2)im^f+j@bG4vPno*K zmRq^aEyKfGPupf&e4%gnBOe`}F+4o;V;|psczB0T>^N(u*~2^U@<~3LaClfBPB=Wg z&oG@&I6Qp7=Ws;fFr862j6dOX3WpCK9&SHmcz7;8oiIFqn9nO5HU}2M8nW?Y~U_$Bkae)w}dr{&1P+RlMAps2FchPNiR0cC7&5PMACEyRPEO!fz#531xp9~2)LDn2k) z`*Q)<0U@vhDw$TRt&JBIa1N$+XLJLnqN)09Sp)!TB176g)ZG4>s)%AuBdEaK?H8)B zU!a?PL&f`QJcf#WV)uK;?)TF7MqQubd!MEJo@Kcp&PzI{7b3;esI{7G?p6tkZM9oT z8VEv+w)1mzRV|JD94DGt@>$F2hLBg^l;nKhknP(ZxiMY#6w?NExzieg?O6Axcu17<~~=db>Q(_6NGI& z_BukyURrQ1piu{E%^_NvHDAUoTzzlMYAb!8D6uW0L{Wp@)JSN_W*bp5!ORHxVsDp7 z1&(a3k$hrarN7k&Z4^R41!2bb z4%l)Kk^{1x%w6JafLX2!;i`+&t&L%>(cDxyyk$d(v$|?)z%4hP3Bll~VhGE3n+0uAkgx=h-{W+OfO)6Wu#(|M8E_?Cze?{n3wX*V^4Zy?fhjrgd-K z((HEQ&sJM*F?Gu3n@yfHaRS|TH#K&5kMAB=#AQQ$ccHsGpR22_>CR%djWiUtUqdIy zl1}IrYp&*&%w*#}C!@vRlrslk1)#PLDjZ6`lW}f03@IQ5<_RmMqq$+FDV-RMSH(2D zs;Xq1XiL6afV{immy(SdCqS5>Cf?Xj;BF;w0iLF*pD{Z1gmG$hU@m?0U@p3oPbbgv z5l#jrgl-1G9TJA)BlTho;ecIMGebwPiniVAh)Qbv;Aq=K)8v3eNE8LrN~K7}twcLb z_kAA2wEMOJh%qQQL1R>(IsfvgZ2_XHwit}a|DPyIZYto1Znr0}|1Jd!^*~X=WCHwB z6tL7bNtHHBbw;UF<-snc4~UT63IBgZ@l$z~$`8>?wWbDK$|`JP-y+B+YWF`%+l^o# zz#;)sCM0AJe)+#9l$QXO6cEOPqBToJT7*bTOQ-sRZY`B(Dfo;;B)j-X_9{g}yzNI6 zQaUNdGsg4Ld?8hzRUO#0>cFaSz^speSh_74JEjHC#j=w%{n;qjr6MK0*lg-kONCbo z?gE_X*(=_B>jvY#w9zVQ6ldlhR5*Yr+;9XDwvf0PIaw6ttYQ`w>c0USLRZs4RH5pz zDTIk?mFR!8=Wd*|F&2nT%qq1BqGlIje~&2paefhS0HP{KAFn$3pu(rAY86g1p(+w+ z>sod9b+5YHx>wz`%Blob(#u1JDSlw|f{^Ky?fKLehYqu%T9yh40iHZa2twq+_Q{5{ zd)P`hFzz`U5qE@cl2u5ibj!o>_HHHrAleGmlY%kDb(9JWd7!ca40;Jb{OFqqJ0MiIH zr6NOC$#~)gF%6X%1Ba>DK{DogL51XYiNHx?$6KPT(F;m=8of#-2$6dkKRS!ps*kcI z6%tIk)Ff#xPU2#3K>5lN^^F=RuWM^DqD5(=wnktv6RH#;jWT(f73Q}rBh=X>oDkggI#plm-3Mb)Ytyik?k0;oQl3O1mH1>zG&dD)N&38Km6 zd`UtJQlpZSQPC#+reVk7rb|Xy0t}f-?$__yDrG*pvO;yYIKjsV?KzwN`|wJ@wc}af zYz>b2h-_>NwzcU^Z6EpQ4BF5p+u6)+w#bKeX&YM=U)sF{AI7~1AIM#a59OYZ59XeW z59gkZ59pqW59ywc59*$Z59^+c5A3eMhjvfI2X~Lhhj)*~2Y8p`L%c`hgS+_{8Gz z39#Qzgl$TMeeD;Fx8BEV)A|ilkpEeP*5mGB$ZbN9A0k@skI;JEx0%)%qtp7vSqz!= zAuGuBWr3}U!Y0f0z6Tj^gAW^$>wQsLMXpnT`}b1n8+|`i^P_OA|GVJz7)hybZKBQ*)3BC|S ztBd+np;KSuDvg=|s)GH`Y5JaO$}6I#<7Nu@BoIEgiVtqkmwcu82%s<+@l8`KlF+iI zMtaMujC67YDIs)$@E+x6_AcD5@^?jKcHsqFXDcI#@_qb!BC~M@G9)wCo@rru5v{;W zXkxAsVu}JzWdBObIK+VgzTs@9!uKCOZjw0urbsWe>WQ#{91BN?l@R{m=Zw%e4%Bg3 z8(jt0ixIL(+lUlo(s)gIq6{TtwNs*x$Fd5{qLk0&6K}#Z(iu|hBE!lttX&uas}11(b$Ad61o9%3^k+|lP| z46)Islh}FnJQi%;v_FcbB$ltFsWnj-N17rMC1^7wR#Mf}4W_DN#0q^6Itp*o*1-yA z87ti0Xuc9_Gd37&NmjVKu|n+X5i1OtTHFfn4y*)Lc>ev>dW|zhy%}RK(!G)+gFAo5 zSbg~mY&9d8*!EPzkRKz2sE#ufbAy*~)6;x1%Z55pA~#gGN*Iu_6;!nHlZfc=xQ{9Q z=;)N*C4p8+@NgmpW%(aRuwHjvwF^bll7)f2pR#`?No)kBNHs%MAmjP)C$tQf62gT2mJ*Gl|6-pG|kfEh+r z*vuxX3YkJoSNS^wHKN-evyyc`eRSJKIfr?w zHmq4CftxmevgHb4P30bVM}*>czEf=vyjUo%HCh;Dm>NA;dO6bj$VRx2R6hipXo)=w z!qRn*mM(}y0~@Gw;f2UpJV;Yn6MKcjQEYjOj+BT8ZQ24W9p(0j#*V*|HP&kMP(BoU z|7^@iEYj1&;Rm$GI(d>qeoUg)SnxR6xDJ188WYll?&}BRYXVGgH0NB-qTOzE(MD}I zk$p}=j4jF?V;37e%8l6{y4W-m31Ww_SXZS;aKi<;QTvv_sdPvPsUv1B`P(9zI`4*R z-PT#+W%SHpLuo1@L*yIhtr1F3xq~UKV&-(3%yINs4F3?#4pf;HcuYnLGq8lR0)2tY ziDm^}l`1AJQ<@dHnJ4i#sr>gMti5wRv$o~v-DP95ws4(UyOCMDLFK;_VeO5ZnYAjy z-Hpv!_d2t79kaGt<*$vf_U>y18)M(186&JQYCgqU*WFIc)Jhg%`0j84O%F=f<~ zpY~(MS%oLxq%nRyp!(G12GiJgBYo`Q%UEMoB+$ngRE|1tL!A7ogz0)V%7$ek>cH=z zIOTmuI=COxh=ZAy=!{m&>d+J&PDsvxW`j1p05^KDy5XjSPe*2^CT7%o8P++CkUYuM zyGz#<(eth)cE*Wc4u*N8ePViW_CT@;FR+zQL zAd?3?ZDaWxB3wQ4eeO21J}9n^6dRuyYQId+smN7K0`JMpLFd~bRUYzNwO*rL7A1+54T>gkLY#nz06e=@p?tB^4CSM{`exsTE$L;%2-!Nur6Q2SgS}9R>T^! zf$Do!vSm$8^vMam&`%shrxh>W&Rl)uAKk9L9nsZ~Wghr}dBG3DUtANBz{4_KtRg42 zajZ4L0@uZ3=C6)$^?e!Ls_=rzQ>5gT!~|N)jBXYCU~E?VL&&~LSxZuLN8nw zy+*i7dC8-;t4HlCB79vUqjnV|(OCG}Q1-eiLhG3_YF076{r_mM(X`I@ZmTwK`5^Rq zSwyclON>>8ABuVm6OZZ{LH^PR)=MO3S4Cp0GS*8XSYNq`>U z=!L#_yEwwt8{cEDs@N5|ak%>S`P_bNd2W4oHYBg5t?$l;Ls z-;$jz!Q{>MX6bZC#Qc;OGZZ99=9tyI-K$BEY_Ioq@o2qX>*YsD0w}i6Vn4G^d#7c{ z3CuUPo|m-x`&S7FVpzXmu->#w88LSVl8`fyj#hyb+;e!p%r+l2D{u>iO z{-QuONaCC!&b4{;z$IDs>$ejM1SChKlM`o!$%?{OSJ|y^;`6aBekUxcn!OVF3nQ}n z%bo0os>oI!Uz#g7JH;Y>E9GsRtzb!3QYxkpcX1_0YDQKR?p`4YKs%j^6QZ5M%Op@4w$NjT%!_ zrsoAbd5=o>NLm`mpBuoT&tD^pid8HHZ=uOR2}y!=R~aF@@u#Uwv65bu8?;z^Z*SHY8F;${40GI zxlRo-deT1qG2ImKi6P{^}FZKS*(u3|A)F)O%S@8EIBap@-wm03!-*g#>IM#cTBG&}hY-0HQ znITLsh&jwm=xX^hLU1?A9?wL$(*rnipjWZ-t4PnDCQGqe`P5_StOtEMsKOz2(h)-F zV~podi?n>tkGSRS6L^V;Jmqbi$!J0+Of-&ip{-dUJT=1AZ9ibHcKV>WN=P-X3s*4> zB&Qn90^unU39P=ACGdeQd2A@Xo*d!og`YB4RfNtJtu=pA1nY$tGuA4W5h`O{5yASb zED$F3{+M1XVvWJR|H-RwMYuXvc7;_jYl}r%6$1THU*L4+z|rx`o1=z0$Uxd8dCLfn(Ml?Dz>qzobp2&j`5#AJ`fF*|Bgh|Rcwo0CLdm_ z^UXwsw(#bUi(q|HUXH6`_LiLC)6swa*Z`}yR^HA}TItDuGk^n6uUy9ttqOy_Q@Bs& zDK=Ck8_9ak+AyE^gCv-P?apOaoKKOYvA@zm^2e()GR1aHb~_}CxayZj#I!~>$5gQ# zwXrv*<0wNjevR=ZkRdwAVK7f$6_c|Tp#C#udrTEk)yC%Q6YI=ZKk?O<$5+Y%zOIo? zFG(FBXb0XiZ^zN>dtqC`FdBJMHTVK#^wvhEv_S93y7~n^Yg=ey)ARm zPxubA?0fVZCt}`EbCz#Jyv7?c7v1@T;_8E#i!O^uV6DtWcle+ru%Yz2G{V&>_idP2 z<46SSgEALg-+WAdNw{OJkb&z1O9mvzEMwoRN(UI}QA>F*Ud{3!b*&Y7S4nvL@7jbC z-V$WeK~2gW)Wk;yAzK?isA=h|+@49h@++AH#mBaWykO`|rHkZjCljggE17sPjJ`sP zZ|9)qS7xK-k)^CEHox5`Z%A!s`c;fC;%#02tMV1qyCUlXrc%X&tCs$S zMQEbO(pOaF;3^#36g{{K-^uaE8DCW1BSL`Q5}*&XVmkOUzkG020zx{^DjDI+f-s}y zDJNuw5U#PPYU$ZpQXZnQ+YuT^R5D5_uY~e^F-OC_$dbV0T>6n$0Dj8S9k zQD3AU^&feBeKzP(f4Y%-R24JETjixDKVKXhqs*{Dha|#x#mC&2Vt$iWr^!L6fE%AI z?^$sSdbA~mE1a&AoM&9W%$&DE-Z(UFK3G`~URe&(vSUtVBYA;5sJu$)r?mff{WIF} zq{r8Mks>#6?e*1a`kzIjU*GT&Jv=PYbHB?Htzum$Dp4dV%5MJ})$rEC?5J7a+`hH} zgmb(s;w1?nf0!>R?{#@MIw^aTU+jayM4y*8YpO_xTqe$FQbNF-wDaW=39)oMgeEIF zlu;LD0u{tw&IZ%SN|#xcGOt7PvOYX_nbWZ#h9_kMNfoP@n@*IX?@f9Y(gOLRuz}rr zKlj)wHW!X@V|mOFf1@QqiB8D``A5)@o5KZ%YT#z!(izU)AYtO6V>dCDqYs;^!m3AxAjSt1qp%*3>k zB)u84@$IgN^ssIu(pwa^r=^nPtitbNsB>|e!dE(@JWh?0+w38M;=SegKps=ije zqy#9_s1u+iC`%Kdag<33P(djP&{C8o3D7voq;!p-lmuugN-hVRM%{3Wbj*Licv1pX zP)Y){6eX26RzjJS02P#!0Nsmb5}(QM>63t|!8P(ONvoOnU`AKww3y_;BzbRn@?MbS zw>}a&zi}yf`og%MtNoLFGGx@wUv59}#w9hf4F8L@J99
#Y&q%(8507o%0vpqt5uqATToqA&B3;b3>EBx;S$ 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�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%0Dh+gqo?7SnR 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 AxBvhE From 4ab2854190368647574f0f8500af8a47e75a90ca Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 23 Feb 2026 15:48:34 -0600 Subject: [PATCH 250/289] Additional tweaks to get chicory-prism artifact deployed --- java-wasm/README.md | 6 +++ java-wasm/pom.xml | 91 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/java-wasm/README.md b/java-wasm/README.md index 2ff93a66d7..1c9eaee85e 100644 --- a/java-wasm/README.md +++ b/java-wasm/README.md @@ -1,5 +1,7 @@ This dir contains the chicory-prism artifact, a version of prism compiled to WASM and then AOT compiled to JVM bytecode by the Chicory project. +## Building + Generate the templated sources: ``` @@ -21,3 +23,7 @@ mvn -f java-wasm/pom.xml clean package This should build the chicory-wasm jar file and pass some basic tests. The jar will be under `java-wasm/target/chicory-prism-#####-SNAPSHOT.jar` or can be installed by using `install` instead of `pacakge` in the `mvn` command line above. + +## Releasing + +Pass `-Prelease` to enable release plugins for Maven Central (optional for snapshots) and run the `deploy` target for `mvn`. diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index ea94a82130..93f9bf3920 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -66,6 +66,60 @@ + + + release + + + + maven-source-plugin + + + attach-sources + + jar-no-fork + + + + + + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + none + + + + maven-gpg-plugin + 3.2.4 + + + sign-artifacts + verify + + sign + + + + + + --pinentry-mode + loopback + + + + + + + + @@ -97,26 +151,26 @@ - org.apache.maven.plugins - maven-surefire-plugin - 3.5.5 + org.apache.maven.plugins + maven-surefire-plugin + 3.5.5 org.codehaus.mojo build-helper-maven-plugin 3.6.1 - - generate-sources - - add-source - - - - ../java - - - + + generate-sources + + add-source + + + + ../java + + + @@ -136,6 +190,15 @@ + + org.sonatype.central + central-publishing-maven-plugin + 0.7.0 + true + + central + + From 588f41ed6b2c637a05d4038dd76ced0f06ad7ffa Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 5 Mar 2026 00:39:33 -0600 Subject: [PATCH 251/289] Use common method to construct Location here --- templates/lib/prism/serialize.rb.erb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/templates/lib/prism/serialize.rb.erb b/templates/lib/prism/serialize.rb.erb index c272d84bb4..a676f957af 100644 --- a/templates/lib/prism/serialize.rb.erb +++ b/templates/lib/prism/serialize.rb.erb @@ -437,11 +437,10 @@ module Prism tokens = [] #: Array[[Token, Integer]] while (type = TOKEN_TYPES.fetch(load_varuint)) - start = load_varuint - length = load_varuint + location = load_location_object(false) + lex_state = load_varuint - location = Location.new(@source, start, length) token = Token.new(@source, type, location.slice, location) tokens << [token, lex_state] From f3bbf6ca6e03923cd9042b431b1a75444928f90e Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 9 Mar 2026 12:31:01 -0500 Subject: [PATCH 252/289] Match formatting from js build --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1c56c0d358..d6d07943c3 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,12 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) $(ECHO) "building $@" $(Q) $(MAKEDIRS) $(@D) - $(Q) $(WASI_SDK_PATH)/bin/clang $(DEBUG_FLAGS) -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(JAVA_WASM_CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi -o $@ $(SOURCES) + $(Q) $(WASI_SDK_PATH)/bin/clang \ + $(DEBUG_FLAGS) \ + -DPRISM_EXCLUDE_PRETTYPRINT -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN \ + -lwasi-emulated-mman $(CPPFLAGS) $(JAVA_WASM_CFLAGS) \ + -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -lc++ -lc++abi \ + -o $@ $(SOURCES) build/shared/%.o: src/%.c Makefile $(HEADERS) $(ECHO) "compiling $@" From b12adc582c53ff667a28b085e9c894d215600c72 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 9 Mar 2026 12:32:23 -0500 Subject: [PATCH 253/289] Move groupID and package to ruby-lang New groupID: org.ruby-lang New artifactID: prism-ruby-parser[-wasm] New root package: org.ruby_lang --- java-wasm/pom.xml | 8 +- .../prism/wasm/WasmResource.java | 2 +- .../org/jruby/parser/prism/wasm/Prism.java | 95 ----------- .../java/org/ruby_lang/prism/wasm/Prism.java | 159 ++++++++++++++++++ .../org/jruby/parser/prism/JRubyTest.java | 4 +- .../prism/{DummyTest.java => WASMTest.java} | 11 +- 6 files changed, 175 insertions(+), 104 deletions(-) rename java-wasm/src/main/java-templates/org/{jruby/parser => ruby_lang}/prism/wasm/WasmResource.java (82%) delete mode 100644 java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java create mode 100644 java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java rename java-wasm/src/test/java/org/jruby/parser/prism/{DummyTest.java => WASMTest.java} (92%) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 93f9bf3920..83eeb25696 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -2,10 +2,10 @@ 4.0.0 - org.jruby - chicory-prism + org.ruby-lang + prism-parser-wasm 0.0.1-SNAPSHOT - Java Prism + Java WASM Prism Pure Java Prism using Chicory WASM runtime @@ -184,7 +184,7 @@ compile - org.jruby.parser.prism.wasm.PrismParser + org.ruby_lang.prism.wasm.PrismParser src/test/resources/prism.wasm diff --git a/java-wasm/src/main/java-templates/org/jruby/parser/prism/wasm/WasmResource.java b/java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java similarity index 82% rename from java-wasm/src/main/java-templates/org/jruby/parser/prism/wasm/WasmResource.java rename to java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java index 2b95406d13..785c2bd916 100644 --- a/java-wasm/src/main/java-templates/org/jruby/parser/prism/wasm/WasmResource.java +++ b/java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java @@ -1,4 +1,4 @@ -package org.jruby.parser.prism.wasm; +package org.ruby_lang.prism.wasm; public final class WasmResource { public static final String absoluteFile = "file://${project.basedir}/src/test/resources/prism.wasm"; diff --git a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java b/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java deleted file mode 100644 index 71726703c3..0000000000 --- a/java-wasm/src/main/java/org/jruby/parser/prism/wasm/Prism.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.jruby.parser.prism.wasm; - -import com.dylibso.chicory.annotations.WasmModuleInterface; -import com.dylibso.chicory.runtime.ByteArrayMemory; -import com.dylibso.chicory.runtime.ImportValues; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasi.WasiOptions; -import com.dylibso.chicory.wasi.WasiPreview1; -import org.ruby_lang.prism.Loader; -import org.ruby_lang.prism.ParseResult; - -import java.nio.charset.StandardCharsets; - -@WasmModuleInterface(WasmResource.absoluteFile) -public class Prism implements AutoCloseable { - private final WasiPreview1 wasi; - protected final Prism_ModuleExports exports; - private final Instance instance; - - private int bufferPointer; - private int preSourcePointer; - private int preOptionsPointer; - - private final int SOURCE_SIZE = 2 * 1024 * 1024; // 2 MiB - private final int PACKED_OPTIONS_BUFFER_SIZE = 1024; - - public Prism() { - this(WasiOptions.builder().build()); - } - - public Prism(WasiOptions wasiOpts) { - wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); - instance = Instance.builder(PrismParser.load()) - .withMemoryFactory(ByteArrayMemory::new) - .withMachineFactory(PrismParser::create) - .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) - .build(); - exports = new Prism_ModuleExports(instance); - - preOptionsPointer = exports.calloc(1, PACKED_OPTIONS_BUFFER_SIZE); - preSourcePointer = exports.calloc(1, SOURCE_SIZE); - - bufferPointer = exports.pmBufferNew(); - } - - public byte[] serialize(byte[] packedOptions, byte[] sourceBytes, int sourceLength) { - int sourcePointer = 0; - boolean useDefaultSourcePointer = sourceLength + 1 > SOURCE_SIZE; - int optionsPointer = 0; - boolean useDefaultOptionsPointer = packedOptions.length > PACKED_OPTIONS_BUFFER_SIZE; - byte[] result; - try { - sourcePointer = (!useDefaultSourcePointer) ? - exports.calloc(1, sourceLength + 1) : preSourcePointer; - instance.memory().write(sourcePointer, sourceBytes, 0, sourceLength); - instance.memory().writeByte(sourcePointer + sourceLength, (byte) 0); - - optionsPointer = (!useDefaultOptionsPointer) ? - exports.calloc(1, packedOptions.length) : preOptionsPointer; - instance.memory().write(optionsPointer, packedOptions); - - exports.pmBufferFree(bufferPointer); - bufferPointer = exports.pmBufferNew(); - - exports.pmSerializeParse( - bufferPointer, sourcePointer, sourceLength, optionsPointer); - - result = instance.memory().readBytes( - exports.pmBufferValue(bufferPointer), - exports.pmBufferLength(bufferPointer)); - } finally { - if (!useDefaultSourcePointer) { - exports.free(sourcePointer); - } - if (!useDefaultOptionsPointer) { - exports.free(optionsPointer); - } - } - - return result; - } - - public ParseResult serializeParse(byte[] packedOptions, String source) { - var sourceBytes = source.getBytes(StandardCharsets.ISO_8859_1); - byte[] result = serialize(packedOptions, sourceBytes, sourceBytes.length); - return Loader.load(result); - } - - @Override - public void close() { - if (wasi != null) { - wasi.close(); - } - } -} diff --git a/java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java b/java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java new file mode 100644 index 0000000000..20d6c286cb --- /dev/null +++ b/java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java @@ -0,0 +1,159 @@ +package org.ruby_lang.prism.wasm; + +import com.dylibso.chicory.annotations.WasmModuleInterface; +import com.dylibso.chicory.runtime.ByteArrayMemory; +import com.dylibso.chicory.runtime.ImportValues; +import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.wasi.WasiOptions; +import com.dylibso.chicory.wasi.WasiPreview1; +import org.ruby_lang.prism.Loader; +import org.ruby_lang.prism.ParseResult; + +import java.nio.charset.StandardCharsets; + +@WasmModuleInterface(WasmResource.absoluteFile) +public class Prism implements AutoCloseable { + private final WasiPreview1 wasi; + protected final Prism_ModuleExports exports; + private final Instance instance; + + public Prism() { + this(WasiOptions.builder().build()); + } + + public Prism(WasiOptions wasiOpts) { + wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); + instance = Instance.builder(PrismParser.load()) + .withMemoryFactory(ByteArrayMemory::new) + .withMachineFactory(PrismParser::create) + .withImportValues(ImportValues.builder().addFunction(wasi.toHostFunctions()).build()) + .build(); + exports = new Prism_ModuleExports(instance); + } + + public String version() { + int versionPointer = exports.pmVersion(); + int length = exports.strchr(versionPointer, 0); + + return new String(instance.memory().readBytes(versionPointer, length - versionPointer)); + } + + public byte[] parse(byte[] sourceBytes, byte[] packedOptions) { + try ( + Buffer buffer = new Buffer(); + Source source = new Source(sourceBytes, 0, sourceBytes.length); + Options options = new Options(packedOptions)) { + + return parse(buffer, source, options); + } + } + + public byte[] lex(byte[] sourceBytes, byte[] packedOptions) { + try ( + Buffer buffer = new Buffer(); + Source source = new Source(sourceBytes, 0, sourceBytes.length); + Options options = new Options(packedOptions)) { + + return lex(buffer, source, options); + } + } + + public byte[] parse(byte[] sourceBytes, int sourceOffset, int sourceLength, byte[] packedOptions) { + try ( + Buffer buffer = new Buffer(); + Source source = new Source(sourceBytes, sourceOffset, sourceLength); + Options options = new Options(packedOptions)) { + + return parse(buffer, source, options); + } + } + + public byte[] parse(Buffer buffer, Source source, Options options) { + exports.pmSerializeParse( + buffer.pointer, source.pointer, source.length, options.pointer); + + return buffer.read(); + } + + public byte[] lex(Buffer buffer, Source source, Options options) { + exports.pmSerializeLex( + buffer.pointer, source.pointer, source.length, options.pointer); + + return buffer.read(); + } + + public class Buffer implements AutoCloseable { + final int pointer; + + Buffer() { + pointer = exports.pmBufferNew(); + clear(); + } + + public void clear() { + exports.pmBufferClear(pointer); + } + + public void close() { + exports.pmBufferFree(pointer); + } + + public byte[] read() { + return instance.memory().readBytes( + exports.pmBufferValue(pointer), + exports.pmBufferLength(pointer)); + } + } + + class Source implements AutoCloseable{ + final int pointer; + final int length; + + Source(int length) { + pointer = exports.calloc(1, length); + this.length = length; + } + + Source(byte[] bytes, int offset, int length) { + this(length + 1); + write(bytes, offset, length); + } + + public void write(byte[] bytes, int offset, int length) { + assert length + 1 <= this.length; + instance.memory().write(pointer, bytes, offset, length); + instance.memory().writeByte(pointer + length, (byte) 0); + } + + public void close() { + exports.free(pointer); + } + } + + class Options implements AutoCloseable { + final int pointer; + + Options(byte[] packedOptions) { + int pointer = exports.calloc(1, packedOptions.length); + instance.memory().write(pointer, packedOptions); + this.pointer = pointer; + } + + public void close() { + exports.free(pointer); + } + } + + public ParseResult serializeParse(byte[] packedOptions, String source) { + var sourceBytes = source.getBytes(StandardCharsets.ISO_8859_1); + byte[] result = parse(sourceBytes, 0, sourceBytes.length, packedOptions); + return Loader.load(result); + } + + @Override + public void close() { + if (wasi != null) { + wasi.close(); + } + } +} diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java index b8249f4c70..3af956111e 100644 --- a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java @@ -1,9 +1,9 @@ package org.jruby.parser.prism; import org.jruby.Ruby; -import org.jruby.parser.prism.wasm.Prism; import org.junit.jupiter.api.Test; import org.ruby_lang.prism.ParsingOptions; +import org.ruby_lang.prism.wasm.Prism; import java.io.DataInputStream; import java.io.InputStream; @@ -108,7 +108,7 @@ private static void basicJRubyTest(Prism prism) throws Exception { try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { DataInputStream dis = new DataInputStream(fileIn); int read = dis.read(src); - prism.serialize(options, src, read); + prism.parse(src, 0, read, options); } } } diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java similarity index 92% rename from java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java rename to java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java index 4e89f6f6e3..9e2711cd6b 100644 --- a/java-wasm/src/test/java/org/jruby/parser/prism/DummyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java @@ -1,16 +1,16 @@ package org.jruby.parser.prism; -import org.jruby.parser.prism.wasm.Prism; import org.junit.jupiter.api.Test; import org.ruby_lang.prism.ParseResult; import org.ruby_lang.prism.ParsingOptions; +import org.ruby_lang.prism.wasm.Prism; import java.util.EnumSet; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -public class DummyTest { +public class WASMTest { private static final byte[] packedOptions = ParsingOptions.serialize( new byte[] {}, @@ -88,4 +88,11 @@ public void test2Aot() { System.out.println(pr.value.childNodes()[0]); assertTrue(pr.value.childNodes()[0].toString().contains("CallNode")); } + + @Test + public void testVersion() { + try (Prism prism = new Prism()) { + assertEquals("1.9.0", prism.version()); + } + } } From 9ed60328f7457cf5b44f865d05c3060447d82a05 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 9 Mar 2026 13:57:00 -0500 Subject: [PATCH 254/289] Switch to base/stdlib dependencies This library depends on jruby-base but also needs stdlib for the parsing test. Rather than depend on jruby-complete, use a hard dep for jruby-base and a test-scoped dep for stdlib. --- java-wasm/pom.xml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 83eeb25696..c6072568ac 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -61,8 +61,14 @@ org.jruby - jruby-complete - 10.0.3.0 + jruby-stdlib + 10.1.0.0-SNAPSHOT + test + + + org.jruby + jruby-base + 10.1.0.0-SNAPSHOT From fa6f034951517709d3737f878c42d537e8dbfb38 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 17 Mar 2026 12:08:03 -0500 Subject: [PATCH 255/289] Switch to JRuby 10.0.4.0 dependency This patch allows publishing the artifact now based on available JRuby releases. * jruby-base 10.0.4.0 is used at compile time and specified as "provided" scope in Maven, to avoid a hard dependency on that specific release. The API requires that some JRuby 10.0.4.0 or higher be provided by the host environment. * jruby-stdlib 10.0.4.0 is used in concert with jruby-base to test the ability to parse Ruby source files required by JRuby 10.0.4.0 at startup. This dependency is only scoped for testing. --- java-wasm/pom.xml | 5 +-- .../org/jruby/parser/prism/JRubyTest.java | 32 +++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index c6072568ac..a6ddcf804d 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -62,13 +62,14 @@ org.jruby jruby-stdlib - 10.1.0.0-SNAPSHOT + 10.0.4.0 test org.jruby jruby-base - 10.1.0.0-SNAPSHOT + 10.0.4.0 + provided diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java index 3af956111e..12c3e4f74d 100644 --- a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java @@ -11,8 +11,10 @@ import java.util.EnumSet; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class JRubyTest { + // TODO: This list is hardcoded from JRuby 10.0.4.0 and should be made dynamic final static String[] JRUBY_BOOT_FILES = { "jruby/java.rb", "jruby/java/core_ext.rb", @@ -33,10 +35,9 @@ public class JRubyTest { "jruby/kernel/thread.rb", "jruby/kernel/integer.rb", "jruby/kernel/time.rb", + "jruby/kernel/string.rb", "jruby/preludes.rb", "jruby/kernel/prelude.rb", - "jruby/kernel/enc_prelude.rb", - "META-INF/jruby.home/lib/ruby/stdlib/unicode_normalize.rb", "jruby/kernel/gem_prelude.rb", "META-INF/jruby.home/lib/ruby/stdlib/rubygems.rb", "META-INF/jruby.home/lib/ruby/stdlib/rbconfig.rb", @@ -56,6 +57,32 @@ public class JRubyTest { "META-INF/jruby.home/lib/ruby/stdlib/rubygems/util/list.rb", "META-INF/jruby.home/lib/ruby/stdlib/rubygems/requirement.rb", "META-INF/jruby.home/lib/ruby/stdlib/rubygems/version.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults/operating_system.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/defaults/jruby.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/util.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/dependency.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_gem.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/core_ext/kernel_warn.rb", + "META-INF/jruby.home/lib/ruby/stdlib/monitor.rb", + "META-INF/jruby.home/lib/ruby/stdlib/bundled_gems.rb", + "META-INF/jruby.home/lib/ruby/stdlib/rubygems/path_support.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/version.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/core_ext/name_error.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/levenshtein.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/jaro_winkler.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/name_error_checkers.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/method_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/key_error_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/null_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/require_path_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/tree_spell_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/spell_checkers/pattern_key_name_checker.rb", + "META-INF/jruby.home/lib/ruby/stdlib/did_you_mean/formatter.rb", + "META-INF/jruby.home/lib/ruby/stdlib/syntax_suggest/core_ext.rb", }; private class TestingPrism extends Prism { @@ -106,6 +133,7 @@ private static void basicJRubyTest(Prism prism) throws Exception { ); try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { + assertNotNull(fileIn, "Could not find file: " + file); DataInputStream dis = new DataInputStream(fileIn); int read = dis.read(src); prism.parse(src, 0, read, options); From cffc95c2d3b2b1da8e76ea2a1fe6aee50e812ad6 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 17 Mar 2026 12:10:34 -0500 Subject: [PATCH 256/289] Update description and Chicory dependency --- java-wasm/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index a6ddcf804d..8eed6eb137 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -6,7 +6,7 @@ prism-parser-wasm 0.0.1-SNAPSHOT Java WASM Prism - Pure Java Prism using Chicory WASM runtime + Pure Java Prism API using Chicory WASM AOT runtime @@ -15,7 +15,7 @@ 21 21 - 1.7.2 + 1.7.3 6.0.3 From 6c9710d1295180b2fcaea1fd04df9afd1845bd41 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 17 Mar 2026 12:17:05 -0500 Subject: [PATCH 257/289] Rename library to top-level artifact for now This library will eventually be split into a few pieces: * The direct Parser API, probably called prism-parser-api * The native backend, probably called prism-parser-native * The WASM backend, probably called prism-parser-wasm * The Prism gem backend (with line info etc), name TBD But for now, the first three are all in one library and the fourth is still being designed. We will publish this aggregate library as prism-parser. When the component libraries are defined, most likely prism-parser will aggregate (depend upon) the first three artifacts, so this should not impact future releases of JRuby. --- java-wasm/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 8eed6eb137..2e6baaf7ca 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -3,10 +3,10 @@ 4.0.0 org.ruby-lang - prism-parser-wasm + prism-parser 0.0.1-SNAPSHOT - Java WASM Prism - Pure Java Prism API using Chicory WASM AOT runtime + Java Prism + Java API for the Prism Ruby language parser From 21942ddd6269b858c289dca6f041d70fd60539c9 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 19 Mar 2026 10:52:09 -0500 Subject: [PATCH 258/289] Add java and java-wasm dirs to CI trigger --- .github/workflows/java-wasm-bindings.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 4715d6f93b..2d6a574ee1 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -7,6 +7,8 @@ on: - "include/" - "src/" - "*akefile*" + - "java/" + - "java-wasm/" branches: - main - ruby-4.0 From 3cffc44510da21a9021ff0b36bb5cf10cbaa6f2f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 14:14:54 -0400 Subject: [PATCH 259/289] Lazily build offsets from a packed array --- ext/prism/extension.c | 8 +++----- lib/prism/parse_result.rb | 24 +++++++++++++++++------- rbi/generated/prism/parse_result.rbi | 12 ++++++++---- sig/generated/prism/parse_result.rbs | 16 +++++++++++----- templates/ext/prism/api_node.c.erb | 6 +----- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index a3ff4a1632..9f9169cfff 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -802,16 +802,14 @@ parse_lex_input(const uint8_t *input, size_t input_length, const pm_options_t *o pm_node_t *node = pm_parse(parser); - // Here we need to update the Source object to have the correct - // encoding for the source string and the correct newline offsets. - // We do it here because we've already created the Source object and given - // it over to all of the tokens, and both of these are only set after pm_parse(). + /* Update the Source object with the correct encoding and line offsets, + * which are only available after pm_parse() completes. */ rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser)); rb_enc_associate(source_string, encoding); const pm_line_offset_list_t *line_offsets = pm_parser_line_offsets(parser); for (size_t index = 0; index < line_offsets->size; index++) { - rb_ary_push(offsets, ULONG2NUM(line_offsets->offsets[index])); + rb_ary_store(offsets, (long) index, ULONG2NUM(line_offsets->offsets[index])); } if (pm_options_freeze(options)) { diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 5c4d4fcb8a..4d1fa2c296 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -58,16 +58,26 @@ def self.for(source, start_line, offsets) # The line number where this source starts. attr_reader :start_line #: Integer - # The list of newline byte offsets in the source code. - attr_reader :offsets #: Array[Integer] + # The list of newline byte offsets in the source code. When initialized from + # the C extension, this may be a packed binary string of uint32_t values + # that is lazily unpacked on first access. + #-- + #: () -> Array[Integer] + def offsets + offsets = @offsets + return offsets if offsets.is_a?(Array) + @offsets = offsets.unpack("L*") + end - # Create a new source object with the given source code. + # Create a new source object with the given source code. The offsets + # parameter can be either an Array of Integer byte offsets or a packed + # binary string of uint32_t values (from the C extension). #-- - #: (String source, Integer start_line, Array[Integer] offsets) -> void + #: (String source, Integer start_line, Array[Integer] | String offsets) -> void def initialize(source, start_line, offsets) @source = source - @start_line = start_line # set after parsing is done - @offsets = offsets # set after parsing is done + @start_line = start_line + @offsets = offsets end # Replace the value of start_line with the given value. @@ -81,7 +91,7 @@ def replace_start_line(start_line) #-- #: (Array[Integer] offsets) -> void def replace_offsets(offsets) - @offsets.replace(offsets) + @offsets = offsets end # Returns the encoding of the source code, which is set by parameters to the diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi index ddced69934..f20ba90ef5 100644 --- a/rbi/generated/prism/parse_result.rbi +++ b/rbi/generated/prism/parse_result.rbi @@ -28,12 +28,16 @@ module Prism sig { returns(Integer) } attr_reader :start_line - # The list of newline byte offsets in the source code. + # The list of newline byte offsets in the source code. When initialized from + # the C extension, this may be a packed binary string of uint32_t values + # that is lazily unpacked on first access. sig { returns(T::Array[Integer]) } - attr_reader :offsets + def offsets; end - # Create a new source object with the given source code. - sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).void } + # Create a new source object with the given source code. The offsets + # parameter can be either an Array of Integer byte offsets or a packed + # binary string of uint32_t values (from the C extension). + sig { params(source: String, start_line: Integer, offsets: ::T.any(T::Array[Integer], String)).void } def initialize(source, start_line, offsets); end # Replace the value of start_line with the given value. diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs index d2b4035960..1f3b8a8d54 100644 --- a/sig/generated/prism/parse_result.rbs +++ b/sig/generated/prism/parse_result.rbs @@ -33,13 +33,19 @@ module Prism # The line number where this source starts. attr_reader start_line: Integer - # The list of newline byte offsets in the source code. - attr_reader offsets: Array[Integer] + # The list of newline byte offsets in the source code. When initialized from + # the C extension, this may be a packed binary string of uint32_t values + # that is lazily unpacked on first access. + # -- + # : () -> Array[Integer] + def offsets: () -> Array[Integer] - # Create a new source object with the given source code. + # Create a new source object with the given source code. The offsets + # parameter can be either an Array of Integer byte offsets or a packed + # binary string of uint32_t values (from the C extension). # -- - # : (String source, Integer start_line, Array[Integer] offsets) -> void - def initialize: (String source, Integer start_line, Array[Integer] offsets) -> void + # : (String source, Integer start_line, Array[Integer] | String offsets) -> void + def initialize: (String source, Integer start_line, Array[Integer] | String offsets) -> void # Replace the value of start_line with the given value. # -- diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index 506c2e87f8..42a30ce0f2 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -81,11 +81,7 @@ pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) { VALUE source_string = rb_enc_str_new((const char *) start, pm_parser_end(parser) - start, encoding); const pm_line_offset_list_t *line_offsets = pm_parser_line_offsets(parser); - VALUE offsets = rb_ary_new_capa(line_offsets->size); - - for (size_t index = 0; index < line_offsets->size; index++) { - rb_ary_push(offsets, ULONG2NUM(line_offsets->offsets[index])); - } + VALUE offsets = rb_str_new((const char *) line_offsets->offsets, line_offsets->size * sizeof(uint32_t)); if (freeze) { rb_obj_freeze(source_string); From bbcb5690ce663f0316d2091f433143fde5d10237 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 14:22:02 -0400 Subject: [PATCH 260/289] Use an arena for building the Prism AST --- templates/ext/prism/api_node.c.erb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/templates/ext/prism/api_node.c.erb b/templates/ext/prism/api_node.c.erb index 42a30ce0f2..71f7fe273e 100644 --- a/templates/ext/prism/api_node.c.erb +++ b/templates/ext/prism/api_node.c.erb @@ -1,6 +1,7 @@ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>" #include "prism/extension.h" #include "prism/internal/allocator.h" +#include "prism/internal/arena.h" #include @@ -101,8 +102,8 @@ typedef struct pm_node_stack_node { } pm_node_stack_node_t; static void -pm_node_stack_push(pm_node_stack_node_t **stack, const pm_node_t *visit) { - pm_node_stack_node_t *node = xmalloc(sizeof(pm_node_stack_node_t)); +pm_node_stack_push(pm_arena_t *arena, pm_node_stack_node_t **stack, const pm_node_t *visit) { + pm_node_stack_node_t *node = (pm_node_stack_node_t *) pm_arena_alloc(arena, sizeof(pm_node_stack_node_t), PRISM_ALIGNOF(pm_node_stack_node_t)); node->prev = *stack; node->visit = visit; node->visited = false; @@ -115,7 +116,6 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) { const pm_node_t *visit = current->visit; *stack = current->prev; - xfree_sized(current, sizeof(pm_node_stack_node_t)); return visit; } @@ -147,8 +147,9 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi pm_ast_constants_each_data_t constants_data = { .constants = constants, .encoding = encoding }; pm_parser_constants_each(parser, pm_ast_constants_each, &constants_data); + pm_arena_t *node_arena = pm_arena_new(); pm_node_stack_node_t *node_stack = NULL; - pm_node_stack_push(&node_stack, node); + pm_node_stack_push(node_arena, &node_stack, node); VALUE value_stack = rb_ary_new(); while (node_stack != NULL) { @@ -171,10 +172,10 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi <%- node.fields.each do |field| -%> <%- case field -%> <%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%> - pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>); + pm_node_stack_push(node_arena, &node_stack, (pm_node_t *) cast-><%= field.name %>); <%- when Prism::Template::NodeListField -%> for (size_t index = 0; index < cast-><%= field.name %>.size; index++) { - pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>.nodes[index]); + pm_node_stack_push(node_arena, &node_stack, (pm_node_t *) cast-><%= field.name %>.nodes[index]); } <%- end -%> <%- end -%> @@ -276,6 +277,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi } } + pm_arena_free(node_arena); return rb_ary_pop(value_stack); } From 9df357af897e93f65cfe63c071c979a3d054e638 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 19 Mar 2026 17:18:21 -0400 Subject: [PATCH 261/289] Fast path for returning from parse_arguments_list --- src/prism.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/prism.c b/src/prism.c index 53c33cee39..5e2d37a8e0 100644 --- a/src/prism.c +++ b/src/prism.c @@ -12589,6 +12589,14 @@ match4(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4); } +/** + * Returns true if the current token is any of the six given types. + */ +static PRISM_INLINE bool +match6(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_token_type_t type4, pm_token_type_t type5, pm_token_type_t type6) { + return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6); +} + /** * Returns true if the current token is any of the seven given types. */ @@ -15091,6 +15099,16 @@ parse_block(pm_parser_t *parser, uint16_t depth) { */ static bool parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, uint8_t flags, uint16_t depth) { + /* Fast path: if the current token can't begin an expression and isn't + * a parenthesis, block opener, or splat/block-pass operator, there are + * no arguments to parse. */ + if ( + !token_begins_expression_p(parser->current.type) && + !match6(parser, PM_TOKEN_PARENTHESIS_LEFT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_KEYWORD_DO_BLOCK, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR, PM_TOKEN_UAMPERSAND) + ) { + return false; + } + bool found = false; bool parsed_command_args = false; From 56cdcbbb8c7ef02bfd58d0ac61bce558f5782d37 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 20 Mar 2026 12:18:17 -0400 Subject: [PATCH 262/289] Provide a single-entry cache on parser for avoiding constant hashes --- include/prism/internal/parser.h | 12 ++++++++++++ src/prism.c | 14 +++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/include/prism/internal/parser.h b/include/prism/internal/parser.h index dbed71e737..3afe226757 100644 --- a/include/prism/internal/parser.h +++ b/include/prism/internal/parser.h @@ -582,6 +582,18 @@ struct pm_parser_t { */ uint32_t node_id; + /* + * A single-entry cache for pm_parser_constant_id_raw. Avoids redundant + * constant pool lookups when the same token is resolved multiple times + * (e.g., once during lexing for local variable detection, and again + * during parsing for node creation). + */ + struct { + const uint8_t *start; + const uint8_t *end; + pm_constant_id_t id; + } constant_cache; + /* The current state of the lexer. */ pm_lex_state_t lex_state; diff --git a/src/prism.c b/src/prism.c index 5e2d37a8e0..1fa4a46ed8 100644 --- a/src/prism.c +++ b/src/prism.c @@ -1120,7 +1120,19 @@ pm_locals_order(pm_parser_t *parser, pm_locals_t *locals, pm_constant_id_list_t */ static PRISM_INLINE pm_constant_id_t pm_parser_constant_id_raw(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { - return pm_constant_pool_insert_shared(&parser->metadata_arena, &parser->constant_pool, start, (size_t) (end - start)); + /* Fast path: if this is the same token as the last lookup (same pointer + * range), return the cached result. */ + if (start == parser->constant_cache.start && end == parser->constant_cache.end) { + return parser->constant_cache.id; + } + + pm_constant_id_t id = pm_constant_pool_insert_shared(&parser->metadata_arena, &parser->constant_pool, start, (size_t) (end - start)); + + parser->constant_cache.start = start; + parser->constant_cache.end = end; + parser->constant_cache.id = id; + + return id; } /** From 992926b100518dcd13141dd29fd01c9cf6645d6a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 20 Mar 2026 13:27:34 -0400 Subject: [PATCH 263/289] Better documentation website --- doc/index.css | 202 +++++++++++++----- doc/index.html | 93 +++++++-- doc/playground.css | 336 +++++++++++++++++++++++++++++ doc/playground.html | 63 ++++++ doc/playground.js | 499 ++++++++++++++++++++++++++++++++++++++++++++ doc/robots.txt | 2 + 6 files changed, 1123 insertions(+), 72 deletions(-) create mode 100644 doc/playground.css create mode 100644 doc/playground.html create mode 100644 doc/playground.js create mode 100644 doc/robots.txt diff --git a/doc/index.css b/doc/index.css index b4683cf24f..e33d019791 100644 --- a/doc/index.css +++ b/doc/index.css @@ -1,84 +1,186 @@ :root { - --color-background: #1c1f26; - --color-text: white; + --color-ruby: #CC342D; + --color-ruby-dark: #A50C07; + --color-bg: #FFFFFF; + --color-bg-alt: #F7F7F7; + --color-text: #3E4451; + --color-text-light: #6B7280; + --color-border: #E5E7EB; } -body { - background-color: var(--color-background); - font-family: "Noto Sans", "Helvetica Neue", Helvetica, sans-serif; +* { margin: 0; + padding: 0; + box-sizing: border-box; } -header { - height: 10vh; +body { + background-color: var(--color-bg); + color: var(--color-text); + font-family: "Noto Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + line-height: 1.6; } -h1 { - color: var(--color-text); +header { + background-color: var(--color-ruby); + color: white; + padding: 3rem 2rem; text-align: center; - line-height: 10vh; - margin: 0; +} + +header h1 { + font-size: 2.25rem; + font-weight: 700; + margin-bottom: 0.5rem; +} + +header p { + font-size: 1.1rem; +} + +:focus-visible { + outline: 2px solid var(--color-ruby); + outline-offset: 2px; } main { - display: grid; - grid-template-rows: 1fr 1fr; - grid-template-columns: 1fr 1fr; - height: 36vh; - margin: 2vh 20vw; + max-width: 56rem; + margin: 0 auto; + padding: 0 2rem; } -@media only screen and (max-width: 1200px) { - main { - margin: 2vh 10vw; - } +section { + margin-top: 2.5rem; } -@media only screen and (max-width: 900px) { - main { - grid-template-rows: repeat(1fr); - grid-template-columns: 1fr; - height: 72vh; - } +section h2 { + font-size: 1.25rem; + font-weight: 700; + margin-bottom: 1rem; + color: var(--color-text); +} + +section p { + color: var(--color-text-light); + font-size: 0.9375rem; + margin-bottom: 0.75rem; +} + +.playground-link { + display: inline-block; + margin-top: 0.5rem; + padding: 0.625rem 1.25rem; + background: var(--color-ruby); + color: white; + text-decoration: none; + border-radius: 0.375rem; + font-size: 0.9375rem; + font-weight: 600; + transition: background-color 150ms ease; +} + +.playground-link:hover { + background: var(--color-ruby-dark); +} + +pre { + background: var(--color-bg-alt); + border: 1px solid var(--color-border); + border-radius: 0.375rem; + padding: 0.75rem 1rem; + font-size: 0.875rem; + overflow-x: auto; + margin-bottom: 0.75rem; +} + +code { + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; } -@media only screen and (max-width: 600px) { - main { - margin: 2vh 5vw; +/* API reference cards */ +.grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; +} + +@media (max-width: 640px) { + .grid { + grid-template-columns: 1fr; } } .reference { - border-radius: 1em; - box-sizing: border-box; - color: var(--color-text); - height: 18vh; - padding: 4vh 0; - text-align: center; + display: flex; + align-items: center; + gap: 1.25rem; + padding: 1.25rem; + border: 1px solid var(--color-border); + border-radius: 0.5rem; text-decoration: none; - transition: background-color 100ms ease; - vertical-align: middle; + color: var(--color-text); + background: var(--color-bg); + transition: border-color 150ms ease, box-shadow 150ms ease; +} + +.reference:hover { + border-color: var(--color-ruby); + box-shadow: 0 2px 8px rgba(204, 52, 45, 0.1); } -.reference > img { - height: 10vh; - width: 10vh; - margin-right: 1em; - vertical-align: middle; +.reference img { + width: 2.5rem; + height: 2.5rem; + flex-shrink: 0; } -.reference > h2 { - display: inline; +.reference h3 { + font-size: 1rem; + font-weight: 600; margin: 0; - text-decoration: underline; + color: var(--color-ruby); } -.reference:hover { - background-color: rgba(255, 255, 255, 0.1); +.reference span { + display: block; + font-size: 0.8125rem; + color: var(--color-text-light); + margin-top: 0.125rem; } -#logo { +/* Guide links */ +.guide { display: block; - height: 50vh; - margin: 0 auto; + padding: 0.625rem 0.875rem; + border: 1px solid var(--color-border); + border-radius: 0.375rem; + text-decoration: none; + color: var(--color-text); + font-size: 0.875rem; + transition: border-color 150ms ease, color 150ms ease; +} + +.guide:hover { + border-color: var(--color-ruby); + color: var(--color-ruby); +} + +/* Footer */ +footer { + margin-top: 3rem; + padding: 1.5rem 2rem; + text-align: center; + border-top: 1px solid var(--color-border); + display: flex; + justify-content: center; + gap: 2rem; +} + +footer a { + color: var(--color-text-light); + font-size: 0.875rem; +} + +footer a:hover { + color: var(--color-ruby); } diff --git a/doc/index.html b/doc/index.html index 9e0e38cb60..b3af99e367 100644 --- a/doc/index.html +++ b/doc/index.html @@ -2,37 +2,86 @@ - - Prism - - + + + Prism Ruby Parser + + + +
-

Prism Ruby parser

+

Prism

+

A portable, error-tolerant Ruby parser

diff --git a/doc/playground.css b/doc/playground.css new file mode 100644 index 0000000000..9666ae4bfe --- /dev/null +++ b/doc/playground.css @@ -0,0 +1,336 @@ +:root { + --color-ruby: #CC342D; + --color-ruby-light: rgba(204, 52, 45, 0.15); + --color-bg: #FFFFFF; + --color-bg-alt: #F7F7F7; + --color-text: #3E4451; + --color-text-light: #6B7280; + --color-border: #E5E7EB; + --color-highlight: rgba(204, 52, 45, 0.12); +} + +* { margin: 0; padding: 0; box-sizing: border-box; } + +body { + font-family: "Noto Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + color: var(--color-text); + height: 100vh; + display: flex; + flex-direction: column; +} + +:focus-visible { + outline: 2px solid var(--color-ruby); + outline-offset: 2px; +} + +.skip-link { + position: absolute; + left: -9999px; + top: 0; + background: var(--color-ruby); + color: white; + padding: 0.5rem 1rem; + z-index: 200; + font-size: 0.875rem; + text-decoration: none; +} + +.skip-link:focus { + left: 0; +} + +nav { + background: var(--color-ruby); + color: white; + padding: 0.5rem 1rem; + display: flex; + align-items: center; + justify-content: space-between; + flex-shrink: 0; + gap: 0.5rem; +} + +nav h1 { font-size: 1.1rem; font-weight: 600; } +nav a { color: white; text-decoration: none; font-size: 0.8125rem; } +nav a:hover { text-decoration: underline; } +nav a:focus-visible { outline-color: white; } + +.nav-left { + display: flex; + align-items: center; + gap: 0.75rem; + min-width: 0; +} + +.nav-right { + display: flex; + align-items: center; + gap: 0.5rem; +} + +@media (max-width: 540px) { + .nav-version, .nav-right a { display: none; } +} + +.nav-version { + font-size: 0.75rem; + color: rgba(255,255,255,0.9); +} + +.nav-select, .nav-button { + font-family: inherit; + font-size: 0.8125rem; + height: 1.75rem; + padding: 0 0.5rem; + border: 1px solid rgba(255,255,255,0.4); + border-radius: 4px; + background: rgba(255,255,255,0.15); + color: white; + cursor: pointer; +} + +.nav-select:hover, .nav-button:hover { + background: rgba(255,255,255,0.25); +} + +.nav-select:focus-visible, .nav-button:focus-visible { + outline-color: white; +} + +.nav-select option { + color: var(--color-text); + background: white; +} + +main { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; +} + +#loading { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-text-light); +} + +#loading.hidden { + display: none; +} + +.editor { + flex: 1; + display: none; + grid-template-columns: 1fr 1fr; + min-height: 0; +} + +.editor.ready { display: grid; } + +@media (max-width: 1024px) { + .editor { + grid-template-columns: 1fr; + grid-template-rows: minmax(40vh, 1fr) minmax(40vh, 1fr); + overflow: auto; + } +} + +#monaco-container { + border-right: 1px solid var(--color-border); + min-width: 0; + overflow: hidden; +} + +.output-panel { + display: flex; + flex-direction: column; + overflow: hidden; +} + +.tabs { + display: flex; + flex-wrap: wrap; + align-items: center; + border-bottom: 1px solid var(--color-border); + background: var(--color-bg); + flex-shrink: 0; +} + +.tabs button[role="tab"] { + padding: 0.625rem 1rem; + border: none; + background: none; + font-family: inherit; + font-size: 0.8125rem; + color: var(--color-text-light); + cursor: pointer; + border-bottom: 2px solid transparent; +} + +.tabs button[role="tab"]:hover { color: var(--color-text); } +.tabs button[role="tab"].active { + color: var(--color-ruby); + border-bottom-color: var(--color-ruby); +} + +.tabs-spacer { + flex: 1; +} + +.tab-action { + font-family: inherit; + font-size: 0.75rem; + padding: 0.25rem 0.5rem; + margin-right: 0.375rem; + border: 1px solid var(--color-border); + border-radius: 3px; + background: var(--color-bg); + color: var(--color-text-light); + cursor: pointer; +} + +.tab-action:hover { + color: var(--color-text); + border-color: var(--color-text-light); +} + +#output { + flex: 1; + overflow: auto; + background: var(--color-bg-alt); + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + font-size: 13px; + line-height: 1.5; + padding: 0.75rem; +} + +/* AST tree styles */ +.tree-node { + white-space: pre; +} + +.tree-type { + color: var(--color-ruby); + font-weight: 600; + cursor: pointer; +} + +.tree-type:hover { + text-decoration: underline; +} + +.tree-loc { + color: var(--color-text-light); + cursor: pointer; +} + +.tree-loc:hover { + color: var(--color-ruby); +} + +.tree-toggle { + display: inline-block; + cursor: pointer; + user-select: none; + color: var(--color-text-light); + background: none; + border: none; + padding: 0.125em 0.25em; + margin-right: 0.125em; + font: inherit; + line-height: inherit; + border-radius: 2px; +} + +.tree-toggle:hover { + color: var(--color-ruby); + background: var(--color-highlight); +} + +.tree-children.collapsed { + display: none; +} + +.tree-field { + color: var(--color-text-light); +} + +.tree-value { + color: var(--color-text); +} + +.tree-string { + color: #953800; +} + +.tree-null { + color: var(--color-text-light); + font-style: italic; +} + +.tree-connector { + color: #d1d5db; +} + +.tree-flag { + display: inline-block; + padding: 0 0.375em; + border-radius: 3px; + font-size: 0.85em; + vertical-align: middle; + background: rgba(204, 52, 45, 0.08); + color: var(--color-ruby); +} + +.tree-highlight { + background: var(--color-highlight); + border-radius: 2px; +} + +.prism-highlight { + background: var(--color-ruby-light) !important; +} + +.diagnostics-line { + padding: 0.25rem 0; +} + +.diagnostics-line[data-sl] { + cursor: pointer; +} + +.error-text { color: var(--color-ruby); } +.warning-text { color: #b45309; } + +.noscript-message { + padding: 2rem; + text-align: center; + color: var(--color-text-light); +} + +.empty-message { + padding: 0.5rem; +} + +.share-toast { + position: fixed; + bottom: 1rem; + left: 50%; + transform: translateX(-50%); + padding: 0.5rem 1rem; + background: var(--color-text); + color: white; + border-radius: 4px; + font-size: 0.8125rem; + z-index: 100; + opacity: 0; + transition: opacity 200ms; +} + +.share-toast.visible { + opacity: 1; +} diff --git a/doc/playground.html b/doc/playground.html new file mode 100644 index 0000000000..cc1e17367f --- /dev/null +++ b/doc/playground.html @@ -0,0 +1,63 @@ + + + + + + + + Prism - Playground + + + + + + + + + + + +
+
Loading…
+ + +
+
+
+
+ + + + + +
+
+
+
+
+ + + + + + + diff --git a/doc/playground.js b/doc/playground.js new file mode 100644 index 0000000000..f593b96afe --- /dev/null +++ b/doc/playground.js @@ -0,0 +1,499 @@ +import { WASI } from "https://unpkg.com/@bjorn3/browser_wasi_shim@latest/dist/index.js"; +import { parsePrism } from "https://unpkg.com/@ruby/prism@latest/src/parsePrism.js"; + +const output = document.getElementById("output"); +const editorDiv = document.getElementById("editor"); +const loading = document.getElementById("loading"); +const toast = document.getElementById("toast"); + +// Load Prism WASM and Monaco, show error if either fails +let instance, monaco; +try { + const [wasmResult] = await Promise.all([ + WebAssembly.compileStreaming(fetch("https://unpkg.com/@ruby/prism@latest/src/prism.wasm")) + .then(wasm => { + const wasi = new WASI([], [], []); + return WebAssembly.instantiate(wasm, { wasi_snapshot_preview1: wasi.wasiImport }) + .then(inst => { wasi.initialize(inst); return inst; }); + }), + fetch("https://unpkg.com/@ruby/prism@latest/package.json") + .then(r => r.json()) + .then(pkg => { document.getElementById("version").textContent = `v${pkg.version}`; }) + .catch(() => {}) + ]); + instance = wasmResult; + + monaco = await new Promise((resolve, reject) => { + require.config({ paths: { vs: "https://cdn.jsdelivr.net/npm/monaco-editor@0.52.2/min/vs" } }); + require(["vs/editor/editor.main"], resolve, reject); + }); +} catch (error) { + loading.textContent = `Failed to load: ${error.message}`; + throw error; +} + +// Example snippets +const EXAMPLES = { + fibonacci: `def fibonacci(n) + case n + when 0 + 0 + when 1 + 1 + else + fibonacci(n - 1) + fibonacci(n - 2) + end +end +`, + pattern: `case [1, [2, 3]] +in [Integer => a, [Integer => b, Integer => c]] + puts "matched: \#{a}, \#{b}, \#{c}" +in [Integer => a, *rest] + puts "first: \#{a}, rest: \#{rest}" +end + +config = { name: "prism", version: "1.0" } + +case config +in { name: /^pr/ => name, version: } + puts "\#{name} v\#{version}" +end +`, + heredoc: `name = "World" + +message = <<~HEREDOC + Hello, \#{name}! + Today is \#{Time.now}. +HEREDOC + +query = <<~SQL.strip + SELECT * + FROM users + WHERE active = true +SQL +`, + blocks: `numbers = [1, 2, 3, 4, 5] + +squares = numbers.map { |n| n ** 2 } +evens = numbers.select(&:even?) + +doubler = ->(x) { x * 2 } + +numbers.each do |n| + puts doubler.call(n) +end + +def with_logging(&block) + puts "start" + result = block.call + puts "end" + result +end +`, + class: `class Person + attr_accessor :name, :age + + def initialize(name, age) + @name = name + @age = age + end + + def greeting = "Hi, I'm \#{name}!" + + def <=>(other) + age <=> other.age + end + + private + + def validate! + raise ArgumentError, "Invalid age" unless age&.positive? + end +end +` +}; + +// URL-safe base64 encode/decode (RFC 4648 §5) +function encodeSource(str) { + const bytes = new TextEncoder().encode(str); + let binary = ""; + for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]); + return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); +} + +function decodeSource(str) { + const padded = str.replace(/-/g, "+").replace(/_/g, "/") + "==".slice(0, (4 - str.length % 4) % 4); + return new TextDecoder().decode(Uint8Array.from(atob(padded), ch => ch.codePointAt(0))); +} + +// Read initial source from URL hash or use default +function sourceFromHash() { + const hash = location.hash.slice(1); + if (!hash) return null; + try { return decodeSource(hash); } catch { return null; } +} + +const initialSource = sourceFromHash() || EXAMPLES.fibonacci; + +monaco.editor.defineTheme("prism", { + base: "vs", + inherit: true, + rules: [], + colors: { "editorLineNumber.foreground": "#6B7280" } +}); + +const monacoEditor = monaco.editor.create(document.getElementById("monaco-container"), { + theme: "prism", + value: initialSource, + language: "ruby", + minimap: { enabled: false }, + fontSize: 14, + lineHeight: 21, + scrollBeyondLastLine: false, + automaticLayout: true, + tabSize: 2 +}); + +let currentTab = "ast"; +let lastResult = null; +let lastSource = ""; +let currentDecorations = []; + +// Tab switching +const tabs = Array.from(document.querySelectorAll("[role=tab]")); + +function activateTab(tab) { + tabs.forEach(t => { + t.classList.remove("active"); + t.setAttribute("aria-selected", "false"); + t.setAttribute("tabindex", "-1"); + }); + tab.classList.add("active"); + tab.setAttribute("aria-selected", "true"); + tab.setAttribute("tabindex", "0"); + tab.focus(); + currentTab = tab.dataset.tab; + render(); +} + +document.querySelector(".tabs").addEventListener("click", (event) => { + const tab = event.target.closest("[role=tab]"); + if (tab) activateTab(tab); +}); + +document.querySelector(".tabs").addEventListener("keydown", (event) => { + const tab = event.target.closest("[role=tab]"); + if (!tab) return; + const index = tabs.indexOf(tab); + let next = -1; + if (event.key === "ArrowRight") next = (index + 1) % tabs.length; + else if (event.key === "ArrowLeft") next = (index - 1 + tabs.length) % tabs.length; + else if (event.key === "Home") next = 0; + else if (event.key === "End") next = tabs.length - 1; + if (next >= 0) { + event.preventDefault(); + activateTab(tabs[next]); + } +}); + +// Examples dropdown +document.getElementById("examples").addEventListener("change", (event) => { + const key = event.target.value; + if (key && EXAMPLES[key]) { + monacoEditor.setValue(EXAMPLES[key]); + monacoEditor.focus(); + } +}); + +// Share button +document.getElementById("share").addEventListener("click", async () => { + try { + await navigator.clipboard.writeText(location.href); + showToast("Link copied to clipboard"); + } catch { + showToast("Copy the URL from the address bar"); + } +}); + +let toastTimeout = null; +function showToast(message) { + if (toastTimeout) clearTimeout(toastTimeout); + toast.textContent = message; + toast.classList.add("visible"); + toastTimeout = setTimeout(() => toast.classList.remove("visible"), 2000); +} + +// Shared toggle helper +function setToggleState(toggle, collapsed) { + const treeitem = toggle.closest(".tree-node"); + const children = treeitem.nextElementSibling; + if (!children || !children.classList.contains("tree-children")) return; + children.classList.toggle("collapsed", collapsed); + toggle.textContent = collapsed ? "▶" : "▼"; + treeitem.setAttribute("aria-expanded", String(!collapsed)); +} + +document.getElementById("collapse-all").addEventListener("click", () => { + output.querySelectorAll(".tree-toggle").forEach(toggle => setToggleState(toggle, true)); +}); + +document.getElementById("expand-all").addEventListener("click", () => { + output.querySelectorAll(".tree-toggle").forEach(toggle => setToggleState(toggle, false)); +}); + +// Convert byte offset to line:column using the source string +function offsetToLineCol(source, offset) { + let line = 1, col = 0; + for (let i = 0; i < offset && i < source.length; i++) { + if (source[i] === "\n") { line++; col = 0; } + else { col++; } + } + return { line, col }; +} + + +function formatLoc(source, loc) { + if (!loc || loc.startOffset === undefined) return null; + const start = offsetToLineCol(source, loc.startOffset); + const end = offsetToLineCol(source, loc.startOffset + loc.length); + return { start, end, text: `${start.line}:${start.col}-${end.line}:${end.col}` }; +} + +function locDataAttrs(loc) { + if (!loc) return ""; + return ` data-sl="${loc.start.line}" data-sc="${loc.start.col}" data-el="${loc.end.line}" data-ec="${loc.end.col}"`; +} + +// Highlight a range in Monaco +function highlightRange(startLine, startCol, endLine, endCol) { + currentDecorations = monacoEditor.deltaDecorations(currentDecorations, [{ + range: new monaco.Range(startLine, startCol + 1, endLine, endCol + 1), + options: { + className: "prism-highlight", + isWholeLine: false + } + }]); +} + +function clearHighlight() { + currentDecorations = monacoEditor.deltaDecorations(currentDecorations, []); +} + +// Detect whether a value is a Prism AST node (class instance with location) +function isNode(value) { + return value && typeof value === "object" && !Array.isArray(value) && value.location && value.constructor && value.constructor.name !== "Object"; +} + +// Get the node type name from the class name +function nodeType(node) { + return node.constructor?.name || "Unknown"; +} + +// Get the enumerable field names, skipping internal ones +const SKIP_FIELDS = new Set(["nodeID", "location", "flags"]); +function nodeFields(node) { + const fields = []; + for (const key of Object.getOwnPropertyNames(node)) { + if (!SKIP_FIELDS.has(key) && !key.startsWith("#")) fields.push(key); + } + return fields; +} + +// Decode flags by calling is*() predicate methods on the node's prototype +const flagNamesCache = new WeakMap(); +function flagPredicateNames(proto) { + let names = flagNamesCache.get(proto); + if (!names) { + names = Object.getOwnPropertyNames(proto).filter(n => n.startsWith("is") && typeof proto[n] === "function"); + flagNamesCache.set(proto, names); + } + return names; +} + +function activeFlags(node) { + const proto = Object.getPrototypeOf(node); + if (!proto) return []; + const flags = []; + for (const name of flagPredicateNames(proto)) { + try { if (node[name]()) flags.push(name.slice(2)); } catch (e) {} + } + return flags; +} + +// Check if a node has child nodes (not just scalar fields) +function hasChildNodes(fields, node) { + for (const field of fields) { + const value = node[field]; + if (isNode(value)) return true; + if (Array.isArray(value) && value.some(isNode)) return true; + } + return false; +} + +const CONNECTOR = { last: "└── ", mid: "├── ", lastPad: " ", midPad: "│ " }; + +// Build the AST tree as interactive HTML +function renderNode(node, source, prefix, isLast, isRoot) { + if (!isNode(node)) return ""; + + const type = nodeType(node); + const childPrefix = isRoot ? "" : prefix + (isLast ? CONNECTOR.lastPad : CONNECTOR.midPad); + const fields = nodeFields(node); + const foldable = hasChildNodes(fields, node); + const escapedType = escapeHtml(type); + + let html = `
`; + if (!isRoot) html += ``; + if (foldable) html += ``; + + const loc = formatLoc(source, node.location); + const locAttrs = locDataAttrs(loc); + + html += `@ ${escapedType}`; + if (loc) html += ` (${loc.text})`; + html += `
`; + + html += `
`; + const flags = activeFlags(node); + const hasFields = fields.length > 0; + if (flags.length > 0) { + const flagConnector = hasFields ? CONNECTOR.mid : CONNECTOR.last; + html += `
flags: ${flags.map(f => `${escapeHtml(f)}`).join(" ")}
`; + } + fields.forEach((field, idx) => { + const value = node[field]; + const fieldIsLast = idx === fields.length - 1; + const fieldConnector = fieldIsLast ? CONNECTOR.last : CONNECTOR.mid; + const fieldChildPrefix = childPrefix + (fieldIsLast ? CONNECTOR.lastPad : CONNECTOR.midPad); + + if (value === null || value === undefined) { + html += `
${escapeHtml(field)}:
`; + } else if (Array.isArray(value)) { + if (value.length === 0) { + html += `
${escapeHtml(field)}: []
`; + } else { + html += `
${escapeHtml(field)}: (${value.length} item${value.length === 1 ? "" : "s"})
`; + value.forEach((item, i) => { + if (isNode(item)) { + html += renderNode(item, source, fieldChildPrefix, i === value.length - 1); + } else { + const itemConnector = i === value.length - 1 ? CONNECTOR.last : CONNECTOR.mid; + html += `
${escapeHtml(JSON.stringify(item))}
`; + } + }); + } + } else if (isNode(value)) { + html += `
${escapeHtml(field)}:
`; + html += renderNode(value, source, fieldChildPrefix, true); + } else if (typeof value === "object" && value.startOffset !== undefined) { + const fieldLoc = formatLoc(source, value); + if (fieldLoc) { + html += `
${escapeHtml(field)}: ${fieldLoc.text}
`; + } + } else if (typeof value === "string") { + html += `
${escapeHtml(field)}: ${escapeHtml(JSON.stringify(value))}
`; + } else { + html += `
${escapeHtml(field)}: ${escapeHtml(String(value))}
`; + } + }); + html += `
`; + + return html; +} + +const ESCAPE_MAP = { "&": "&", "<": "<", ">": ">", '"': """ }; +function escapeHtml(str) { + return str.replace(/[&<>"]/g, ch => ESCAPE_MAP[ch]); +} + +// Render a single diagnostic line +function renderDiagnostic(source, item, kind) { + const loc = formatLoc(source, item.location); + const cssClass = kind === "Error" ? "error-text" : "warning-text"; + return `
${kind}: ${escapeHtml(item.message)}${loc ? ` (${loc.text})` : ""}
`; +} + +// Delegated event handlers on #output (attached once, survive re-renders) +output.addEventListener("click", (event) => { + const toggle = event.target.closest(".tree-toggle"); + if (toggle) { + const treeitem = toggle.closest(".tree-node"); + const collapsed = treeitem.getAttribute("aria-expanded") === "true"; + setToggleState(toggle, collapsed); + return; + } + + const locEl = event.target.closest("[data-sl]"); + if (locEl) { + const sl = parseInt(locEl.dataset.sl); + const sc = parseInt(locEl.dataset.sc); + monacoEditor.revealLineInCenter(sl); + monacoEditor.setPosition({ lineNumber: sl, column: sc + 1 }); + monacoEditor.focus(); + } +}); + +output.addEventListener("mouseenter", (event) => { + const locEl = event.target.closest("[data-sl]"); + if (!locEl) return; + highlightRange(parseInt(locEl.dataset.sl), parseInt(locEl.dataset.sc), parseInt(locEl.dataset.el), parseInt(locEl.dataset.ec)); + (locEl.closest(".tree-node") || locEl).classList.add("tree-highlight"); +}, true); + +output.addEventListener("mouseleave", (event) => { + const locEl = event.target.closest("[data-sl]"); + if (!locEl) return; + clearHighlight(); + (locEl.closest(".tree-node") || locEl).classList.remove("tree-highlight"); +}, true); + + +function render() { + if (!lastResult) return; + + output.setAttribute("aria-labelledby", currentTab === "ast" ? "tab-ast" : "tab-diagnostics"); + + switch (currentTab) { + case "ast": + const tree = renderNode(lastResult.value, lastSource, "", true, true); + output.innerHTML = tree + ? `
${tree}
` + : `
${escapeHtml(lastResult.error || "Failed to parse.")}
`; + break; + + case "diagnostics": + const errors = lastResult.errors || []; + const warnings = lastResult.warnings || []; + if (errors.length === 0 && warnings.length === 0) { + output.innerHTML = `
No errors or warnings.
`; + } else { + let html = ""; + for (const err of errors) html += renderDiagnostic(lastSource, err, "Error"); + for (const warn of warnings) html += renderDiagnostic(lastSource, warn, "Warning"); + output.innerHTML = html; + } + break; + } +} + +let timeout = null; +function parse() { + if (timeout) clearTimeout(timeout); + timeout = setTimeout(() => { + lastSource = monacoEditor.getValue(); + history.replaceState(null, "", `#${encodeSource(lastSource)}`); + try { + lastResult = parsePrism(instance.exports, lastSource); + } catch (e) { + lastResult = { value: null, error: e.message, errors: [], warnings: [] }; + } + render(); + }, 200); +} + +monacoEditor.onDidChangeModelContent(parse); + +// Ready +loading.classList.add("hidden"); +editorDiv.classList.add("ready"); +parse(); diff --git a/doc/robots.txt b/doc/robots.txt new file mode 100644 index 0000000000..c2a49f4fb8 --- /dev/null +++ b/doc/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / From cbe91a3f36fb3f103592a8f427a64a66c8630d98 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 19 Mar 2026 12:14:34 -0500 Subject: [PATCH 264/289] Swich identifiers to byte[] * JAVA_STRING_TYPE and related change to IDENTIFIER * TruffleRuby still uses java.lang.String Fixes #4009 --- templates/java/org/ruby_lang/prism/Loader.java.erb | 8 ++++---- templates/java/org/ruby_lang/prism/Nodes.java.erb | 6 +++--- templates/template.rb | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 534d8401ca..bf1bf7a625 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,4 +1,4 @@ -<%- string_type = Prism::Template::JAVA_STRING_TYPE -%> +<%- string_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> package org.ruby_lang.prism; import java.lang.Short; @@ -31,7 +31,7 @@ public class Loader { <%- if string_type == "String" -%> return new String(bytes, encodingCharset).intern(); <%- else -%> - return null; // Must be implemented by subclassing Loader + return bytes; // Must be implemented by subclassing Loader <%- end -%> } @@ -229,7 +229,7 @@ public class Loader { private <%= string_type %>[] loadConstants() { int length = loadVarUInt(); if (length == 0) { - return Nodes.EMPTY_STRING_ARRAY; + return Nodes.EMPTY_IDENTIFIER_ARRAY; } <%= string_type %>[] constants = new <%= string_type %>[length]; for (int i = 0; i < length; i++) { @@ -395,7 +395,7 @@ public class Loader { int bufferPosition = buffer.position(); int serializedLength = buffer.getInt(); // Load everything except the body and locals, because the name, receiver, parameters are still needed for lazily defining the method - Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_STRING_ARRAY); + Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_IDENTIFIER_ARRAY); buffer.position(bufferPosition + serializedLength); // skip past the serialized DefNode return lazyDefNode; } diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index de597eea67..f43df2623e 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -1,4 +1,4 @@ -<%- string_type = Prism::Template::JAVA_STRING_TYPE -%> +<%- id_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> package org.ruby_lang.prism; import java.lang.Override; @@ -16,7 +16,7 @@ import java.util.Arrays; // @formatter:off public abstract class Nodes { - public static final <%= string_type %>[] EMPTY_STRING_ARRAY = {}; + public static final <%= id_type %>[] EMPTY_IDENTIFIER_ARRAY = {}; @Target(ElementType.FIELD) @Retention(RetentionPolicy.SOURCE) @@ -383,7 +383,7 @@ public abstract class Nodes { builder.append('\n'); <%- when Prism::Template::ConstantListField -%> builder.append('\n'); - for (<%= string_type %> constant : this.<%= field.name %>) { + for (<%= id_type %> constant : this.<%= field.name %>) { builder.append(nextNextIndent).append('"').append(constant).append('"').append('\n'); } <%- when Prism::Template::Flags -%> diff --git a/templates/template.rb b/templates/template.rb index 8f7734dd43..be39c2f682 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -12,7 +12,7 @@ module Template # :nodoc: all CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false) JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby" - JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String" + JAVA_IDENTIFIER_TYPE = JAVA_BACKEND == "truffleruby" ? "String" : "byte[]" INCLUDE_NODE_ID = !SERIALIZE_ONLY_SEMANTICS_FIELDS || JAVA_BACKEND == "jruby" COMMON_FLAGS_COUNT = 2 @@ -272,7 +272,7 @@ def call_seq_type end def java_type - JAVA_STRING_TYPE + JAVA_IDENTIFIER_TYPE end end @@ -292,7 +292,7 @@ def call_seq_type end def java_type - JAVA_STRING_TYPE + JAVA_IDENTIFIER_TYPE end end @@ -312,7 +312,7 @@ def call_seq_type end def java_type - "#{JAVA_STRING_TYPE}[]" + "#{JAVA_IDENTIFIER_TYPE}[]" end end From 6ad180a00d51b8b9fb3896cb98da1740db5c37c0 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 09:59:53 -0500 Subject: [PATCH 265/289] Tweaks for byte[] identifiers * Allocate array of byte[] as byte[length][]. * Default JAVA_BACKEND to "default" with "truffleruby" the custom option. --- .../java/org/ruby_lang/prism/Loader.java.erb | 34 ++++++++++++------- templates/template.rb | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index bf1bf7a625..ae8007bf90 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,4 +1,4 @@ -<%- string_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> +<%- id_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> package org.ruby_lang.prism; import java.lang.Short; @@ -27,8 +27,8 @@ public class Loader { return Charset.forName(encodingName); } - public <%= string_type %> bytesToName(byte[] bytes) { - <%- if string_type == "String" -%> + public <%= id_type %> bytesToName(byte[] bytes) { + <%- if id_type == "String" -%> return new String(bytes, encodingCharset).intern(); <%- else -%> return bytes; // Must be implemented by subclassing Loader @@ -39,17 +39,21 @@ public class Loader { private final Loader loader; private final int bufferOffset; - private final <%= string_type %>[] cache; + private final <%= id_type %>[] cache; ConstantPool(Loader loader, int bufferOffset, int length) { this.loader = loader; this.bufferOffset = bufferOffset; - cache = new <%= string_type %>[length]; + <%- if id_type == "String" -%> + cache = new <%= id_type %>[length]; + <%- else -%> + cache = new byte[length][]; + <%- end -%> } - <%= string_type %> get(ByteBuffer buffer, int oneBasedIndex) { + <%= id_type %> get(ByteBuffer buffer, int oneBasedIndex) { int index = oneBasedIndex - 1; - <%= string_type %> constant = cache[index]; + <%= id_type %> constant = cache[index]; if (constant == null) { int offset = bufferOffset + index * 8; @@ -70,7 +74,7 @@ public class Loader { private final ByteBuffer buffer; protected String encodingName; - <%- if string_type == "String" -%> + <%- if id_type == "String" -%> private Charset encodingCharset; <%- end -%> private ConstantPool constantPool; @@ -100,7 +104,7 @@ public class Loader { byte[] encodingNameBytes = new byte[encodingLength]; buffer.get(encodingNameBytes); this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII); - <%- if string_type == "String" -%> + <%- if id_type == "String" -%> this.encodingCharset = getEncodingCharset(this.encodingName); <%- end -%> @@ -213,11 +217,11 @@ public class Loader { } } - private <%= string_type %> loadConstant() { + private <%= id_type %> loadConstant() { return constantPool.get(buffer, loadVarUInt()); } - private <%= string_type %> loadOptionalConstant() { + private <%= id_type %> loadOptionalConstant() { if (buffer.get(buffer.position()) != 0) { return loadConstant(); } else { @@ -226,12 +230,16 @@ public class Loader { } } - private <%= string_type %>[] loadConstants() { + private <%= id_type %>[] loadConstants() { int length = loadVarUInt(); if (length == 0) { return Nodes.EMPTY_IDENTIFIER_ARRAY; } - <%= string_type %>[] constants = new <%= string_type %>[length]; + <%- if id_type == "String" -%> + <%= id_type %>[] constants = new <%= id_type %>[length]; + <%- else -%> + <%= id_type %>[] constants = new byte[length][]; + <%- end -%> for (int i = 0; i < length; i++) { constants[i] = constantPool.get(buffer, loadVarUInt()); } diff --git a/templates/template.rb b/templates/template.rb index be39c2f682..5d1afc9506 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -11,7 +11,7 @@ module Template # :nodoc: all REMOVE_ON_ERROR_TYPES = SERIALIZE_ONLY_SEMANTICS_FIELDS CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false) - JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby" + JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "default" JAVA_IDENTIFIER_TYPE = JAVA_BACKEND == "truffleruby" ? "String" : "byte[]" INCLUDE_NODE_ID = !SERIALIZE_ONLY_SEMANTICS_FIELDS || JAVA_BACKEND == "jruby" From 5de563794a607fd02ff762be73aaf839e6e17bfb Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 10:49:52 -0500 Subject: [PATCH 266/289] Remove no-longer-relevant comment Co-authored-by: Benoit Daloze --- templates/java/org/ruby_lang/prism/Loader.java.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index ae8007bf90..5695e5a651 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -31,7 +31,7 @@ public class Loader { <%- if id_type == "String" -%> return new String(bytes, encodingCharset).intern(); <%- else -%> - return bytes; // Must be implemented by subclassing Loader + return bytes; <%- end -%> } From ccafd2a7d633ce4eea6e69027a6db83c65b3f092 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 15:52:22 -0500 Subject: [PATCH 267/289] Eliminate encodingCharset and bytesToName With identifiers moving to byte[] there's no need to have bytesToName in the logic. It remains as an abstract method in the String version for TruffleRuby to implement their way. --- .../java/org/ruby_lang/prism/Loader.java.erb | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 5695e5a651..3e44cccc14 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -19,21 +19,9 @@ public class Loader { // Overridable methods - public Charset getEncodingCharset(String encodingName) { - encodingName = encodingName.toLowerCase(Locale.ROOT); - if (encodingName.equals("ascii-8bit")) { - return StandardCharsets.US_ASCII; - } - return Charset.forName(encodingName); - } - - public <%= id_type %> bytesToName(byte[] bytes) { - <%- if id_type == "String" -%> - return new String(bytes, encodingCharset).intern(); - <%- else -%> - return bytes; - <%- end -%> - } + <%- if id_type == "String" -%> + public abstract <%= id_type %> bytesToName(byte[] bytes); + <%- end -%> private static final class ConstantPool { @@ -63,7 +51,11 @@ public class Loader { byte[] bytes = new byte[length]; buffer.get(start, bytes); + <%- if id_type == "byte[]" -%> + constant = bytes; + <%- else %> constant = loader.bytesToName(bytes); + <%- end %> cache[index] = constant; } @@ -74,9 +66,6 @@ public class Loader { private final ByteBuffer buffer; protected String encodingName; - <%- if id_type == "String" -%> - private Charset encodingCharset; - <%- end -%> private ConstantPool constantPool; private Nodes.Source source = null; @@ -104,9 +93,6 @@ public class Loader { byte[] encodingNameBytes = new byte[encodingLength]; buffer.get(encodingNameBytes); this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII); - <%- if id_type == "String" -%> - this.encodingCharset = getEncodingCharset(this.encodingName); - <%- end -%> source.setStartLine(loadVarSInt()); source.setLineOffsets(loadLineOffsets()); From efe36fbc46e750edf86baa20c6a63efc6c2551f2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 20 Mar 2026 17:58:06 -0400 Subject: [PATCH 268/289] Revert "Switch identifiers to byte[]" --- .../java/org/ruby_lang/prism/Loader.java.erb | 58 ++++++++++--------- .../java/org/ruby_lang/prism/Nodes.java.erb | 6 +- templates/template.rb | 10 ++-- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 3e44cccc14..534d8401ca 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,4 +1,4 @@ -<%- id_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> +<%- string_type = Prism::Template::JAVA_STRING_TYPE -%> package org.ruby_lang.prism; import java.lang.Short; @@ -19,29 +19,37 @@ public class Loader { // Overridable methods - <%- if id_type == "String" -%> - public abstract <%= id_type %> bytesToName(byte[] bytes); - <%- end -%> + public Charset getEncodingCharset(String encodingName) { + encodingName = encodingName.toLowerCase(Locale.ROOT); + if (encodingName.equals("ascii-8bit")) { + return StandardCharsets.US_ASCII; + } + return Charset.forName(encodingName); + } + + public <%= string_type %> bytesToName(byte[] bytes) { + <%- if string_type == "String" -%> + return new String(bytes, encodingCharset).intern(); + <%- else -%> + return null; // Must be implemented by subclassing Loader + <%- end -%> + } private static final class ConstantPool { private final Loader loader; private final int bufferOffset; - private final <%= id_type %>[] cache; + private final <%= string_type %>[] cache; ConstantPool(Loader loader, int bufferOffset, int length) { this.loader = loader; this.bufferOffset = bufferOffset; - <%- if id_type == "String" -%> - cache = new <%= id_type %>[length]; - <%- else -%> - cache = new byte[length][]; - <%- end -%> + cache = new <%= string_type %>[length]; } - <%= id_type %> get(ByteBuffer buffer, int oneBasedIndex) { + <%= string_type %> get(ByteBuffer buffer, int oneBasedIndex) { int index = oneBasedIndex - 1; - <%= id_type %> constant = cache[index]; + <%= string_type %> constant = cache[index]; if (constant == null) { int offset = bufferOffset + index * 8; @@ -51,11 +59,7 @@ public class Loader { byte[] bytes = new byte[length]; buffer.get(start, bytes); - <%- if id_type == "byte[]" -%> - constant = bytes; - <%- else %> constant = loader.bytesToName(bytes); - <%- end %> cache[index] = constant; } @@ -66,6 +70,9 @@ public class Loader { private final ByteBuffer buffer; protected String encodingName; + <%- if string_type == "String" -%> + private Charset encodingCharset; + <%- end -%> private ConstantPool constantPool; private Nodes.Source source = null; @@ -93,6 +100,9 @@ public class Loader { byte[] encodingNameBytes = new byte[encodingLength]; buffer.get(encodingNameBytes); this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII); + <%- if string_type == "String" -%> + this.encodingCharset = getEncodingCharset(this.encodingName); + <%- end -%> source.setStartLine(loadVarSInt()); source.setLineOffsets(loadLineOffsets()); @@ -203,11 +213,11 @@ public class Loader { } } - private <%= id_type %> loadConstant() { + private <%= string_type %> loadConstant() { return constantPool.get(buffer, loadVarUInt()); } - private <%= id_type %> loadOptionalConstant() { + private <%= string_type %> loadOptionalConstant() { if (buffer.get(buffer.position()) != 0) { return loadConstant(); } else { @@ -216,16 +226,12 @@ public class Loader { } } - private <%= id_type %>[] loadConstants() { + private <%= string_type %>[] loadConstants() { int length = loadVarUInt(); if (length == 0) { - return Nodes.EMPTY_IDENTIFIER_ARRAY; + return Nodes.EMPTY_STRING_ARRAY; } - <%- if id_type == "String" -%> - <%= id_type %>[] constants = new <%= id_type %>[length]; - <%- else -%> - <%= id_type %>[] constants = new byte[length][]; - <%- end -%> + <%= string_type %>[] constants = new <%= string_type %>[length]; for (int i = 0; i < length; i++) { constants[i] = constantPool.get(buffer, loadVarUInt()); } @@ -389,7 +395,7 @@ public class Loader { int bufferPosition = buffer.position(); int serializedLength = buffer.getInt(); // Load everything except the body and locals, because the name, receiver, parameters are still needed for lazily defining the method - Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_IDENTIFIER_ARRAY); + Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_STRING_ARRAY); buffer.position(bufferPosition + serializedLength); // skip past the serialized DefNode return lazyDefNode; } diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index f43df2623e..de597eea67 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -1,4 +1,4 @@ -<%- id_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> +<%- string_type = Prism::Template::JAVA_STRING_TYPE -%> package org.ruby_lang.prism; import java.lang.Override; @@ -16,7 +16,7 @@ import java.util.Arrays; // @formatter:off public abstract class Nodes { - public static final <%= id_type %>[] EMPTY_IDENTIFIER_ARRAY = {}; + public static final <%= string_type %>[] EMPTY_STRING_ARRAY = {}; @Target(ElementType.FIELD) @Retention(RetentionPolicy.SOURCE) @@ -383,7 +383,7 @@ public abstract class Nodes { builder.append('\n'); <%- when Prism::Template::ConstantListField -%> builder.append('\n'); - for (<%= id_type %> constant : this.<%= field.name %>) { + for (<%= string_type %> constant : this.<%= field.name %>) { builder.append(nextNextIndent).append('"').append(constant).append('"').append('\n'); } <%- when Prism::Template::Flags -%> diff --git a/templates/template.rb b/templates/template.rb index 5d1afc9506..8f7734dd43 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -11,8 +11,8 @@ module Template # :nodoc: all REMOVE_ON_ERROR_TYPES = SERIALIZE_ONLY_SEMANTICS_FIELDS CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false) - JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "default" - JAVA_IDENTIFIER_TYPE = JAVA_BACKEND == "truffleruby" ? "String" : "byte[]" + JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby" + JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String" INCLUDE_NODE_ID = !SERIALIZE_ONLY_SEMANTICS_FIELDS || JAVA_BACKEND == "jruby" COMMON_FLAGS_COUNT = 2 @@ -272,7 +272,7 @@ def call_seq_type end def java_type - JAVA_IDENTIFIER_TYPE + JAVA_STRING_TYPE end end @@ -292,7 +292,7 @@ def call_seq_type end def java_type - JAVA_IDENTIFIER_TYPE + JAVA_STRING_TYPE end end @@ -312,7 +312,7 @@ def call_seq_type end def java_type - "#{JAVA_IDENTIFIER_TYPE}[]" + "#{JAVA_STRING_TYPE}[]" end end From 02a93356a3073555446144d749178b4a201a7b49 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 20 Mar 2026 16:34:36 -0400 Subject: [PATCH 269/289] Prism.find Take a method, unbound method, proc, or thread backtrace location. This is our equivalent to RubyVM::AbstractSyntaxTree.of, and could be leveraged in something like error highlight. Note that this uses CRuby-specific APIs on CRuby, and falls back to using location-based APIs when those aren't available. --- lib/prism.rb | 16 +- lib/prism/node_find.rb | 193 ++++++++++++++++++++++++ prism.gemspec | 4 + rakelib/typecheck.rake | 1 + rbi/generated/prism.rbi | 7 + rbi/generated/prism/node_find.rbi | 64 ++++++++ rbi/rubyvm/node_find.rbi | 14 ++ sig/_shims/rubyvm.rbs | 6 + sig/generated/prism.rbs | 8 + sig/generated/prism/node_find.rbs | 74 +++++++++ test/prism/newline_test.rb | 2 + test/prism/ruby/find_fixtures.rb | 70 +++++++++ test/prism/ruby/find_test.rb | 242 ++++++++++++++++++++++++++++++ 13 files changed, 700 insertions(+), 1 deletion(-) create mode 100644 lib/prism/node_find.rb create mode 100644 rbi/generated/prism/node_find.rbi create mode 100644 rbi/rubyvm/node_find.rbi create mode 100644 sig/_shims/rubyvm.rbs create mode 100644 sig/generated/prism/node_find.rbs create mode 100644 test/prism/ruby/find_fixtures.rb create mode 100644 test/prism/ruby/find_test.rb diff --git a/lib/prism.rb b/lib/prism.rb index 6b34ab12bf..8f0342724a 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -23,6 +23,7 @@ module Prism autoload :InspectVisitor, "prism/inspect_visitor" autoload :LexCompat, "prism/lex_compat" autoload :MutationCompiler, "prism/mutation_compiler" + autoload :NodeFind, "prism/node_find" autoload :Pattern, "prism/pattern" autoload :Reflection, "prism/reflection" autoload :Relocation, "prism/relocation" @@ -34,7 +35,10 @@ module Prism # Some of these constants are not meant to be exposed, so marking them as # private here. - private_constant :LexCompat + if RUBY_ENGINE != "jruby" + private_constant :LexCompat + private_constant :NodeFind + end # Raised when requested to parse as the currently running Ruby version but Prism has no support for it. class CurrentVersionError < ArgumentError @@ -81,6 +85,16 @@ def self.load(source, serialized, freeze = false) Serialize.load_parse(source, serialized, freeze) end + # Given a Method, UnboundMethod, Proc, or Thread::Backtrace::Location, + # returns the Prism node representing it. On CRuby, this uses node_id for + # an exact match. On other implementations, it falls back to best-effort + # matching by source location line number. + #-- + #: (Method | UnboundMethod | Proc | Thread::Backtrace::Location callable, ?rubyvm: bool) -> Node? + def self.find(callable, rubyvm: !!defined?(RubyVM)) + NodeFind.find(callable, rubyvm) + end + # @rbs! # VERSION: String # BACKEND: :CEXT | :FFI diff --git a/lib/prism/node_find.rb b/lib/prism/node_find.rb new file mode 100644 index 0000000000..46dd598c05 --- /dev/null +++ b/lib/prism/node_find.rb @@ -0,0 +1,193 @@ +# frozen_string_literal: true +# :markup: markdown +#-- +# rbs_inline: enabled + +module Prism + # Finds the Prism AST node corresponding to a given Method, UnboundMethod, + # Proc, or Thread::Backtrace::Location. On CRuby, uses node_id from the + # instruction sequence for an exact match. On other implementations, falls + # back to best-effort matching by source location line number. + # + # This module is autoloaded so that programs that don't use Prism.find don't + # pay for its definition. + module NodeFind # :nodoc: + # Find the node for the given callable or backtrace location. + #-- + #: (Method | UnboundMethod | Proc | Thread::Backtrace::Location callable, bool rubyvm) -> Node? + #++ + def self.find(callable, rubyvm) + case callable + when Proc + if rubyvm + RubyVMCallableFind.new.find(callable) + elsif callable.lambda? + LineLambdaFind.new.find(callable) + else + LineProcFind.new.find(callable) + end + when Method, UnboundMethod + if rubyvm + RubyVMCallableFind.new.find(callable) + else + LineMethodFind.new.find(callable) + end + when Thread::Backtrace::Location + if rubyvm + RubyVMBacktraceLocationFind.new.find(callable) + else + LineBacktraceLocationFind.new.find(callable) + end + else + raise ArgumentError, "Expected a Method, UnboundMethod, Proc, or Thread::Backtrace::Location, got #{callable.class}" + end + end + + # Base class that handles parsing a file. + class Find + private + + # Parse the given file path, returning a ParseResult or nil. + #-- + #: (String? file) -> ParseResult? + + def parse_file(file) + return unless file && File.readable?(file) + result = Prism.parse_file(file) + result if result.success? + end + end + + # Finds the AST node for a Method, UnboundMethod, or Proc using the node_id + # from the instruction sequence. + class RubyVMCallableFind < Find + # Find the node for the given callable using the ISeq node_id. + #-- + #: (Method | UnboundMethod | Proc callable) -> Node? + + def find(callable) + return unless (source_location = callable.source_location) + return unless (result = parse_file(source_location[0])) + return unless (iseq = RubyVM::InstructionSequence.of(callable)) + + header = iseq.to_a[4] + return unless header[:parser] == :prism + + result.value.find { |node| node.node_id == header[:node_id] } + end + end + + # Finds the AST node for a Thread::Backtrace::Location using the node_id + # from the backtrace location. + class RubyVMBacktraceLocationFind < Find + # Find the node for the given backtrace location using node_id. + #-- + #: (Thread::Backtrace::Location location) -> Node? + + def find(location) + file = location.absolute_path || location.path + return unless (result = parse_file(file)) + return unless RubyVM::AbstractSyntaxTree.respond_to?(:node_id_for_backtrace_location) + + node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(location) + + result.value.find { |node| node.node_id == node_id } + end + end + + # Finds the AST node for a Method or UnboundMethod using best-effort line + # matching. Used on non-CRuby implementations. + class LineMethodFind < Find + # Find the node for the given method by matching on name and line. + #-- + #: (Method | UnboundMethod callable) -> Node? + + def find(callable) + return unless (source_location = callable.source_location) + return unless (result = parse_file(source_location[0])) + + name = callable.name + start_line = source_location[1] + + result.value.find do |node| + case node + when DefNode + node.name == name && node.location.start_line == start_line + when CallNode + node.block.is_a?(BlockNode) && node.location.start_line == start_line + else + false + end + end + end + end + + # Finds the AST node for a lambda using best-effort line matching. Used + # on non-CRuby implementations. + class LineLambdaFind < Find + # Find the node for the given lambda by matching on line. + #-- + #: (Proc callable) -> Node? + + def find(callable) + return unless (source_location = callable.source_location) + return unless (result = parse_file(source_location[0])) + + start_line = source_location[1] + + result.value.find do |node| + case node + when LambdaNode + node.location.start_line == start_line + when CallNode + node.block.is_a?(BlockNode) && node.location.start_line == start_line + else + false + end + end + end + end + + # Finds the AST node for a non-lambda Proc using best-effort line + # matching. Used on non-CRuby implementations. + class LineProcFind < Find + # Find the node for the given proc by matching on line. + #-- + #: (Proc callable) -> Node? + + def find(callable) + return unless (source_location = callable.source_location) + return unless (result = parse_file(source_location[0])) + + start_line = source_location[1] + + result.value.find do |node| + case node + when ForNode + node.location.start_line == start_line + when CallNode + node.block.is_a?(BlockNode) && node.location.start_line == start_line + else + false + end + end + end + end + + # Finds the AST node for a Thread::Backtrace::Location using best-effort + # line matching. Used on non-CRuby implementations. + class LineBacktraceLocationFind < Find + # Find the node for the given backtrace location by matching on line. + #-- + #: (Thread::Backtrace::Location location) -> Node? + + def find(location) + file = location.absolute_path || location.path + return unless (result = parse_file(file)) + + start_line = location.lineno + result.value.find { |node| node.location.start_line == start_line } + end + end + end +end diff --git a/prism.gemspec b/prism.gemspec index d489a37af4..aac056b3f8 100644 --- a/prism.gemspec +++ b/prism.gemspec @@ -117,6 +117,7 @@ Gem::Specification.new do |spec| "lib/prism/lex_compat.rb", "lib/prism/mutation_compiler.rb", "lib/prism/node_ext.rb", + "lib/prism/node_find.rb", "lib/prism/node.rb", "lib/prism/parse_result.rb", "lib/prism/parse_result/comments.rb", @@ -158,6 +159,7 @@ Gem::Specification.new do |spec| "rbi/generated/prism/mutation_compiler.rbi", "rbi/generated/prism/node.rbi", "rbi/generated/prism/node_ext.rbi", + "rbi/generated/prism/node_find.rbi", "rbi/generated/prism/parse_result.rbi", "rbi/generated/prism/pattern.rbi", "rbi/generated/prism/reflection.rbi", @@ -172,6 +174,7 @@ Gem::Specification.new do |spec| "rbi/prism/translation/parser.rbi", "rbi/prism/translation/parser_versions.rbi", "rbi/prism/translation/ripper.rbi", + "rbi/rubyvm/node_find.rbi", "sig/generated/prism.rbs", "sig/generated/prism/compiler.rbs", "sig/generated/prism/desugar_compiler.rbs", @@ -183,6 +186,7 @@ Gem::Specification.new do |spec| "sig/generated/prism/mutation_compiler.rbs", "sig/generated/prism/node.rbs", "sig/generated/prism/node_ext.rbs", + "sig/generated/prism/node_find.rbs", "sig/generated/prism/parse_result.rbs", "sig/generated/prism/pattern.rbs", "sig/generated/prism/reflection.rbs", diff --git a/rakelib/typecheck.rake b/rakelib/typecheck.rake index 69bd4a0078..56a216cd9f 100644 --- a/rakelib/typecheck.rake +++ b/rakelib/typecheck.rake @@ -358,6 +358,7 @@ namespace :typecheck do - ./lib/prism/lex_compat.rb - ./lib/prism/node.rb - ./lib/prism/node_ext.rb + - ./lib/prism/node_find.rb - ./lib/prism/parse_result.rb - ./lib/prism/pattern.rb - ./lib/prism/visitor.rb diff --git a/rbi/generated/prism.rbi b/rbi/generated/prism.rbi index 037c50382c..8c1b4e99bb 100644 --- a/rbi/generated/prism.rbi +++ b/rbi/generated/prism.rbi @@ -23,6 +23,13 @@ module Prism sig { params(source: String, serialized: String, freeze: T::Boolean).returns(ParseResult) } def self.load(source, serialized, freeze = T.unsafe(nil)); end + # Given a Method, UnboundMethod, Proc, or Thread::Backtrace::Location, + # returns the Prism node representing it. On CRuby, this uses node_id for + # an exact match. On other implementations, it falls back to best-effort + # matching by source location line number. + sig { params(callable: ::T.any(Method, UnboundMethod, Proc, Thread::Backtrace::Location), rubyvm: T::Boolean).returns(::T.nilable(Node)) } + def self.find(callable, rubyvm: T.unsafe(nil)); end + VERSION = T.let(nil, String) BACKEND = T.let(nil, Symbol) diff --git a/rbi/generated/prism/node_find.rbi b/rbi/generated/prism/node_find.rbi new file mode 100644 index 0000000000..9374a496c1 --- /dev/null +++ b/rbi/generated/prism/node_find.rbi @@ -0,0 +1,64 @@ +# typed: true + +module Prism + # Finds the Prism AST node corresponding to a given Method, UnboundMethod, + # Proc, or Thread::Backtrace::Location. On CRuby, uses node_id from the + # instruction sequence for an exact match. On other implementations, falls + # back to best-effort matching by source location line number. + # + # This module is autoloaded so that programs that don't use Prism.find don't + # pay for its definition. + module NodeFind + # Find the node for the given callable or backtrace location. + sig { params(callable: ::T.any(Method, UnboundMethod, Proc, Thread::Backtrace::Location), rubyvm: T::Boolean).returns(::T.nilable(Node)) } + def self.find(callable, rubyvm); end + + # Base class that handles parsing a file. + class Find + sig { params(file: ::T.nilable(String)).returns(::T.nilable(ParseResult)) } + private def parse_file(file); end + end + + # Finds the AST node for a Method, UnboundMethod, or Proc using the node_id + # from the instruction sequence. + class RubyVMCallableFind < Find + sig { params(callable: ::T.any(Method, UnboundMethod, Proc)).returns(::T.nilable(Node)) } + def find(callable); end + end + + # Finds the AST node for a Thread::Backtrace::Location using the node_id + # from the backtrace location. + class RubyVMBacktraceLocationFind < Find + sig { params(location: Thread::Backtrace::Location).returns(::T.nilable(Node)) } + def find(location); end + end + + # Finds the AST node for a Method or UnboundMethod using best-effort line + # matching. Used on non-CRuby implementations. + class LineMethodFind < Find + sig { params(callable: ::T.any(Method, UnboundMethod)).returns(::T.nilable(Node)) } + def find(callable); end + end + + # Finds the AST node for a lambda using best-effort line matching. Used + # on non-CRuby implementations. + class LineLambdaFind < Find + sig { params(callable: Proc).returns(::T.nilable(Node)) } + def find(callable); end + end + + # Finds the AST node for a non-lambda Proc using best-effort line + # matching. Used on non-CRuby implementations. + class LineProcFind < Find + sig { params(callable: Proc).returns(::T.nilable(Node)) } + def find(callable); end + end + + # Finds the AST node for a Thread::Backtrace::Location using best-effort + # line matching. Used on non-CRuby implementations. + class LineBacktraceLocationFind < Find + sig { params(location: Thread::Backtrace::Location).returns(::T.nilable(Node)) } + def find(location); end + end + end +end diff --git a/rbi/rubyvm/node_find.rbi b/rbi/rubyvm/node_find.rbi new file mode 100644 index 0000000000..92bae0af52 --- /dev/null +++ b/rbi/rubyvm/node_find.rbi @@ -0,0 +1,14 @@ +# typed: true + +class RubyVM::InstructionSequence + sig { params(callable: T.any(Method, UnboundMethod, Proc)).returns(T.nilable(RubyVM::InstructionSequence)) } + def self.of(callable); end + + sig { returns(T::Array[T.untyped]) } + def to_a; end +end + +module RubyVM::AbstractSyntaxTree + sig { params(location: Thread::Backtrace::Location).returns(Integer) } + def self.node_id_for_backtrace_location(location); end +end diff --git a/sig/_shims/rubyvm.rbs b/sig/_shims/rubyvm.rbs new file mode 100644 index 0000000000..bf4e5ab18f --- /dev/null +++ b/sig/_shims/rubyvm.rbs @@ -0,0 +1,6 @@ +class RubyVM + class InstructionSequence + def self.of: (Method | UnboundMethod | Proc) -> RubyVM::InstructionSequence? + def to_a: () -> Array[untyped] + end +end diff --git a/sig/generated/prism.rbs b/sig/generated/prism.rbs index 4777914d3e..93fbba28eb 100644 --- a/sig/generated/prism.rbs +++ b/sig/generated/prism.rbs @@ -32,6 +32,14 @@ module Prism # : (String source, String serialized, ?bool freeze) -> ParseResult def self.load: (String source, String serialized, ?bool freeze) -> ParseResult + # Given a Method, UnboundMethod, Proc, or Thread::Backtrace::Location, + # returns the Prism node representing it. On CRuby, this uses node_id for + # an exact match. On other implementations, it falls back to best-effort + # matching by source location line number. + # -- + # : (Method | UnboundMethod | Proc | Thread::Backtrace::Location callable, ?rubyvm: bool) -> Node? + def self.find: (Method | UnboundMethod | Proc | Thread::Backtrace::Location callable, ?rubyvm: bool) -> Node? + VERSION: String BACKEND: :CEXT | :FFI diff --git a/sig/generated/prism/node_find.rbs b/sig/generated/prism/node_find.rbs new file mode 100644 index 0000000000..3f8e4459d7 --- /dev/null +++ b/sig/generated/prism/node_find.rbs @@ -0,0 +1,74 @@ +# Generated from lib/prism/node_find.rb with RBS::Inline + +module Prism + # Finds the Prism AST node corresponding to a given Method, UnboundMethod, + # Proc, or Thread::Backtrace::Location. On CRuby, uses node_id from the + # instruction sequence for an exact match. On other implementations, falls + # back to best-effort matching by source location line number. + # + # This module is autoloaded so that programs that don't use Prism.find don't + # pay for its definition. + module NodeFind + # Find the node for the given callable or backtrace location. + # -- + # : (Method | UnboundMethod | Proc | Thread::Backtrace::Location callable, bool rubyvm) -> Node? + def self.find: (Method | UnboundMethod | Proc | Thread::Backtrace::Location callable, bool rubyvm) -> Node? + + # Base class that handles parsing a file. + class Find + private + + # -- + # : (String? file) -> ParseResult? + def parse_file: (String? file) -> ParseResult? + end + + # Finds the AST node for a Method, UnboundMethod, or Proc using the node_id + # from the instruction sequence. + class RubyVMCallableFind < Find + # -- + # : (Method | UnboundMethod | Proc callable) -> Node? + def find: (Method | UnboundMethod | Proc callable) -> Node? + end + + # Finds the AST node for a Thread::Backtrace::Location using the node_id + # from the backtrace location. + class RubyVMBacktraceLocationFind < Find + # -- + # : (Thread::Backtrace::Location location) -> Node? + def find: (Thread::Backtrace::Location location) -> Node? + end + + # Finds the AST node for a Method or UnboundMethod using best-effort line + # matching. Used on non-CRuby implementations. + class LineMethodFind < Find + # -- + # : (Method | UnboundMethod callable) -> Node? + def find: (Method | UnboundMethod callable) -> Node? + end + + # Finds the AST node for a lambda using best-effort line matching. Used + # on non-CRuby implementations. + class LineLambdaFind < Find + # -- + # : (Proc callable) -> Node? + def find: (Proc callable) -> Node? + end + + # Finds the AST node for a non-lambda Proc using best-effort line + # matching. Used on non-CRuby implementations. + class LineProcFind < Find + # -- + # : (Proc callable) -> Node? + def find: (Proc callable) -> Node? + end + + # Finds the AST node for a Thread::Backtrace::Location using best-effort + # line matching. Used on non-CRuby implementations. + class LineBacktraceLocationFind < Find + # -- + # : (Thread::Backtrace::Location location) -> Node? + def find: (Thread::Backtrace::Location location) -> Node? + end + end +end diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb index fefe9def91..c8914b57dc 100644 --- a/test/prism/newline_test.rb +++ b/test/prism/newline_test.rb @@ -17,6 +17,8 @@ class NewlineTest < TestCase result/breadth_first_search_test.rb result/static_literals_test.rb result/warnings_test.rb + ruby/find_fixtures.rb + ruby/find_test.rb ruby/parser_test.rb ruby/ruby_parser_test.rb ] diff --git a/test/prism/ruby/find_fixtures.rb b/test/prism/ruby/find_fixtures.rb new file mode 100644 index 0000000000..df82cc7004 --- /dev/null +++ b/test/prism/ruby/find_fixtures.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +# Test fixtures for Prism.find. These must be in a separate file because +# source_location returns the file path and Prism.find re-parses the file. + +module Prism + module FindFixtures + module Methods + def simple_method + 42 + end + + def method_with_params(a, b, c) + a + b + c + end + + def method_with_block(&block) + block.call + end + + def self.singleton_method_fixture + :singleton + end + + def été + :utf8 + end + + def inline_method; :inline; end + end + + module Procs + SIMPLE_PROC = proc { 42 } + SIMPLE_LAMBDA = ->(x) { x * 2 } + MULTI_LINE_LAMBDA = lambda do |x| + x + 1 + end + DO_BLOCK_PROC = proc do |x| + x - 1 + end + end + + module DefineMethod + define_method(:dynamic) { |x| x + 1 } + end + + module ForLoop + items = [1, 2, 3] + for_proc = nil + o = Object.new + def o.each(&block) = block.call(block) + for for_proc in o; end + FOR_PROC = for_proc + end + + module MultipleOnLine + def self.first; end; def self.second; end + end + + module Errors + def self.divide(a, b) + a / b + end + + def self.call_undefined + undefined_method_call + end + end + end +end diff --git a/test/prism/ruby/find_test.rb b/test/prism/ruby/find_test.rb new file mode 100644 index 0000000000..5b59113d30 --- /dev/null +++ b/test/prism/ruby/find_test.rb @@ -0,0 +1,242 @@ +# frozen_string_literal: true + +return if RUBY_ENGINE == "ruby" && RUBY_VERSION < "3.4" +return if defined?(RubyVM::InstructionSequence) && RubyVM::InstructionSequence.compile("").to_a[4][:parser] != :prism + +require_relative "../test_helper" +require_relative "find_fixtures" + +module Prism + class FindTest < TestCase + Fixtures = FindFixtures + FIXTURES_PATH = File.expand_path("find_fixtures.rb", __dir__) + + # === Method / UnboundMethod tests === + + def test_simple_method + assert_def_node Prism.find(Fixtures::Methods.instance_method(:simple_method)), :simple_method + end + + def test_method_with_params + node = Prism.find(Fixtures::Methods.instance_method(:method_with_params)) + assert_def_node node, :method_with_params + assert_equal 3, node.parameters.requireds.length + end + + def test_method_with_block_param + assert_def_node Prism.find(Fixtures::Methods.instance_method(:method_with_block)), :method_with_block + end + + def test_singleton_method + assert_def_node Prism.find(Fixtures::Methods.method(:singleton_method_fixture)), :singleton_method_fixture + end + + def test_utf8_method_name + assert_def_node Prism.find(Fixtures::Methods.instance_method(:été)), :été + end + + def test_inline_method + assert_def_node Prism.find(Fixtures::Methods.instance_method(:inline_method)), :inline_method + end + + def test_bound_method + obj = Object.new + obj.extend(Fixtures::Methods) + assert_def_node Prism.find(obj.method(:simple_method)), :simple_method + end + + # === Proc / Lambda tests === + + def test_simple_proc + assert_not_nil Prism.find(Fixtures::Procs::SIMPLE_PROC) + end + + def test_simple_lambda + assert_not_nil Prism.find(Fixtures::Procs::SIMPLE_LAMBDA) + end + + def test_multi_line_lambda + assert_not_nil Prism.find(Fixtures::Procs::MULTI_LINE_LAMBDA) + end + + def test_do_block_proc + assert_not_nil Prism.find(Fixtures::Procs::DO_BLOCK_PROC) + end + + # === define_method tests === + + def test_define_method + assert_not_nil Prism.find(Fixtures::DefineMethod.instance_method(:dynamic)) + end + + def test_define_method_bound + obj = Object.new + obj.extend(Fixtures::DefineMethod) + assert_not_nil Prism.find(obj.method(:dynamic)) + end + + # === for loop test === + + def test_for_loop_proc + node = Prism.find(Fixtures::ForLoop::FOR_PROC) + assert_instance_of ForNode, node + end + + # === Thread::Backtrace::Location tests === + + def test_backtrace_location_zero_division + location = zero_division_location + assert_not_nil location, "could not find backtrace location in fixtures file" + assert_not_nil Prism.find(location) + end + + def test_backtrace_location_name_error + location = begin + Fixtures::Errors.call_undefined + rescue NameError => e + fixture_backtrace_location(e) + end + + assert_not_nil location, "could not find backtrace location in fixtures file" + assert_not_nil Prism.find(location) + end + + def test_backtrace_location_from_caller + # caller_locations returns locations for the current call stack + location = caller_locations(0, 1).first + node = Prism.find(location) + assert_not_nil node + end + + def test_backtrace_location_eval_returns_nil + location = begin + eval("raise 'eval error'") + rescue RuntimeError => e + e.backtrace_locations.find { |loc| loc.path == "(eval)" || loc.label&.include?("eval") } + end + + # eval locations have no file on disk + assert_nil Prism.find(location) if location + end + + # === Edge cases === + + def test_nil_source_location + # Built-in methods have nil source_location + assert_nil Prism.find(method(:puts)) + end + + def test_argument_error_on_wrong_type + assert_raise(ArgumentError) { Prism.find("not a callable") } + assert_raise(ArgumentError) { Prism.find(42) } + assert_raise(ArgumentError) { Prism.find(nil) } + end + + def test_eval_returns_nil + # eval'd code has no file on disk + m = eval("proc { 1 }") + assert_nil Prism.find(m) + end + + def test_multiple_methods_on_same_line + assert_def_node Prism.find(Fixtures::MultipleOnLine.method(:first)), :first + assert_def_node Prism.find(Fixtures::MultipleOnLine.method(:second)), :second + end + + # === Fallback (line-based) tests via rubyvm: false === + + def test_fallback_simple_method + assert_def_node Prism.find(Fixtures::Methods.instance_method(:simple_method), rubyvm: false), :simple_method + end + + def test_fallback_singleton_method + assert_def_node Prism.find(Fixtures::Methods.method(:singleton_method_fixture), rubyvm: false), :singleton_method_fixture + end + + def test_fallback_lambda + node = Prism.find(Fixtures::Procs::SIMPLE_LAMBDA, rubyvm: false) + assert_instance_of LambdaNode, node + end + + def test_fallback_proc + node = Prism.find(Fixtures::Procs::SIMPLE_PROC, rubyvm: false) + assert_instance_of CallNode, node + assert node.block.is_a?(BlockNode) + end + + def test_fallback_define_method + node = Prism.find(Fixtures::DefineMethod.instance_method(:dynamic), rubyvm: false) + assert_instance_of CallNode, node + assert node.block.is_a?(BlockNode) + end + + def test_fallback_for_loop + node = Prism.find(Fixtures::ForLoop::FOR_PROC, rubyvm: false) + assert_instance_of ForNode, node + end + + def test_fallback_backtrace_location + location = zero_division_location + assert_not_nil location + node = Prism.find(location, rubyvm: false) + assert_not_nil node + assert_equal location.lineno, node.location.start_line + end + + # === Node identity with node_id (CRuby only) === + + if defined?(RubyVM::InstructionSequence) + def test_node_id_matches_iseq + m = Fixtures::Methods.instance_method(:simple_method) + node = Prism.find(m) + assert_equal node_id_of(m), node.node_id + end + + def test_node_id_for_lambda + node = Prism.find(Fixtures::Procs::SIMPLE_LAMBDA) + assert_equal node_id_of(Fixtures::Procs::SIMPLE_LAMBDA), node.node_id + end + + def test_node_id_for_proc + node = Prism.find(Fixtures::Procs::SIMPLE_PROC) + assert_equal node_id_of(Fixtures::Procs::SIMPLE_PROC), node.node_id + end + + def test_node_id_for_define_method + m = Fixtures::DefineMethod.instance_method(:dynamic) + node = Prism.find(m) + assert_equal node_id_of(m), node.node_id + end + + def test_node_id_for_backtrace_location + location = zero_division_location + assert_not_nil location + expected_node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(location) + + node = Prism.find(location) + assert_equal expected_node_id, node.node_id + end + end + + private + + def assert_def_node(node, expected_name) + assert_instance_of DefNode, node + assert_equal expected_name, node.name + end + + def fixture_backtrace_location(exception) + exception.backtrace_locations.find { |loc| loc.path == FIXTURES_PATH } + end + + def zero_division_location + Fixtures::Errors.divide(1, 0) + rescue ZeroDivisionError => e + fixture_backtrace_location(e) + end + + def node_id_of(callable) + RubyVM::InstructionSequence.of(callable).to_a[4][:node_id] + end + end +end From 3f6014dc5315d3f120de38ca495ac30675556b55 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 16 Mar 2026 20:13:39 +0100 Subject: [PATCH 270/289] Ensure Source#offsets is set correctly in all cases * See https://github.com/ruby/prism/issues/3861 --- lib/prism/parse_result.rb | 3 ++- rbi/generated/prism/dsl.rbi | 6 +++++- rbi/generated/prism/parse_result.rbi | 3 ++- sig/generated/prism/dsl.rbs | 9 ++++++++- sig/generated/prism/parse_result.rbs | 3 ++- templates/lib/prism/dsl.rb.erb | 20 +++++++++++++++++--- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 4d1fa2c296..4f7bcf07d6 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -26,7 +26,8 @@ class Source # source is a subset of a larger source or if this is an eval. offsets is an # array of byte offsets for the start of each line in the source code, which # can be calculated by iterating through the source code and recording the - # byte offset whenever a newline character is encountered. + # byte offset whenever a newline character is encountered. The first + # element is always 0 to mark the first line. #-- #: (String source, Integer start_line, Array[Integer] offsets) -> Source def self.for(source, start_line, offsets) diff --git a/rbi/generated/prism/dsl.rbi b/rbi/generated/prism/dsl.rbi index ac4e68bfa7..148d4724de 100644 --- a/rbi/generated/prism/dsl.rbi +++ b/rbi/generated/prism/dsl.rbi @@ -4,7 +4,7 @@ module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: # - # source = Prism::Source.for("[1]", 1, []) + # source = Prism::Source.for("[1]", 1, [0]) # # Prism::ArrayNode.new( # source, @@ -743,5 +743,9 @@ module Prism # required node field. sig { params(source: Source, location: Location).returns(Node) } private def default_node(source, location); end + + # Build the newline byte offset array for the given source string. + sig { params(source: String).returns(T::Array[Integer]) } + private def build_offsets(source); end end end diff --git a/rbi/generated/prism/parse_result.rbi b/rbi/generated/prism/parse_result.rbi index f20ba90ef5..4d065b5be1 100644 --- a/rbi/generated/prism/parse_result.rbi +++ b/rbi/generated/prism/parse_result.rbi @@ -16,7 +16,8 @@ module Prism # source is a subset of a larger source or if this is an eval. offsets is an # array of byte offsets for the start of each line in the source code, which # can be calculated by iterating through the source code and recording the - # byte offset whenever a newline character is encountered. + # byte offset whenever a newline character is encountered. The first + # element is always 0 to mark the first line. sig { params(source: String, start_line: Integer, offsets: T::Array[Integer]).returns(Source) } def self.for(source, start_line, offsets); end diff --git a/sig/generated/prism/dsl.rbs b/sig/generated/prism/dsl.rbs index 4b09efccd3..fc0c198705 100644 --- a/sig/generated/prism/dsl.rbs +++ b/sig/generated/prism/dsl.rbs @@ -4,7 +4,7 @@ module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: # - # source = Prism::Source.for("[1]", 1, []) + # source = Prism::Source.for("[1]", 1, [0]) # # Prism::ArrayNode.new( # source, @@ -917,5 +917,12 @@ module Prism # -- # : (Source source, Location location) -> node def default_node: (Source source, Location location) -> node + + private + + # Build the newline byte offset array for the given source string. + # -- + # : (String source) -> Array[Integer] + def build_offsets: (String source) -> Array[Integer] end end diff --git a/sig/generated/prism/parse_result.rbs b/sig/generated/prism/parse_result.rbs index 1f3b8a8d54..f005f17375 100644 --- a/sig/generated/prism/parse_result.rbs +++ b/sig/generated/prism/parse_result.rbs @@ -22,7 +22,8 @@ module Prism # source is a subset of a larger source or if this is an eval. offsets is an # array of byte offsets for the start of each line in the source code, which # can be calculated by iterating through the source code and recording the - # byte offset whenever a newline character is encountered. + # byte offset whenever a newline character is encountered. The first + # element is always 0 to mark the first line. # -- # : (String source, Integer start_line, Array[Integer] offsets) -> Source def self.for: (String source, Integer start_line, Array[Integer] offsets) -> Source diff --git a/templates/lib/prism/dsl.rb.erb b/templates/lib/prism/dsl.rb.erb index 6dcbbec100..95c4dac71a 100644 --- a/templates/lib/prism/dsl.rb.erb +++ b/templates/lib/prism/dsl.rb.erb @@ -5,7 +5,7 @@ module Prism # The DSL module provides a set of methods that can be used to create prism # nodes in a more concise manner. For example, instead of writing: # - # source = Prism::Source.for("[1]", 1, []) + # source = Prism::Source.for("[1]", 1, [0]) # # Prism::ArrayNode.new( # source, @@ -62,7 +62,7 @@ module Prism #-- #: (String string) -> Source def source(string) - Source.for(string, 1, []) + Source.for(string, 1, build_offsets(string)) end # Create a new Location object. @@ -136,7 +136,7 @@ module Prism #-- #: () -> Source def default_source - Source.for("", 1, []) + Source.for("", 1, [0]) end # The default location object that gets attached to nodes if no location is @@ -154,5 +154,19 @@ module Prism def default_node(source, location) MissingNode.new(source, -1, location, 0) end + + private + + # Build the newline byte offset array for the given source string. + #-- + #: (String source) -> Array[Integer] + def build_offsets(source) + offsets = [0] + start = 0 + while (index = source.byteindex("\n", start)) + offsets << (start = index + 1) + end + offsets + end end end From 0ba6b31d3c6443fd9e64bf600e57d0d53dd688b1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 20 Mar 2026 19:09:45 -0400 Subject: [PATCH 271/289] Remove accidentally checked-in json source file --- .gitignore | 1 + src/json.c | 5723 ---------------------------------------------------- 2 files changed, 1 insertion(+), 5723 deletions(-) delete mode 100644 src/json.c diff --git a/.gitignore b/.gitignore index 471c5006a7..516e30de3e 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ out.svg /lib/prism/visitor.rb /sorbet/ /src/diagnostic.c +/src/json.c /src/node.c /src/prettyprint.c /src/serialize.c diff --git a/src/json.c b/src/json.c deleted file mode 100644 index 72975db724..0000000000 --- a/src/json.c +++ /dev/null @@ -1,5723 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* This file is generated by the templates/template.rb script and should not */ -/* be modified manually. See */ -/* templates/src/json.c.erb */ -/* if you are looking to modify the */ -/* template */ -/*----------------------------------------------------------------------------*/ - -#include "prism/json.h" - -// Ensure this translation unit is never empty, even when JSON is excluded. -typedef int pm_json_unused_t; - -#ifndef PRISM_EXCLUDE_JSON - -#include "prism/internal/buffer.h" -#include "prism/internal/constant_pool.h" -#include "prism/internal/integer.h" -#include "prism/internal/parser.h" - -#include - -static void -pm_dump_json_constant(pm_buffer_t *buffer, const pm_parser_t *parser, pm_constant_id_t constant_id) { - const pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id); - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, constant->start, constant->length, PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); -} - -static void -pm_dump_json_location(pm_buffer_t *buffer, const pm_location_t *location) { - pm_buffer_append_format(buffer, "{\"start\":%" PRIu32 ",\"length\":%" PRIu32 "}", location->start, location->length); -} - -/** - * Dump JSON to the given buffer. - */ -void -pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) { - switch (PM_NODE_TYPE(node)) { - case PM_ALIAS_GLOBAL_VARIABLE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"AliasGlobalVariableNode\",\"location\":", 45); - - const pm_alias_global_variable_node_t *cast = (const pm_alias_global_variable_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the new_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"new_name\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->new_name); - - // Dump the old_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"old_name\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->old_name); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ALIAS_METHOD_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"AliasMethodNode\",\"location\":", 37); - - const pm_alias_method_node_t *cast = (const pm_alias_method_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the new_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"new_name\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->new_name); - - // Dump the old_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"old_name\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->old_name); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ALTERNATION_PATTERN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"AlternationPatternNode\",\"location\":", 44); - - const pm_alternation_pattern_node_t *cast = (const pm_alternation_pattern_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the left field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"left\":", 7); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); - - // Dump the right field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"right\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_AND_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"AndNode\",\"location\":", 29); - - const pm_and_node_t *cast = (const pm_and_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the left field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"left\":", 7); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); - - // Dump the right field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"right\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ARGUMENTS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ArgumentsNode\",\"location\":", 35); - - const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ArgumentsNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"CONTAINS_FORWARDING\"", 21); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"CONTAINS_KEYWORDS\"", 19); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"CONTAINS_KEYWORD_SPLAT\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"CONTAINS_SPLAT\"", 16); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"CONTAINS_MULTIPLE_SPLATS\"", 26); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - const pm_node_list_t *arguments = &cast->arguments; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < arguments->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, arguments->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ARRAY_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ArrayNode\",\"location\":", 31); - - const pm_array_node_t *cast = (const pm_array_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ArrayNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"CONTAINS_SPLAT\"", 16); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the elements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"elements\":", 11); - const pm_node_list_t *elements = &cast->elements; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < elements->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, elements->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ARRAY_PATTERN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ArrayPatternNode\",\"location\":", 38); - - const pm_array_pattern_node_t *cast = (const pm_array_pattern_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the constant field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"constant\":", 11); - if (cast->constant != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the requireds field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"requireds\":", 12); - const pm_node_list_t *requireds = &cast->requireds; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < requireds->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, requireds->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the rest field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rest\":", 7); - if (cast->rest != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the posts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"posts\":", 8); - const pm_node_list_t *posts = &cast->posts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < posts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, posts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ASSOC_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"AssocNode\",\"location\":", 31); - - const pm_assoc_node_t *cast = (const pm_assoc_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the key field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"key\":", 6); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->key); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - if (cast->operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ASSOC_SPLAT_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"AssocSplatNode\",\"location\":", 36); - - const pm_assoc_splat_node_t *cast = (const pm_assoc_splat_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - if (cast->value != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BACK_REFERENCE_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BackReferenceReadNode\",\"location\":", 43); - - const pm_back_reference_read_node_t *cast = (const pm_back_reference_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BEGIN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BeginNode\",\"location\":", 31); - - const pm_begin_node_t *cast = (const pm_begin_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the begin_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"begin_keyword_loc\":", 20); - if (cast->begin_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->begin_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rescue_clause field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rescue_clause\":", 16); - if (cast->rescue_clause != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->rescue_clause); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the else_clause field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"else_clause\":", 14); - if (cast->else_clause != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the ensure_clause field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ensure_clause\":", 16); - if (cast->ensure_clause != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->ensure_clause); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - if (cast->end_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->end_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BLOCK_ARGUMENT_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BlockArgumentNode\",\"location\":", 39); - - const pm_block_argument_node_t *cast = (const pm_block_argument_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the expression field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"expression\":", 13); - if (cast->expression != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BLOCK_LOCAL_VARIABLE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BlockLocalVariableNode\",\"location\":", 44); - - const pm_block_local_variable_node_t *cast = (const pm_block_local_variable_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BLOCK_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BlockNode\",\"location\":", 31); - - const pm_block_node_t *cast = (const pm_block_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_constant_id_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, locals->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the parameters field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parameters\":", 13); - if (cast->parameters != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - if (cast->body != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BLOCK_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BlockParameterNode\",\"location\":", 40); - - const pm_block_parameter_node_t *cast = (const pm_block_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - if (cast->name != PM_CONSTANT_ID_UNSET) { - pm_dump_json_constant(buffer, parser, cast->name); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - if (cast->name_loc.length != 0) { - pm_dump_json_location(buffer, &cast->name_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BLOCK_PARAMETERS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BlockParametersNode\",\"location\":", 41); - - const pm_block_parameters_node_t *cast = (const pm_block_parameters_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the parameters field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parameters\":", 13); - if (cast->parameters != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_node_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, locals->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_BREAK_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"BreakNode\",\"location\":", 31); - - const pm_break_node_t *cast = (const pm_break_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CALL_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CallAndWriteNode\",\"location\":", 38); - - const pm_call_and_write_node_t *cast = (const pm_call_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - if (cast->call_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->call_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the message_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"message_loc\":", 14); - if (cast->message_loc.length != 0) { - pm_dump_json_location(buffer, &cast->message_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the read_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"read_name\":", 12); - pm_dump_json_constant(buffer, parser, cast->read_name); - - // Dump the write_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"write_name\":", 13); - pm_dump_json_constant(buffer, parser, cast->write_name); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CALL_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CallNode\",\"location\":", 30); - - const pm_call_node_t *cast = (const pm_call_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - if (cast->call_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->call_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the message_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"message_loc\":", 14); - if (cast->message_loc.length != 0) { - pm_dump_json_location(buffer, &cast->message_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the equal_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"equal_loc\":", 12); - if (cast->equal_loc.length != 0) { - pm_dump_json_location(buffer, &cast->equal_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CALL_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CallOperatorWriteNode\",\"location\":", 43); - - const pm_call_operator_write_node_t *cast = (const pm_call_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - if (cast->call_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->call_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the message_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"message_loc\":", 14); - if (cast->message_loc.length != 0) { - pm_dump_json_location(buffer, &cast->message_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the read_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"read_name\":", 12); - pm_dump_json_constant(buffer, parser, cast->read_name); - - // Dump the write_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"write_name\":", 13); - pm_dump_json_constant(buffer, parser, cast->write_name); - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CALL_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CallOrWriteNode\",\"location\":", 37); - - const pm_call_or_write_node_t *cast = (const pm_call_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - if (cast->call_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->call_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the message_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"message_loc\":", 14); - if (cast->message_loc.length != 0) { - pm_dump_json_location(buffer, &cast->message_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the read_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"read_name\":", 12); - pm_dump_json_constant(buffer, parser, cast->read_name); - - // Dump the write_name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"write_name\":", 13); - pm_dump_json_constant(buffer, parser, cast->write_name); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CALL_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CallTargetNode\",\"location\":", 36); - - const pm_call_target_node_t *cast = (const pm_call_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - pm_dump_json_location(buffer, &cast->call_operator_loc); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the message_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"message_loc\":", 14); - pm_dump_json_location(buffer, &cast->message_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CAPTURE_PATTERN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CapturePatternNode\",\"location\":", 40); - - const pm_capture_pattern_node_t *cast = (const pm_capture_pattern_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the target field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"target\":", 9); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CASE_MATCH_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CaseMatchNode\",\"location\":", 35); - - const pm_case_match_node_t *cast = (const pm_case_match_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the predicate field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"predicate\":", 12); - if (cast->predicate != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the conditions field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"conditions\":", 13); - const pm_node_list_t *conditions = &cast->conditions; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < conditions->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, conditions->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the else_clause field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"else_clause\":", 14); - if (cast->else_clause != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the case_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"case_keyword_loc\":", 19); - pm_dump_json_location(buffer, &cast->case_keyword_loc); - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->end_keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CASE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"CaseNode\",\"location\":", 30); - - const pm_case_node_t *cast = (const pm_case_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the predicate field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"predicate\":", 12); - if (cast->predicate != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the conditions field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"conditions\":", 13); - const pm_node_list_t *conditions = &cast->conditions; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < conditions->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, conditions->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the else_clause field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"else_clause\":", 14); - if (cast->else_clause != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the case_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"case_keyword_loc\":", 19); - pm_dump_json_location(buffer, &cast->case_keyword_loc); - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->end_keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CLASS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ClassNode\",\"location\":", 31); - - const pm_class_node_t *cast = (const pm_class_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_constant_id_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, locals->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the class_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"class_keyword_loc\":", 20); - pm_dump_json_location(buffer, &cast->class_keyword_loc); - - // Dump the constant_path field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"constant_path\":", 16); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant_path); - - // Dump the inheritance_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"inheritance_operator_loc\":", 27); - if (cast->inheritance_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->inheritance_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the superclass field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"superclass\":", 13); - if (cast->superclass != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->superclass); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - if (cast->body != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->end_keyword_loc); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CLASS_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableAndWriteNode\",\"location\":", 47); - - const pm_class_variable_and_write_node_t *cast = (const pm_class_variable_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableOperatorWriteNode\",\"location\":", 52); - - const pm_class_variable_operator_write_node_t *cast = (const pm_class_variable_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CLASS_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableOrWriteNode\",\"location\":", 46); - - const pm_class_variable_or_write_node_t *cast = (const pm_class_variable_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CLASS_VARIABLE_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableReadNode\",\"location\":", 43); - - const pm_class_variable_read_node_t *cast = (const pm_class_variable_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CLASS_VARIABLE_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableTargetNode\",\"location\":", 45); - - const pm_class_variable_target_node_t *cast = (const pm_class_variable_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CLASS_VARIABLE_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableWriteNode\",\"location\":", 44); - - const pm_class_variable_write_node_t *cast = (const pm_class_variable_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantAndWriteNode\",\"location\":", 42); - - const pm_constant_and_write_node_t *cast = (const pm_constant_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantOperatorWriteNode\",\"location\":", 47); - - const pm_constant_operator_write_node_t *cast = (const pm_constant_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantOrWriteNode\",\"location\":", 41); - - const pm_constant_or_write_node_t *cast = (const pm_constant_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_PATH_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathAndWriteNode\",\"location\":", 46); - - const pm_constant_path_and_write_node_t *cast = (const pm_constant_path_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the target field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"target\":", 9); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_PATH_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathNode\",\"location\":", 38); - - const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the parent field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parent\":", 9); - if (cast->parent != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->parent); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - if (cast->name != PM_CONSTANT_ID_UNSET) { - pm_dump_json_constant(buffer, parser, cast->name); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the delimiter_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"delimiter_loc\":", 16); - pm_dump_json_location(buffer, &cast->delimiter_loc); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathOperatorWriteNode\",\"location\":", 51); - - const pm_constant_path_operator_write_node_t *cast = (const pm_constant_path_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the target field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"target\":", 9); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_PATH_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathOrWriteNode\",\"location\":", 45); - - const pm_constant_path_or_write_node_t *cast = (const pm_constant_path_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the target field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"target\":", 9); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_PATH_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathTargetNode\",\"location\":", 44); - - const pm_constant_path_target_node_t *cast = (const pm_constant_path_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the parent field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parent\":", 9); - if (cast->parent != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->parent); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - if (cast->name != PM_CONSTANT_ID_UNSET) { - pm_dump_json_constant(buffer, parser, cast->name); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the delimiter_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"delimiter_loc\":", 16); - pm_dump_json_location(buffer, &cast->delimiter_loc); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_PATH_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathWriteNode\",\"location\":", 43); - - const pm_constant_path_write_node_t *cast = (const pm_constant_path_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the target field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"target\":", 9); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->target); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantReadNode\",\"location\":", 38); - - const pm_constant_read_node_t *cast = (const pm_constant_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantTargetNode\",\"location\":", 40); - - const pm_constant_target_node_t *cast = (const pm_constant_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_CONSTANT_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ConstantWriteNode\",\"location\":", 39); - - const pm_constant_write_node_t *cast = (const pm_constant_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_DEF_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"DefNode\",\"location\":", 29); - - const pm_def_node_t *cast = (const pm_def_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the parameters field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parameters\":", 13); - if (cast->parameters != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - if (cast->body != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_constant_id_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, locals->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the def_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"def_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->def_keyword_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - if (cast->operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the lparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); - if (cast->lparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->lparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); - if (cast->rparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->rparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the equal_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"equal_loc\":", 12); - if (cast->equal_loc.length != 0) { - pm_dump_json_location(buffer, &cast->equal_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - if (cast->end_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->end_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_DEFINED_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"DefinedNode\",\"location\":", 33); - - const pm_defined_node_t *cast = (const pm_defined_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the lparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); - if (cast->lparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->lparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the rparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); - if (cast->rparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->rparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ELSE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ElseNode\",\"location\":", 30); - - const pm_else_node_t *cast = (const pm_else_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the else_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"else_keyword_loc\":", 19); - pm_dump_json_location(buffer, &cast->else_keyword_loc); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - if (cast->end_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->end_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_EMBEDDED_STATEMENTS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"EmbeddedStatementsNode\",\"location\":", 44); - - const pm_embedded_statements_node_t *cast = (const pm_embedded_statements_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_EMBEDDED_VARIABLE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"EmbeddedVariableNode\",\"location\":", 42); - - const pm_embedded_variable_node_t *cast = (const pm_embedded_variable_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the variable field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"variable\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->variable); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_ENSURE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"EnsureNode\",\"location\":", 32); - - const pm_ensure_node_t *cast = (const pm_ensure_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ensure_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ensure_keyword_loc\":", 21); - pm_dump_json_location(buffer, &cast->ensure_keyword_loc); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->end_keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FALSE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"FalseNode\",\"location\":", 31); - - const pm_false_node_t *cast = (const pm_false_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FIND_PATTERN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"FindPatternNode\",\"location\":", 37); - - const pm_find_pattern_node_t *cast = (const pm_find_pattern_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the constant field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"constant\":", 11); - if (cast->constant != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the left field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"left\":", 7); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); - - // Dump the requireds field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"requireds\":", 12); - const pm_node_list_t *requireds = &cast->requireds; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < requireds->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, requireds->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the right field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"right\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FLIP_FLOP_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"FlipFlopNode\",\"location\":", 34); - - const pm_flip_flop_node_t *cast = (const pm_flip_flop_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the RangeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_RANGE_FLAGS_EXCLUDE_END)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXCLUDE_END\"", 13); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the left field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"left\":", 7); - if (cast->left != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the right field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"right\":", 8); - if (cast->right != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FLOAT_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"FloatNode\",\"location\":", 31); - - const pm_float_node_t *cast = (const pm_float_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_buffer_append_format(buffer, "%f", cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FOR_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ForNode\",\"location\":", 29); - - const pm_for_node_t *cast = (const pm_for_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the index field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"index\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->index); - - // Dump the collection field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"collection\":", 13); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->collection); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the for_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"for_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->for_keyword_loc); - - // Dump the in_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"in_keyword_loc\":", 17); - pm_dump_json_location(buffer, &cast->in_keyword_loc); - - // Dump the do_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17); - if (cast->do_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->do_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->end_keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FORWARDING_ARGUMENTS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ForwardingArgumentsNode\",\"location\":", 45); - - const pm_forwarding_arguments_node_t *cast = (const pm_forwarding_arguments_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FORWARDING_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ForwardingParameterNode\",\"location\":", 45); - - const pm_forwarding_parameter_node_t *cast = (const pm_forwarding_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_FORWARDING_SUPER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ForwardingSuperNode\",\"location\":", 41); - - const pm_forwarding_super_node_t *cast = (const pm_forwarding_super_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableAndWriteNode\",\"location\":", 48); - - const pm_global_variable_and_write_node_t *cast = (const pm_global_variable_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableOperatorWriteNode\",\"location\":", 53); - - const pm_global_variable_operator_write_node_t *cast = (const pm_global_variable_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableOrWriteNode\",\"location\":", 47); - - const pm_global_variable_or_write_node_t *cast = (const pm_global_variable_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_GLOBAL_VARIABLE_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableReadNode\",\"location\":", 44); - - const pm_global_variable_read_node_t *cast = (const pm_global_variable_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_GLOBAL_VARIABLE_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableTargetNode\",\"location\":", 46); - - const pm_global_variable_target_node_t *cast = (const pm_global_variable_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_GLOBAL_VARIABLE_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableWriteNode\",\"location\":", 45); - - const pm_global_variable_write_node_t *cast = (const pm_global_variable_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_HASH_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"HashNode\",\"location\":", 30); - - const pm_hash_node_t *cast = (const pm_hash_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the elements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"elements\":", 11); - const pm_node_list_t *elements = &cast->elements; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < elements->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, elements->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_HASH_PATTERN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"HashPatternNode\",\"location\":", 37); - - const pm_hash_pattern_node_t *cast = (const pm_hash_pattern_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the constant field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"constant\":", 11); - if (cast->constant != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the elements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"elements\":", 11); - const pm_node_list_t *elements = &cast->elements; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < elements->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, elements->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the rest field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rest\":", 7); - if (cast->rest != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_IF_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"IfNode\",\"location\":", 28); - - const pm_if_node_t *cast = (const pm_if_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the if_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"if_keyword_loc\":", 17); - if (cast->if_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->if_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the predicate field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"predicate\":", 12); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); - - // Dump the then_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); - if (cast->then_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->then_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the subsequent field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"subsequent\":", 13); - if (cast->subsequent != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->subsequent); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - if (cast->end_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->end_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_IMAGINARY_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ImaginaryNode\",\"location\":", 35); - - const pm_imaginary_node_t *cast = (const pm_imaginary_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the numeric field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"numeric\":", 10); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->numeric); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_IMPLICIT_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ImplicitNode\",\"location\":", 34); - - const pm_implicit_node_t *cast = (const pm_implicit_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_IMPLICIT_REST_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ImplicitRestNode\",\"location\":", 38); - - const pm_implicit_rest_node_t *cast = (const pm_implicit_rest_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_IN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InNode\",\"location\":", 28); - - const pm_in_node_t *cast = (const pm_in_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the pattern field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"pattern\":", 10); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the in_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"in_loc\":", 9); - pm_dump_json_location(buffer, &cast->in_loc); - - // Dump the then_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"then_loc\":", 11); - if (cast->then_loc.length != 0) { - pm_dump_json_location(buffer, &cast->then_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INDEX_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"IndexAndWriteNode\",\"location\":", 39); - - const pm_index_and_write_node_t *cast = (const pm_index_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - if (cast->call_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->call_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INDEX_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"IndexOperatorWriteNode\",\"location\":", 44); - - const pm_index_operator_write_node_t *cast = (const pm_index_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - if (cast->call_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->call_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INDEX_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"IndexOrWriteNode\",\"location\":", 38); - - const pm_index_or_write_node_t *cast = (const pm_index_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - if (cast->receiver != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the call_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20); - if (cast->call_operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->call_operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INDEX_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"IndexTargetNode\",\"location\":", 37); - - const pm_index_target_node_t *cast = (const pm_index_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the CallNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the receiver field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"receiver\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableAndWriteNode\",\"location\":", 50); - - const pm_instance_variable_and_write_node_t *cast = (const pm_instance_variable_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableOperatorWriteNode\",\"location\":", 55); - - const pm_instance_variable_operator_write_node_t *cast = (const pm_instance_variable_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableOrWriteNode\",\"location\":", 49); - - const pm_instance_variable_or_write_node_t *cast = (const pm_instance_variable_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INSTANCE_VARIABLE_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableReadNode\",\"location\":", 46); - - const pm_instance_variable_read_node_t *cast = (const pm_instance_variable_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INSTANCE_VARIABLE_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableTargetNode\",\"location\":", 48); - - const pm_instance_variable_target_node_t *cast = (const pm_instance_variable_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INSTANCE_VARIABLE_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableWriteNode\",\"location\":", 47); - - const pm_instance_variable_write_node_t *cast = (const pm_instance_variable_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INTEGER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"IntegerNode\",\"location\":", 33); - - const pm_integer_node_t *cast = (const pm_integer_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the IntegerBaseFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_BINARY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"BINARY\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_DECIMAL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"DECIMAL\"", 9); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_OCTAL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"OCTAL\"", 7); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_HEXADECIMAL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"HEXADECIMAL\"", 13); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_integer_string(buffer, &cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedMatchLastLineNode\",\"location\":", 51); - - const pm_interpolated_match_last_line_node_t *cast = (const pm_interpolated_match_last_line_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the RegularExpressionFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ONCE\"", 6); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"UTF_8\"", 7); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the parts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parts\":", 8); - const pm_node_list_t *parts = &cast->parts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < parts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, parts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedRegularExpressionNode\",\"location\":", 55); - - const pm_interpolated_regular_expression_node_t *cast = (const pm_interpolated_regular_expression_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the RegularExpressionFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ONCE\"", 6); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"UTF_8\"", 7); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the parts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parts\":", 8); - const pm_node_list_t *parts = &cast->parts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < parts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, parts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INTERPOLATED_STRING_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedStringNode\",\"location\":", 44); - - const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the InterpolatedStringNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FROZEN\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MUTABLE\"", 9); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the parts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parts\":", 8); - const pm_node_list_t *parts = &cast->parts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < parts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, parts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INTERPOLATED_SYMBOL_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedSymbolNode\",\"location\":", 44); - - const pm_interpolated_symbol_node_t *cast = (const pm_interpolated_symbol_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the parts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parts\":", 8); - const pm_node_list_t *parts = &cast->parts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < parts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, parts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_INTERPOLATED_X_STRING_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedXStringNode\",\"location\":", 45); - - const pm_interpolated_x_string_node_t *cast = (const pm_interpolated_x_string_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the parts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parts\":", 8); - const pm_node_list_t *parts = &cast->parts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < parts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, parts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_IT_LOCAL_VARIABLE_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ItLocalVariableReadNode\",\"location\":", 45); - - const pm_it_local_variable_read_node_t *cast = (const pm_it_local_variable_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_IT_PARAMETERS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ItParametersNode\",\"location\":", 38); - - const pm_it_parameters_node_t *cast = (const pm_it_parameters_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_KEYWORD_HASH_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"KeywordHashNode\",\"location\":", 37); - - const pm_keyword_hash_node_t *cast = (const pm_keyword_hash_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the KeywordHashNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"SYMBOL_KEYS\"", 13); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the elements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"elements\":", 11); - const pm_node_list_t *elements = &cast->elements; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < elements->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, elements->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_KEYWORD_REST_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"KeywordRestParameterNode\",\"location\":", 46); - - const pm_keyword_rest_parameter_node_t *cast = (const pm_keyword_rest_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - if (cast->name != PM_CONSTANT_ID_UNSET) { - pm_dump_json_constant(buffer, parser, cast->name); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - if (cast->name_loc.length != 0) { - pm_dump_json_location(buffer, &cast->name_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_LAMBDA_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"LambdaNode\",\"location\":", 32); - - const pm_lambda_node_t *cast = (const pm_lambda_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_constant_id_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, locals->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the parameters field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"parameters\":", 13); - if (cast->parameters != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - if (cast->body != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_LOCAL_VARIABLE_AND_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableAndWriteNode\",\"location\":", 47); - - const pm_local_variable_and_write_node_t *cast = (const pm_local_variable_and_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the depth field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"depth\":", 8); - pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableOperatorWriteNode\",\"location\":", 52); - - const pm_local_variable_operator_write_node_t *cast = (const pm_local_variable_operator_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the binary_operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22); - pm_dump_json_location(buffer, &cast->binary_operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the binary_operator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"binary_operator\":", 18); - pm_dump_json_constant(buffer, parser, cast->binary_operator); - - // Dump the depth field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"depth\":", 8); - pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_LOCAL_VARIABLE_OR_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableOrWriteNode\",\"location\":", 46); - - const pm_local_variable_or_write_node_t *cast = (const pm_local_variable_or_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the depth field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"depth\":", 8); - pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_LOCAL_VARIABLE_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableReadNode\",\"location\":", 43); - - const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the depth field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"depth\":", 8); - pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_LOCAL_VARIABLE_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableTargetNode\",\"location\":", 45); - - const pm_local_variable_target_node_t *cast = (const pm_local_variable_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the depth field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"depth\":", 8); - pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_LOCAL_VARIABLE_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableWriteNode\",\"location\":", 44); - - const pm_local_variable_write_node_t *cast = (const pm_local_variable_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the depth field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"depth\":", 8); - pm_buffer_append_format(buffer, "%" PRIu32, cast->depth); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MATCH_LAST_LINE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"MatchLastLineNode\",\"location\":", 39); - - const pm_match_last_line_node_t *cast = (const pm_match_last_line_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the RegularExpressionFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ONCE\"", 6); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"UTF_8\"", 7); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the content_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"content_loc\":", 14); - pm_dump_json_location(buffer, &cast->content_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the unescaped field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"unescaped\":", 12); - const pm_string_t *unescaped = &cast->unescaped; - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MATCH_PREDICATE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"MatchPredicateNode\",\"location\":", 40); - - const pm_match_predicate_node_t *cast = (const pm_match_predicate_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the pattern field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"pattern\":", 10); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MATCH_REQUIRED_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"MatchRequiredNode\",\"location\":", 39); - - const pm_match_required_node_t *cast = (const pm_match_required_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - // Dump the pattern field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"pattern\":", 10); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MATCH_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"MatchWriteNode\",\"location\":", 36); - - const pm_match_write_node_t *cast = (const pm_match_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the call field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"call\":", 7); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->call); - - // Dump the targets field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"targets\":", 10); - const pm_node_list_t *targets = &cast->targets; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < targets->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, targets->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MISSING_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"MissingNode\",\"location\":", 33); - - const pm_missing_node_t *cast = (const pm_missing_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MODULE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ModuleNode\",\"location\":", 32); - - const pm_module_node_t *cast = (const pm_module_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_constant_id_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, locals->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the module_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"module_keyword_loc\":", 21); - pm_dump_json_location(buffer, &cast->module_keyword_loc); - - // Dump the constant_path field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"constant_path\":", 16); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant_path); - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - if (cast->body != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->end_keyword_loc); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MULTI_TARGET_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"MultiTargetNode\",\"location\":", 37); - - const pm_multi_target_node_t *cast = (const pm_multi_target_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the lefts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lefts\":", 8); - const pm_node_list_t *lefts = &cast->lefts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < lefts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, lefts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the rest field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rest\":", 7); - if (cast->rest != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rights field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rights\":", 9); - const pm_node_list_t *rights = &cast->rights; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < rights->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, rights->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the lparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); - if (cast->lparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->lparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); - if (cast->rparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->rparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_MULTI_WRITE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"MultiWriteNode\",\"location\":", 36); - - const pm_multi_write_node_t *cast = (const pm_multi_write_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the lefts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lefts\":", 8); - const pm_node_list_t *lefts = &cast->lefts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < lefts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, lefts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the rest field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rest\":", 7); - if (cast->rest != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rights field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rights\":", 9); - const pm_node_list_t *rights = &cast->rights; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < rights->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, rights->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the lparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); - if (cast->lparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->lparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); - if (cast->rparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->rparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_NEXT_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"NextNode\",\"location\":", 30); - - const pm_next_node_t *cast = (const pm_next_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_NIL_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"NilNode\",\"location\":", 29); - - const pm_nil_node_t *cast = (const pm_nil_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_NO_BLOCK_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"NoBlockParameterNode\",\"location\":", 42); - - const pm_no_block_parameter_node_t *cast = (const pm_no_block_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_NO_KEYWORDS_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"NoKeywordsParameterNode\",\"location\":", 45); - - const pm_no_keywords_parameter_node_t *cast = (const pm_no_keywords_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_NUMBERED_PARAMETERS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"NumberedParametersNode\",\"location\":", 44); - - const pm_numbered_parameters_node_t *cast = (const pm_numbered_parameters_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the maximum field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"maximum\":", 10); - pm_buffer_append_format(buffer, "%" PRIu8, cast->maximum); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_NUMBERED_REFERENCE_READ_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"NumberedReferenceReadNode\",\"location\":", 47); - - const pm_numbered_reference_read_node_t *cast = (const pm_numbered_reference_read_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the number field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"number\":", 9); - pm_buffer_append_format(buffer, "%" PRIu32, cast->number); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"OptionalKeywordParameterNode\",\"location\":", 50); - - const pm_optional_keyword_parameter_node_t *cast = (const pm_optional_keyword_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_OPTIONAL_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"OptionalParameterNode\",\"location\":", 43); - - const pm_optional_parameter_node_t *cast = (const pm_optional_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the value field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->value); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_OR_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"OrNode\",\"location\":", 28); - - const pm_or_node_t *cast = (const pm_or_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the left field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"left\":", 7); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); - - // Dump the right field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"right\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_PARAMETERS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ParametersNode\",\"location\":", 36); - - const pm_parameters_node_t *cast = (const pm_parameters_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the requireds field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"requireds\":", 12); - const pm_node_list_t *requireds = &cast->requireds; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < requireds->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, requireds->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the optionals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"optionals\":", 12); - const pm_node_list_t *optionals = &cast->optionals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < optionals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, optionals->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the rest field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rest\":", 7); - if (cast->rest != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the posts field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"posts\":", 8); - const pm_node_list_t *posts = &cast->posts; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < posts->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, posts->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the keywords field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keywords\":", 11); - const pm_node_list_t *keywords = &cast->keywords; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < keywords->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, keywords->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the keyword_rest field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_rest\":", 15); - if (cast->keyword_rest != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->keyword_rest); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_PARENTHESES_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ParenthesesNode\",\"location\":", 37); - - const pm_parentheses_node_t *cast = (const pm_parentheses_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParenthesesNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MULTIPLE_STATEMENTS\"", 21); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - if (cast->body != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_PINNED_EXPRESSION_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"PinnedExpressionNode\",\"location\":", 42); - - const pm_pinned_expression_node_t *cast = (const pm_pinned_expression_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the expression field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"expression\":", 13); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the lparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); - pm_dump_json_location(buffer, &cast->lparen_loc); - - // Dump the rparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); - pm_dump_json_location(buffer, &cast->rparen_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_PINNED_VARIABLE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"PinnedVariableNode\",\"location\":", 40); - - const pm_pinned_variable_node_t *cast = (const pm_pinned_variable_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the variable field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"variable\":", 11); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->variable); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_POST_EXECUTION_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"PostExecutionNode\",\"location\":", 39); - - const pm_post_execution_node_t *cast = (const pm_post_execution_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_PRE_EXECUTION_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"PreExecutionNode\",\"location\":", 38); - - const pm_pre_execution_node_t *cast = (const pm_pre_execution_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_PROGRAM_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ProgramNode\",\"location\":", 33); - - const pm_program_node_t *cast = (const pm_program_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_constant_id_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, locals->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_RANGE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RangeNode\",\"location\":", 31); - - const pm_range_node_t *cast = (const pm_range_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the RangeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_RANGE_FLAGS_EXCLUDE_END)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXCLUDE_END\"", 13); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the left field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"left\":", 7); - if (cast->left != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->left); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the right field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"right\":", 8); - if (cast->right != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->right); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_RATIONAL_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RationalNode\",\"location\":", 34); - - const pm_rational_node_t *cast = (const pm_rational_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the IntegerBaseFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_BINARY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"BINARY\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_DECIMAL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"DECIMAL\"", 9); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_OCTAL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"OCTAL\"", 7); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_HEXADECIMAL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"HEXADECIMAL\"", 13); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the numerator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"numerator\":", 12); - pm_integer_string(buffer, &cast->numerator); - - // Dump the denominator field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"denominator\":", 14); - pm_integer_string(buffer, &cast->denominator); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_REDO_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RedoNode\",\"location\":", 30); - - const pm_redo_node_t *cast = (const pm_redo_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_REGULAR_EXPRESSION_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RegularExpressionNode\",\"location\":", 43); - - const pm_regular_expression_node_t *cast = (const pm_regular_expression_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the RegularExpressionFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXTENDED\"", 10); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ONCE\"", 6); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EUC_JP\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"UTF_8\"", 7); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the content_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"content_loc\":", 14); - pm_dump_json_location(buffer, &cast->content_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the unescaped field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"unescaped\":", 12); - const pm_string_t *unescaped = &cast->unescaped; - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_REQUIRED_KEYWORD_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RequiredKeywordParameterNode\",\"location\":", 50); - - const pm_required_keyword_parameter_node_t *cast = (const pm_required_keyword_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - pm_dump_json_location(buffer, &cast->name_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_REQUIRED_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RequiredParameterNode\",\"location\":", 43); - - const pm_required_parameter_node_t *cast = (const pm_required_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - pm_dump_json_constant(buffer, parser, cast->name); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_RESCUE_MODIFIER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RescueModifierNode\",\"location\":", 40); - - const pm_rescue_modifier_node_t *cast = (const pm_rescue_modifier_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the expression field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"expression\":", 13); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the rescue_expression field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rescue_expression\":", 20); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->rescue_expression); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_RESCUE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RescueNode\",\"location\":", 32); - - const pm_rescue_node_t *cast = (const pm_rescue_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the exceptions field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"exceptions\":", 13); - const pm_node_list_t *exceptions = &cast->exceptions; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < exceptions->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, exceptions->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - if (cast->operator_loc.length != 0) { - pm_dump_json_location(buffer, &cast->operator_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the reference field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"reference\":", 12); - if (cast->reference != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->reference); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the then_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); - if (cast->then_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->then_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the subsequent field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"subsequent\":", 13); - if (cast->subsequent != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->subsequent); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_REST_PARAMETER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RestParameterNode\",\"location\":", 39); - - const pm_rest_parameter_node_t *cast = (const pm_rest_parameter_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ParameterFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the name field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name\":", 7); - if (cast->name != PM_CONSTANT_ID_UNSET) { - pm_dump_json_constant(buffer, parser, cast->name); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the name_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"name_loc\":", 11); - if (cast->name_loc.length != 0) { - pm_dump_json_location(buffer, &cast->name_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_RETRY_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"RetryNode\",\"location\":", 31); - - const pm_retry_node_t *cast = (const pm_retry_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_RETURN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ReturnNode\",\"location\":", 32); - - const pm_return_node_t *cast = (const pm_return_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SELF_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SelfNode\",\"location\":", 30); - - const pm_self_node_t *cast = (const pm_self_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SHAREABLE_CONSTANT_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"ShareableConstantNode\",\"location\":", 43); - - const pm_shareable_constant_node_t *cast = (const pm_shareable_constant_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the ShareableConstantNodeFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"LITERAL\"", 9); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXPERIMENTAL_EVERYTHING\"", 25); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"EXPERIMENTAL_COPY\"", 19); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the write field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"write\":", 8); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->write); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SINGLETON_CLASS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SingletonClassNode\",\"location\":", 40); - - const pm_singleton_class_node_t *cast = (const pm_singleton_class_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the locals field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"locals\":", 9); - const pm_constant_id_list_t *locals = &cast->locals; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < locals->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json_constant(buffer, parser, locals->ids[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the class_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"class_keyword_loc\":", 20); - pm_dump_json_location(buffer, &cast->class_keyword_loc); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the expression field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"expression\":", 13); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - if (cast->body != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->body); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - pm_dump_json_location(buffer, &cast->end_keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SOURCE_ENCODING_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SourceEncodingNode\",\"location\":", 40); - - const pm_source_encoding_node_t *cast = (const pm_source_encoding_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SOURCE_FILE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SourceFileNode\",\"location\":", 36); - - const pm_source_file_node_t *cast = (const pm_source_file_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the StringFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FROZEN)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FROZEN\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_MUTABLE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MUTABLE\"", 9); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the filepath field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"filepath\":", 11); - const pm_string_t *filepath = &cast->filepath; - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, pm_string_source(filepath), pm_string_length(filepath), PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SOURCE_LINE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SourceLineNode\",\"location\":", 36); - - const pm_source_line_node_t *cast = (const pm_source_line_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SPLAT_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SplatNode\",\"location\":", 31); - - const pm_splat_node_t *cast = (const pm_splat_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the operator_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"operator_loc\":", 15); - pm_dump_json_location(buffer, &cast->operator_loc); - - // Dump the expression field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"expression\":", 13); - if (cast->expression != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_STATEMENTS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"StatementsNode\",\"location\":", 36); - - const pm_statements_node_t *cast = (const pm_statements_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the body field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"body\":", 7); - const pm_node_list_t *body = &cast->body; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < body->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, body->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_STRING_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"StringNode\",\"location\":", 32); - - const pm_string_node_t *cast = (const pm_string_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the StringFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FROZEN)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FROZEN\"", 8); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_MUTABLE)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"MUTABLE\"", 9); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the content_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"content_loc\":", 14); - pm_dump_json_location(buffer, &cast->content_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the unescaped field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"unescaped\":", 12); - const pm_string_t *unescaped = &cast->unescaped; - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SUPER_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SuperNode\",\"location\":", 31); - - const pm_super_node_t *cast = (const pm_super_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the lparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); - if (cast->lparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->lparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); - if (cast->rparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->rparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the block field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"block\":", 8); - if (cast->block != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->block); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SYMBOL_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"SymbolNode\",\"location\":", 32); - - const pm_symbol_node_t *cast = (const pm_symbol_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the SymbolFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - if (cast->opening_loc.length != 0) { - pm_dump_json_location(buffer, &cast->opening_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the value_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"value_loc\":", 12); - if (cast->value_loc.length != 0) { - pm_dump_json_location(buffer, &cast->value_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the unescaped field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"unescaped\":", 12); - const pm_string_t *unescaped = &cast->unescaped; - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_TRUE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"TrueNode\",\"location\":", 30); - - const pm_true_node_t *cast = (const pm_true_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_UNDEF_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"UndefNode\",\"location\":", 31); - - const pm_undef_node_t *cast = (const pm_undef_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the names field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"names\":", 8); - const pm_node_list_t *names = &cast->names; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < names->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, names->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_UNLESS_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"UnlessNode\",\"location\":", 32); - - const pm_unless_node_t *cast = (const pm_unless_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the predicate field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"predicate\":", 12); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); - - // Dump the then_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); - if (cast->then_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->then_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the else_clause field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"else_clause\":", 14); - if (cast->else_clause != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the end_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18); - if (cast->end_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->end_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_UNTIL_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"UntilNode\",\"location\":", 31); - - const pm_until_node_t *cast = (const pm_until_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the LoopFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_LOOP_FLAGS_BEGIN_MODIFIER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"BEGIN_MODIFIER\"", 16); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the do_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17); - if (cast->do_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->do_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the predicate field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"predicate\":", 12); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_WHEN_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"WhenNode\",\"location\":", 30); - - const pm_when_node_t *cast = (const pm_when_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the conditions field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"conditions\":", 13); - const pm_node_list_t *conditions = &cast->conditions; - pm_buffer_append_byte(buffer, '['); - - for (size_t index = 0; index < conditions->size; index++) { - if (index != 0) pm_buffer_append_byte(buffer, ','); - pm_dump_json(buffer, parser, conditions->nodes[index]); - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the then_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19); - if (cast->then_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->then_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_WHILE_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"WhileNode\",\"location\":", 31); - - const pm_while_node_t *cast = (const pm_while_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the LoopFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_LOOP_FLAGS_BEGIN_MODIFIER)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"BEGIN_MODIFIER\"", 16); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the do_keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17); - if (cast->do_keyword_loc.length != 0) { - pm_dump_json_location(buffer, &cast->do_keyword_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - if (cast->closing_loc.length != 0) { - pm_dump_json_location(buffer, &cast->closing_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the predicate field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"predicate\":", 12); - pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate); - - // Dump the statements field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"statements\":", 13); - if (cast->statements != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_X_STRING_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"XStringNode\",\"location\":", 33); - - const pm_x_string_node_t *cast = (const pm_x_string_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the EncodingFlags field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"flags\":", 8); - size_t flags = 0; - pm_buffer_append_byte(buffer, '['); - if (PM_NODE_FLAG_P(cast, PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22); - flags++; - } - if (PM_NODE_FLAG_P(cast, PM_ENCODING_FLAGS_FORCED_BINARY_ENCODING)) { - if (flags != 0) pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24); - flags++; - } - pm_buffer_append_byte(buffer, ']'); - - // Dump the opening_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"opening_loc\":", 14); - pm_dump_json_location(buffer, &cast->opening_loc); - - // Dump the content_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"content_loc\":", 14); - pm_dump_json_location(buffer, &cast->content_loc); - - // Dump the closing_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"closing_loc\":", 14); - pm_dump_json_location(buffer, &cast->closing_loc); - - // Dump the unescaped field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"unescaped\":", 12); - const pm_string_t *unescaped = &cast->unescaped; - pm_buffer_append_byte(buffer, '"'); - pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON); - pm_buffer_append_byte(buffer, '"'); - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_YIELD_NODE: { - pm_buffer_append_string(buffer, "{\"type\":\"YieldNode\",\"location\":", 31); - - const pm_yield_node_t *cast = (const pm_yield_node_t *) node; - pm_dump_json_location(buffer, &cast->base.location); - - // Dump the keyword_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"keyword_loc\":", 14); - pm_dump_json_location(buffer, &cast->keyword_loc); - - // Dump the lparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"lparen_loc\":", 13); - if (cast->lparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->lparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the arguments field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"arguments\":", 12); - if (cast->arguments != NULL) { - pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - // Dump the rparen_loc field - pm_buffer_append_byte(buffer, ','); - pm_buffer_append_string(buffer, "\"rparen_loc\":", 13); - if (cast->rparen_loc.length != 0) { - pm_dump_json_location(buffer, &cast->rparen_loc); - } else { - pm_buffer_append_string(buffer, "null", 4); - } - - pm_buffer_append_byte(buffer, '}'); - break; - } - case PM_SCOPE_NODE: - break; - } -} - -#endif From 6f597d3ff7f59701f8df365828c3c6d03785759b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 20 Mar 2026 20:38:02 -0400 Subject: [PATCH 272/289] Clean up types on node find --- lib/prism/node_find.rb | 8 -------- rbi/generated/prism/node_find.rbi | 7 +++++++ sig/generated/prism/node_find.rbs | 7 +++++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/prism/node_find.rb b/lib/prism/node_find.rb index 46dd598c05..697ee430e8 100644 --- a/lib/prism/node_find.rb +++ b/lib/prism/node_find.rb @@ -15,7 +15,6 @@ module NodeFind # :nodoc: # Find the node for the given callable or backtrace location. #-- #: (Method | UnboundMethod | Proc | Thread::Backtrace::Location callable, bool rubyvm) -> Node? - #++ def self.find(callable, rubyvm) case callable when Proc @@ -50,7 +49,6 @@ class Find # Parse the given file path, returning a ParseResult or nil. #-- #: (String? file) -> ParseResult? - def parse_file(file) return unless file && File.readable?(file) result = Prism.parse_file(file) @@ -64,7 +62,6 @@ class RubyVMCallableFind < Find # Find the node for the given callable using the ISeq node_id. #-- #: (Method | UnboundMethod | Proc callable) -> Node? - def find(callable) return unless (source_location = callable.source_location) return unless (result = parse_file(source_location[0])) @@ -83,7 +80,6 @@ class RubyVMBacktraceLocationFind < Find # Find the node for the given backtrace location using node_id. #-- #: (Thread::Backtrace::Location location) -> Node? - def find(location) file = location.absolute_path || location.path return unless (result = parse_file(file)) @@ -101,7 +97,6 @@ class LineMethodFind < Find # Find the node for the given method by matching on name and line. #-- #: (Method | UnboundMethod callable) -> Node? - def find(callable) return unless (source_location = callable.source_location) return unless (result = parse_file(source_location[0])) @@ -128,7 +123,6 @@ class LineLambdaFind < Find # Find the node for the given lambda by matching on line. #-- #: (Proc callable) -> Node? - def find(callable) return unless (source_location = callable.source_location) return unless (result = parse_file(source_location[0])) @@ -154,7 +148,6 @@ class LineProcFind < Find # Find the node for the given proc by matching on line. #-- #: (Proc callable) -> Node? - def find(callable) return unless (source_location = callable.source_location) return unless (result = parse_file(source_location[0])) @@ -180,7 +173,6 @@ class LineBacktraceLocationFind < Find # Find the node for the given backtrace location by matching on line. #-- #: (Thread::Backtrace::Location location) -> Node? - def find(location) file = location.absolute_path || location.path return unless (result = parse_file(file)) diff --git a/rbi/generated/prism/node_find.rbi b/rbi/generated/prism/node_find.rbi index 9374a496c1..17afe9cc40 100644 --- a/rbi/generated/prism/node_find.rbi +++ b/rbi/generated/prism/node_find.rbi @@ -15,6 +15,7 @@ module Prism # Base class that handles parsing a file. class Find + # Parse the given file path, returning a ParseResult or nil. sig { params(file: ::T.nilable(String)).returns(::T.nilable(ParseResult)) } private def parse_file(file); end end @@ -22,6 +23,7 @@ module Prism # Finds the AST node for a Method, UnboundMethod, or Proc using the node_id # from the instruction sequence. class RubyVMCallableFind < Find + # Find the node for the given callable using the ISeq node_id. sig { params(callable: ::T.any(Method, UnboundMethod, Proc)).returns(::T.nilable(Node)) } def find(callable); end end @@ -29,6 +31,7 @@ module Prism # Finds the AST node for a Thread::Backtrace::Location using the node_id # from the backtrace location. class RubyVMBacktraceLocationFind < Find + # Find the node for the given backtrace location using node_id. sig { params(location: Thread::Backtrace::Location).returns(::T.nilable(Node)) } def find(location); end end @@ -36,6 +39,7 @@ module Prism # Finds the AST node for a Method or UnboundMethod using best-effort line # matching. Used on non-CRuby implementations. class LineMethodFind < Find + # Find the node for the given method by matching on name and line. sig { params(callable: ::T.any(Method, UnboundMethod)).returns(::T.nilable(Node)) } def find(callable); end end @@ -43,6 +47,7 @@ module Prism # Finds the AST node for a lambda using best-effort line matching. Used # on non-CRuby implementations. class LineLambdaFind < Find + # Find the node for the given lambda by matching on line. sig { params(callable: Proc).returns(::T.nilable(Node)) } def find(callable); end end @@ -50,6 +55,7 @@ module Prism # Finds the AST node for a non-lambda Proc using best-effort line # matching. Used on non-CRuby implementations. class LineProcFind < Find + # Find the node for the given proc by matching on line. sig { params(callable: Proc).returns(::T.nilable(Node)) } def find(callable); end end @@ -57,6 +63,7 @@ module Prism # Finds the AST node for a Thread::Backtrace::Location using best-effort # line matching. Used on non-CRuby implementations. class LineBacktraceLocationFind < Find + # Find the node for the given backtrace location by matching on line. sig { params(location: Thread::Backtrace::Location).returns(::T.nilable(Node)) } def find(location); end end diff --git a/sig/generated/prism/node_find.rbs b/sig/generated/prism/node_find.rbs index 3f8e4459d7..9924ff1452 100644 --- a/sig/generated/prism/node_find.rbs +++ b/sig/generated/prism/node_find.rbs @@ -18,6 +18,7 @@ module Prism class Find private + # Parse the given file path, returning a ParseResult or nil. # -- # : (String? file) -> ParseResult? def parse_file: (String? file) -> ParseResult? @@ -26,6 +27,7 @@ module Prism # Finds the AST node for a Method, UnboundMethod, or Proc using the node_id # from the instruction sequence. class RubyVMCallableFind < Find + # Find the node for the given callable using the ISeq node_id. # -- # : (Method | UnboundMethod | Proc callable) -> Node? def find: (Method | UnboundMethod | Proc callable) -> Node? @@ -34,6 +36,7 @@ module Prism # Finds the AST node for a Thread::Backtrace::Location using the node_id # from the backtrace location. class RubyVMBacktraceLocationFind < Find + # Find the node for the given backtrace location using node_id. # -- # : (Thread::Backtrace::Location location) -> Node? def find: (Thread::Backtrace::Location location) -> Node? @@ -42,6 +45,7 @@ module Prism # Finds the AST node for a Method or UnboundMethod using best-effort line # matching. Used on non-CRuby implementations. class LineMethodFind < Find + # Find the node for the given method by matching on name and line. # -- # : (Method | UnboundMethod callable) -> Node? def find: (Method | UnboundMethod callable) -> Node? @@ -50,6 +54,7 @@ module Prism # Finds the AST node for a lambda using best-effort line matching. Used # on non-CRuby implementations. class LineLambdaFind < Find + # Find the node for the given lambda by matching on line. # -- # : (Proc callable) -> Node? def find: (Proc callable) -> Node? @@ -58,6 +63,7 @@ module Prism # Finds the AST node for a non-lambda Proc using best-effort line # matching. Used on non-CRuby implementations. class LineProcFind < Find + # Find the node for the given proc by matching on line. # -- # : (Proc callable) -> Node? def find: (Proc callable) -> Node? @@ -66,6 +72,7 @@ module Prism # Finds the AST node for a Thread::Backtrace::Location using best-effort # line matching. Used on non-CRuby implementations. class LineBacktraceLocationFind < Find + # Find the node for the given backtrace location by matching on line. # -- # : (Thread::Backtrace::Location location) -> Node? def find: (Thread::Backtrace::Location location) -> Node? From 32028c52c54c40c0d4d2ff7476a18861f79bec9f Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 19 Mar 2026 12:14:34 -0500 Subject: [PATCH 273/289] Swich identifiers to byte[] * JAVA_STRING_TYPE and related change to IDENTIFIER * TruffleRuby still uses java.lang.String Fixes #4009 --- templates/java/org/ruby_lang/prism/Loader.java.erb | 8 ++++---- templates/java/org/ruby_lang/prism/Nodes.java.erb | 6 +++--- templates/template.rb | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 534d8401ca..bf1bf7a625 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,4 +1,4 @@ -<%- string_type = Prism::Template::JAVA_STRING_TYPE -%> +<%- string_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> package org.ruby_lang.prism; import java.lang.Short; @@ -31,7 +31,7 @@ public class Loader { <%- if string_type == "String" -%> return new String(bytes, encodingCharset).intern(); <%- else -%> - return null; // Must be implemented by subclassing Loader + return bytes; // Must be implemented by subclassing Loader <%- end -%> } @@ -229,7 +229,7 @@ public class Loader { private <%= string_type %>[] loadConstants() { int length = loadVarUInt(); if (length == 0) { - return Nodes.EMPTY_STRING_ARRAY; + return Nodes.EMPTY_IDENTIFIER_ARRAY; } <%= string_type %>[] constants = new <%= string_type %>[length]; for (int i = 0; i < length; i++) { @@ -395,7 +395,7 @@ public class Loader { int bufferPosition = buffer.position(); int serializedLength = buffer.getInt(); // Load everything except the body and locals, because the name, receiver, parameters are still needed for lazily defining the method - Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_STRING_ARRAY); + Nodes.DefNode lazyDefNode = new Nodes.DefNode(<%= base_params.join(", ") -%>, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_IDENTIFIER_ARRAY); buffer.position(bufferPosition + serializedLength); // skip past the serialized DefNode return lazyDefNode; } diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index de597eea67..f43df2623e 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -1,4 +1,4 @@ -<%- string_type = Prism::Template::JAVA_STRING_TYPE -%> +<%- id_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> package org.ruby_lang.prism; import java.lang.Override; @@ -16,7 +16,7 @@ import java.util.Arrays; // @formatter:off public abstract class Nodes { - public static final <%= string_type %>[] EMPTY_STRING_ARRAY = {}; + public static final <%= id_type %>[] EMPTY_IDENTIFIER_ARRAY = {}; @Target(ElementType.FIELD) @Retention(RetentionPolicy.SOURCE) @@ -383,7 +383,7 @@ public abstract class Nodes { builder.append('\n'); <%- when Prism::Template::ConstantListField -%> builder.append('\n'); - for (<%= string_type %> constant : this.<%= field.name %>) { + for (<%= id_type %> constant : this.<%= field.name %>) { builder.append(nextNextIndent).append('"').append(constant).append('"').append('\n'); } <%- when Prism::Template::Flags -%> diff --git a/templates/template.rb b/templates/template.rb index 8f7734dd43..be39c2f682 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -12,7 +12,7 @@ module Template # :nodoc: all CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false) JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby" - JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String" + JAVA_IDENTIFIER_TYPE = JAVA_BACKEND == "truffleruby" ? "String" : "byte[]" INCLUDE_NODE_ID = !SERIALIZE_ONLY_SEMANTICS_FIELDS || JAVA_BACKEND == "jruby" COMMON_FLAGS_COUNT = 2 @@ -272,7 +272,7 @@ def call_seq_type end def java_type - JAVA_STRING_TYPE + JAVA_IDENTIFIER_TYPE end end @@ -292,7 +292,7 @@ def call_seq_type end def java_type - JAVA_STRING_TYPE + JAVA_IDENTIFIER_TYPE end end @@ -312,7 +312,7 @@ def call_seq_type end def java_type - "#{JAVA_STRING_TYPE}[]" + "#{JAVA_IDENTIFIER_TYPE}[]" end end From 5f29860bb73afb0ead74d9f7b1be90163b0b2ac1 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 09:59:53 -0500 Subject: [PATCH 274/289] Tweaks for byte[] identifiers * Allocate array of byte[] as byte[length][]. * Default JAVA_BACKEND to "default" with "truffleruby" the custom option. --- .../java/org/ruby_lang/prism/Loader.java.erb | 34 ++++++++++++------- templates/template.rb | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index bf1bf7a625..ae8007bf90 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -1,4 +1,4 @@ -<%- string_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> +<%- id_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%> package org.ruby_lang.prism; import java.lang.Short; @@ -27,8 +27,8 @@ public class Loader { return Charset.forName(encodingName); } - public <%= string_type %> bytesToName(byte[] bytes) { - <%- if string_type == "String" -%> + public <%= id_type %> bytesToName(byte[] bytes) { + <%- if id_type == "String" -%> return new String(bytes, encodingCharset).intern(); <%- else -%> return bytes; // Must be implemented by subclassing Loader @@ -39,17 +39,21 @@ public class Loader { private final Loader loader; private final int bufferOffset; - private final <%= string_type %>[] cache; + private final <%= id_type %>[] cache; ConstantPool(Loader loader, int bufferOffset, int length) { this.loader = loader; this.bufferOffset = bufferOffset; - cache = new <%= string_type %>[length]; + <%- if id_type == "String" -%> + cache = new <%= id_type %>[length]; + <%- else -%> + cache = new byte[length][]; + <%- end -%> } - <%= string_type %> get(ByteBuffer buffer, int oneBasedIndex) { + <%= id_type %> get(ByteBuffer buffer, int oneBasedIndex) { int index = oneBasedIndex - 1; - <%= string_type %> constant = cache[index]; + <%= id_type %> constant = cache[index]; if (constant == null) { int offset = bufferOffset + index * 8; @@ -70,7 +74,7 @@ public class Loader { private final ByteBuffer buffer; protected String encodingName; - <%- if string_type == "String" -%> + <%- if id_type == "String" -%> private Charset encodingCharset; <%- end -%> private ConstantPool constantPool; @@ -100,7 +104,7 @@ public class Loader { byte[] encodingNameBytes = new byte[encodingLength]; buffer.get(encodingNameBytes); this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII); - <%- if string_type == "String" -%> + <%- if id_type == "String" -%> this.encodingCharset = getEncodingCharset(this.encodingName); <%- end -%> @@ -213,11 +217,11 @@ public class Loader { } } - private <%= string_type %> loadConstant() { + private <%= id_type %> loadConstant() { return constantPool.get(buffer, loadVarUInt()); } - private <%= string_type %> loadOptionalConstant() { + private <%= id_type %> loadOptionalConstant() { if (buffer.get(buffer.position()) != 0) { return loadConstant(); } else { @@ -226,12 +230,16 @@ public class Loader { } } - private <%= string_type %>[] loadConstants() { + private <%= id_type %>[] loadConstants() { int length = loadVarUInt(); if (length == 0) { return Nodes.EMPTY_IDENTIFIER_ARRAY; } - <%= string_type %>[] constants = new <%= string_type %>[length]; + <%- if id_type == "String" -%> + <%= id_type %>[] constants = new <%= id_type %>[length]; + <%- else -%> + <%= id_type %>[] constants = new byte[length][]; + <%- end -%> for (int i = 0; i < length; i++) { constants[i] = constantPool.get(buffer, loadVarUInt()); } diff --git a/templates/template.rb b/templates/template.rb index be39c2f682..5d1afc9506 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -11,7 +11,7 @@ module Template # :nodoc: all REMOVE_ON_ERROR_TYPES = SERIALIZE_ONLY_SEMANTICS_FIELDS CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false) - JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby" + JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "default" JAVA_IDENTIFIER_TYPE = JAVA_BACKEND == "truffleruby" ? "String" : "byte[]" INCLUDE_NODE_ID = !SERIALIZE_ONLY_SEMANTICS_FIELDS || JAVA_BACKEND == "jruby" From b529af850a995a3525ef538ed862d8de1bcbeff0 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 10:49:52 -0500 Subject: [PATCH 275/289] Remove no-longer-relevant comment Co-authored-by: Benoit Daloze --- templates/java/org/ruby_lang/prism/Loader.java.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index ae8007bf90..5695e5a651 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -31,7 +31,7 @@ public class Loader { <%- if id_type == "String" -%> return new String(bytes, encodingCharset).intern(); <%- else -%> - return bytes; // Must be implemented by subclassing Loader + return bytes; <%- end -%> } From 4c286040c0a070c43c6737819fcf4026bd877447 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 15:52:22 -0500 Subject: [PATCH 276/289] Eliminate encodingCharset encodingCharset is not needed with byte[] and can be inferred from the encoding name, so remove it from the templated code. bytesToName is modified to raise an AbstractMethodError for the non-default ID type (String, for TruffleRuby) and should be overridden in that case. --- .../java/org/ruby_lang/prism/Loader.java.erb | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Loader.java.erb b/templates/java/org/ruby_lang/prism/Loader.java.erb index 5695e5a651..6d1a77fd10 100644 --- a/templates/java/org/ruby_lang/prism/Loader.java.erb +++ b/templates/java/org/ruby_lang/prism/Loader.java.erb @@ -19,19 +19,11 @@ public class Loader { // Overridable methods - public Charset getEncodingCharset(String encodingName) { - encodingName = encodingName.toLowerCase(Locale.ROOT); - if (encodingName.equals("ascii-8bit")) { - return StandardCharsets.US_ASCII; - } - return Charset.forName(encodingName); - } - public <%= id_type %> bytesToName(byte[] bytes) { - <%- if id_type == "String" -%> - return new String(bytes, encodingCharset).intern(); - <%- else -%> + <%- if id_type == "byte[]" -%> return bytes; + <%- else -%> + throw new AbstractMethodError("Loader.bytesToName(<%= id_type %>) is not implemented"); <%- end -%> } @@ -74,9 +66,6 @@ public class Loader { private final ByteBuffer buffer; protected String encodingName; - <%- if id_type == "String" -%> - private Charset encodingCharset; - <%- end -%> private ConstantPool constantPool; private Nodes.Source source = null; @@ -104,9 +93,6 @@ public class Loader { byte[] encodingNameBytes = new byte[encodingLength]; buffer.get(encodingNameBytes); this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII); - <%- if id_type == "String" -%> - this.encodingCharset = getEncodingCharset(this.encodingName); - <%- end -%> source.setStartLine(loadVarSInt()); source.setLineOffsets(loadLineOffsets()); From e6e73add55fca51f9c44c222fb11e89d97d6b546 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 17:45:06 -0500 Subject: [PATCH 277/289] Fix toString output for byte[] fields --- templates/java/org/ruby_lang/prism/Nodes.java.erb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index f43df2623e..ed6bd5cb1d 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -139,6 +139,14 @@ public abstract class Nodes { protected abstract String toString(String indent); } + + protected static String asString(Object value) { + return value.toString(); + } + + protected static String asString(byte[] value) { + return new String(value, StandardCharsets.ISO_8859_1); + } <%-# FLAGS -%> <%- flags.each do |flag| -%> @@ -376,7 +384,7 @@ public abstract class Nodes { builder.append('"' + new String(this.<%= field.name %>, StandardCharsets.UTF_8) + '"'); builder.append('\n'); <%- when Prism::Template::ConstantField -%> - builder.append('"').append(this.<%= field.name %>).append('"'); + builder.append('"').append(asString(this.<%= field.name %>)).append('"'); builder.append('\n'); <%- when Prism::Template::OptionalConstantField -%> builder.append(this.<%= field.name %> == null ? "null" : "\"" + this.<%= field.name %> + "\""); From 901a7849e10f2e7ca7a1476d4ce9ce86488056aa Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 18:20:35 -0500 Subject: [PATCH 278/289] Verify the TruffleRuby backend for Java API This just checks that the TruffleRuby version of the Java API can compile. No tests are run because the API requires bytesToName to be overridden if identifiers are not byte[]. --- .github/workflows/java-wasm-bindings.yml | 35 +++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 2d6a574ee1..281747d652 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -15,7 +15,7 @@ on: pull_request: jobs: - build: + build-wasm: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 @@ -52,3 +52,36 @@ jobs: with: name: prism.wasm path: java-wasm/src/test/resources/prism.wasm + + build-truffleruby: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: head + bundler-cache: true + + - name: rake templates + run: PRISM_EXCLUDE_PRETTYPRINT=1 PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 PRISM_JAVA_BACKEND=truffleruby bundle exec rake templates + + - name: Set up WASI-SDK + run: | + wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz + tar xvf wasi-sdk-25.0-x86_64-linux.tar.gz + + - name: Build the project + run: make java-wasm WASI_SDK_PATH=$(pwd)/wasi-sdk-25.0-x86_64-linux + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '21' + cache: maven + + - name: Confirm compilation succeeds + run: mvn -B -DskipTests package + working-directory: java-wasm From 6ae9b211102153e16a33a4ab4d0149299a5e2a9e Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 18:38:17 -0500 Subject: [PATCH 279/289] Handle two other forms of identifier field --- templates/java/org/ruby_lang/prism/Nodes.java.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index ed6bd5cb1d..aedbe72b9a 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -387,12 +387,12 @@ public abstract class Nodes { builder.append('"').append(asString(this.<%= field.name %>)).append('"'); builder.append('\n'); <%- when Prism::Template::OptionalConstantField -%> - builder.append(this.<%= field.name %> == null ? "null" : "\"" + this.<%= field.name %> + "\""); + builder.append(this.<%= field.name %> == null ? "null" : "\"" + asString(this.<%= field.name %>) + "\""); builder.append('\n'); <%- when Prism::Template::ConstantListField -%> builder.append('\n'); for (<%= id_type %> constant : this.<%= field.name %>) { - builder.append(nextNextIndent).append('"').append(constant).append('"').append('\n'); + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); } <%- when Prism::Template::Flags -%> builder.append(flags); From da4325c999d6821d51ec91d1f8db4ac99c6ca9f5 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 18:54:56 -0500 Subject: [PATCH 280/289] Escape all byte[] strings for toString This avoids the debate about what encoding to assume they are, and loses no information about the original string contents. --- templates/java/org/ruby_lang/prism/Nodes.java.erb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/templates/java/org/ruby_lang/prism/Nodes.java.erb b/templates/java/org/ruby_lang/prism/Nodes.java.erb index aedbe72b9a..9ef03e99cd 100644 --- a/templates/java/org/ruby_lang/prism/Nodes.java.erb +++ b/templates/java/org/ruby_lang/prism/Nodes.java.erb @@ -145,7 +145,15 @@ public abstract class Nodes { } protected static String asString(byte[] value) { - return new String(value, StandardCharsets.ISO_8859_1); + StringBuilder buf = new StringBuilder(value.length); + for (byte b : value) { + if (b >= 0x20 && b <= 0x7e) { + buf.append((char) b); + } else { + buf.append(String.format("\\x%02x", Byte.toUnsignedInt(b))); + } + } + return buf.toString(); } <%-# FLAGS -%> <%- flags.each do |flag| -%> @@ -381,7 +389,7 @@ public abstract class Nodes { builder.append(nextNextIndent).append(child.toString(nextNextIndent)); } <%- when Prism::Template::StringField -%> - builder.append('"' + new String(this.<%= field.name %>, StandardCharsets.UTF_8) + '"'); + builder.append('"' + asString(this.<%= field.name %>) + '"'); builder.append('\n'); <%- when Prism::Template::ConstantField -%> builder.append('"').append(asString(this.<%= field.name %>)).append('"'); From 54b25c0deae6ddc244bb2d1917e1d7733f5f803f Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 18:55:40 -0500 Subject: [PATCH 281/289] Add a test for MBC identifiers --- .../java/org/jruby/parser/prism/WASMTest.java | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java index 9e2711cd6b..1056075b89 100644 --- a/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java @@ -5,6 +5,7 @@ import org.ruby_lang.prism.ParsingOptions; import org.ruby_lang.prism.wasm.Prism; +import java.nio.charset.StandardCharsets; import java.util.EnumSet; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -41,22 +42,6 @@ public void test1() { assertTrue(pr.value.childNodes()[0].toString().contains("IntegerNode")); } - @Test - public void test1Aot() { - // The Ruby source code to be processed - var source = "1 + 1"; - - ParseResult pr = null; - try (Prism prism = new Prism()) { - pr = prism.serializeParse(packedOptions, source); - } - - assertEquals(1, pr.value.childNodes().length); - System.out.println("Nodes:"); - System.out.println(pr.value.childNodes()[0]); - assertTrue(pr.value.childNodes()[0].toString().contains("IntegerNode")); - } - @Test public void test2() { // The Ruby source code to be processed @@ -74,19 +59,19 @@ public void test2() { } @Test - public void test2Aot() { + public void testMBCIdentifier() { // The Ruby source code to be processed - var source = "puts \"h\ne\nl\nl\no\n\""; + var source = new String("hellø = \"hello\"".getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1); ParseResult pr = null; try (Prism prism = new Prism()) { pr = prism.serializeParse(packedOptions, source); } - assertEquals(1, pr.value.childNodes().length); System.out.println("Nodes:"); + System.out.println(pr); System.out.println(pr.value.childNodes()[0]); - assertTrue(pr.value.childNodes()[0].toString().contains("CallNode")); + assertTrue(pr.value.childNodes()[0].toString().contains("hell\\xc3\\xb8")); } @Test From 70155e0bcb72627e797cc3dd88d174d56e54ffd7 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 19:03:12 -0500 Subject: [PATCH 282/289] Move TruffleRuby compile test to main.yml --- .github/workflows/java-wasm-bindings.yml | 33 ------------------------ .github/workflows/main.yml | 12 +++++++++ 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index 281747d652..e3919472c3 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -52,36 +52,3 @@ jobs: with: name: prism.wasm path: java-wasm/src/test/resources/prism.wasm - - build-truffleruby: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: head - bundler-cache: true - - - name: rake templates - run: PRISM_EXCLUDE_PRETTYPRINT=1 PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 PRISM_JAVA_BACKEND=truffleruby bundle exec rake templates - - - name: Set up WASI-SDK - run: | - wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz - tar xvf wasi-sdk-25.0-x86_64-linux.tar.gz - - - name: Build the project - run: make java-wasm WASI_SDK_PATH=$(pwd)/wasi-sdk-25.0-x86_64-linux - - - name: Set up Java - uses: actions/setup-java@v5 - with: - distribution: 'temurin' - java-version: '21' - cache: maven - - - name: Confirm compilation succeeds - run: mvn -B -DskipTests package - working-directory: java-wasm diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 356956ec8f..6b3888f57d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -188,6 +188,18 @@ jobs: - name: Run Java Loader test run: PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 JRUBY_OPTS="-J-ea" bundle exec rake test:java_loader + build-java-truffleruby: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Set up JRuby + uses: ruby/setup-ruby@v1 + with: + ruby-version: jruby + bundler-cache: true + - name: Run Java Loader test + run: PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 PRISM_JAVA_BACKEND=truffleruby bundle exec rake compile + lex-ruby: runs-on: ubuntu-latest steps: From e18286700bebd35c43ccdf75a2f48c634412da11 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 20 Mar 2026 19:09:10 -0500 Subject: [PATCH 283/289] JRuby uses the default byte[] identifiers now --- java-wasm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-wasm/README.md b/java-wasm/README.md index 1c9eaee85e..47aa48a774 100644 --- a/java-wasm/README.md +++ b/java-wasm/README.md @@ -5,7 +5,7 @@ This dir contains the chicory-prism artifact, a version of prism compiled to WAS Generate the templated sources: ``` -PRISM_EXCLUDE_PRETTYPRINT=1 PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 PRISM_JAVA_BACKEND=jruby bundle exec rake templates +PRISM_EXCLUDE_PRETTYPRINT=1 PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS=1 bundle exec rake templates ``` Compile to WASM using WASI SDK version 25: From 67f41550ec0d27a57682cd7ada86be561cb0a6fc Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Sat, 21 Mar 2026 13:34:24 -0500 Subject: [PATCH 284/289] Remove compile-time dependency on JRuby We use jruby-complete to have both the stdlib and JRuby's internal .rb boot files. --- java-wasm/pom.xml | 8 +------- .../src/test/java/org/jruby/parser/prism/JRubyTest.java | 3 +-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 2e6baaf7ca..89f248b378 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -61,16 +61,10 @@ org.jruby - jruby-stdlib + jruby-complete 10.0.4.0 test - - org.jruby - jruby-base - 10.0.4.0 - provided - diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java index 12c3e4f74d..2039935003 100644 --- a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java +++ b/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java @@ -1,6 +1,5 @@ package org.jruby.parser.prism; -import org.jruby.Ruby; import org.junit.jupiter.api.Test; import org.ruby_lang.prism.ParsingOptions; import org.ruby_lang.prism.wasm.Prism; @@ -132,7 +131,7 @@ private static void basicJRubyTest(Prism prism) throws Exception { new byte[][][]{} ); - try (InputStream fileIn = Ruby.getClassLoader().getResourceAsStream(file)) { + try (InputStream fileIn = JRubyTest.class.getClassLoader().getResourceAsStream(file)) { assertNotNull(fileIn, "Could not find file: " + file); DataInputStream dis = new DataInputStream(fileIn); int read = dis.read(src); From edde5442b724fbfc8a66130cf9ba3eb584f656f6 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Sat, 21 Mar 2026 19:10:00 -0500 Subject: [PATCH 285/289] Add URL, licenses, devs, and SCM info for Maven Central --- java-wasm/pom.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 89f248b378..e3401107c3 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -7,7 +7,25 @@ 0.0.1-SNAPSHOT Java Prism Java API for the Prism Ruby language parser + https://github.com/ruby/prism + + + MIT + + + + + + Charles Oliver Nutter + headius@headius.com + + + + + https://github.com/ruby/prism + https://github.com/ruby/prism.git + UTF-8 From 2a6178df6d05b30ea82641735154811c0653bf79 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Sat, 21 Mar 2026 19:10:24 -0500 Subject: [PATCH 286/289] Release prism-parser 0.0.1 --- java-wasm/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index e3401107c3..680bbbd7b4 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -4,7 +4,7 @@ org.ruby-lang prism-parser - 0.0.1-SNAPSHOT + 0.0.1 Java Prism Java API for the Prism Ruby language parser https://github.com/ruby/prism From 8506d144aa5f4936747c63dd29e24a13e0347555 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Sat, 21 Mar 2026 19:14:58 -0500 Subject: [PATCH 287/289] Bump version for dev --- java-wasm/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index 680bbbd7b4..bba737f105 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -4,7 +4,7 @@ org.ruby-lang prism-parser - 0.0.1 + 0.0.2-SNAPSHOT Java Prism Java API for the Prism Ruby language parser https://github.com/ruby/prism From fe6252deefa639fcbf2b5b1c0b1790993209e0ef Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 23 Mar 2026 11:02:42 -0500 Subject: [PATCH 288/289] Add other primary developers of Java API * @kddnewton * @eregon * @enebo --- java-wasm/pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml index bba737f105..5bbc308595 100644 --- a/java-wasm/pom.xml +++ b/java-wasm/pom.xml @@ -16,10 +16,22 @@ + + Kevin Newton + kddnewton@gmail.com + + + Benoit Daloze + eregontp@gmail.com + Charles Oliver Nutter headius@headius.com + + Thomas E Enebo + tom.enebo@gmail.com + From fc6901d17e6f33574d768784091beb96a08f19c0 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 23 Mar 2026 13:58:08 -0500 Subject: [PATCH 289/289] Begin splitting the Java artifact into components * The Loader API lives under java/api. * The current native endpoint for the Prism shared library lives under java/native. * The WASM build and binding lives under java/wasm. The libraries will be released together but can be developed and snapshotted independently. Users that copy the source from the previous java/ will want to grab both java/api/src/main/java and java/native/src/main/java contents. --- .github/dependabot.yml | 2 +- .github/workflows/java-wasm-bindings.yml | 6 +- .gitignore | 2 +- Makefile | 4 +- README.md | 6 +- Rakefile | 2 +- java-wasm/pom.xml | 236 - java/README.md | 25 + java/api/pom.xml | 81 + .../ruby_lang/prism/AbstractNodeVisitor.java | 1538 ++ .../main/java/org/ruby_lang/prism/Loader.java | 775 + .../ruby_lang/prism/MarkNewlinesVisitor.java | 0 .../main/java/org/ruby_lang/prism/Nodes.java | 11628 ++++++++++++++++ .../org/ruby_lang/prism/ParseResult.java | 0 .../org/ruby_lang/prism/ParsingOptions.java | 0 java/native/pom.xml | 72 + .../java}/org/ruby_lang/prism/Parser.java | 0 java/pom.xml | 157 + {java-wasm => java/wasm}/.gitignore | 0 {java-wasm => java/wasm}/README.md | 4 +- {java-wasm => java/wasm}/perf-test/.gitignore | 0 {java-wasm => java/wasm}/perf-test/bench.sh | 0 {java-wasm => java/wasm}/perf-test/test | 0 java/wasm/pom.xml | 126 + java/wasm/prism-parser.iml | 9 + .../ruby_lang/prism/wasm/WasmResource.java | 0 .../java/org/ruby_lang/prism/wasm/Prism.java | 0 .../org/jruby/parser/prism/JRubyTest.java | 0 .../java/org/jruby/parser/prism/WASMTest.java | 0 .../wasm}/src/test/resources/.gitignore | 0 rakelib/check_manifest.rake | 2 +- templates/template.rb | 6 +- 32 files changed, 14429 insertions(+), 252 deletions(-) delete mode 100644 java-wasm/pom.xml create mode 100644 java/README.md create mode 100644 java/api/pom.xml create mode 100644 java/api/src/main/java/org/ruby_lang/prism/AbstractNodeVisitor.java create mode 100644 java/api/src/main/java/org/ruby_lang/prism/Loader.java rename java/{ => api/src/main/java}/org/ruby_lang/prism/MarkNewlinesVisitor.java (100%) create mode 100644 java/api/src/main/java/org/ruby_lang/prism/Nodes.java rename java/{ => api/src/main/java}/org/ruby_lang/prism/ParseResult.java (100%) rename java/{ => api/src/main/java}/org/ruby_lang/prism/ParsingOptions.java (100%) create mode 100644 java/native/pom.xml rename java/{ => native/src/main/java}/org/ruby_lang/prism/Parser.java (100%) create mode 100644 java/pom.xml rename {java-wasm => java/wasm}/.gitignore (100%) rename {java-wasm => java/wasm}/README.md (88%) rename {java-wasm => java/wasm}/perf-test/.gitignore (100%) rename {java-wasm => java/wasm}/perf-test/bench.sh (100%) rename {java-wasm => java/wasm}/perf-test/test (100%) create mode 100644 java/wasm/pom.xml create mode 100644 java/wasm/prism-parser.iml rename {java-wasm => java/wasm}/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java (100%) rename {java-wasm => java/wasm}/src/main/java/org/ruby_lang/prism/wasm/Prism.java (100%) rename {java-wasm => java/wasm}/src/test/java/org/jruby/parser/prism/JRubyTest.java (100%) rename {java-wasm => java/wasm}/src/test/java/org/jruby/parser/prism/WASMTest.java (100%) rename {java-wasm => java/wasm}/src/test/resources/.gitignore (100%) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6e302f18de..bc0a555340 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,7 +9,7 @@ updates: patterns: - "*" - package-ecosystem: 'maven' - directory: '/java-wasm' + directory: '/java/wasm' schedule: interval: 'weekly' groups: diff --git a/.github/workflows/java-wasm-bindings.yml b/.github/workflows/java-wasm-bindings.yml index e3919472c3..352c1f7b4d 100644 --- a/.github/workflows/java-wasm-bindings.yml +++ b/.github/workflows/java-wasm-bindings.yml @@ -8,7 +8,7 @@ on: - "src/" - "*akefile*" - "java/" - - "java-wasm/" + - "java/wasm/" branches: - main - ruby-4.0 @@ -46,9 +46,9 @@ jobs: - name: Run the tests run: mvn -B install - working-directory: java-wasm + working-directory: java/wasm - uses: actions/upload-artifact@v7 with: name: prism.wasm - path: java-wasm/src/test/resources/prism.wasm + path: java/wasm/src/test/resources/prism.wasm diff --git a/.gitignore b/.gitignore index 516e30de3e..fcdec6fb0a 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,7 @@ out.svg /java/org/ruby_lang/prism/AbstractNodeVisitor.java /java/org/ruby_lang/prism/Loader.java /java/org/ruby_lang/prism/Nodes.java -/java-wasm/src/test/resources/prism.wasm +/java/wasm/src/test/resources/prism.wasm /lib/prism/compiler.rb /lib/prism/dispatcher.rb /lib/prism/dot_visitor.rb diff --git a/Makefile b/Makefile index d6d07943c3..039efee72c 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ all: shared static shared: build/libprism.$(SOEXT) static: build/libprism.a wasm: javascript/src/prism.wasm -java-wasm: java-wasm/src/test/resources/prism.wasm +java-wasm: java/wasm/src/test/resources/prism.wasm build/libprism.$(SOEXT): $(SHARED_OBJECTS) $(ECHO) "linking $@ with $(CC)" @@ -51,7 +51,7 @@ javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS) -Oz -g0 -flto -fdata-sections -ffunction-sections \ -o $@ $(SOURCES) -java-wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) +java/wasm/src/test/resources/prism.wasm: Makefile $(SOURCES) $(HEADERS) $(ECHO) "building $@" $(Q) $(MAKEDIRS) $(@D) $(Q) $(WASI_SDK_PATH)/bin/clang \ diff --git a/README.md b/README.md index 0805698d93..a4a9b6d340 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,10 @@ The repository contains the infrastructure for both a shared library (libprism) ├── include │   ├── prism header files for the shared library │   └── prism.h main header file for the shared library -├── java Java bindings for the shared library -├── java-wasm Java WASM bindings for the shared library +├── java +| ├── api Java API for Prism +| ├── native Java native bindings for the shared library +| └── wasm Java WASM bindings for the shared library ├── javascript JavaScript WASM bindings for the shared library ├── lib │   ├── prism Ruby library files diff --git a/Rakefile b/Rakefile index 80b00bd913..e6a86cdb15 100644 --- a/Rakefile +++ b/Rakefile @@ -54,7 +54,7 @@ end CLOBBER.concat(Prism::Template::TEMPLATES) CLOBBER.concat(["build"]) CLOBBER << "lib/prism/prism.#{RbConfig::CONFIG["DLEXT"]}" -CLOBBER << "java-wasm/src/main/resources/prism.wasm" +CLOBBER << "java/wasm/src/main/resources/prism.wasm" Prism::Template::TEMPLATES.each do |filepath| desc "Generate #{filepath}" diff --git a/java-wasm/pom.xml b/java-wasm/pom.xml deleted file mode 100644 index 5bbc308595..0000000000 --- a/java-wasm/pom.xml +++ /dev/null @@ -1,236 +0,0 @@ - - - 4.0.0 - - org.ruby-lang - prism-parser - 0.0.2-SNAPSHOT - Java Prism - Java API for the Prism Ruby language parser - https://github.com/ruby/prism - - - - MIT - - - - - - Kevin Newton - kddnewton@gmail.com - - - Benoit Daloze - eregontp@gmail.com - - - Charles Oliver Nutter - headius@headius.com - - - Thomas E Enebo - tom.enebo@gmail.com - - - - - https://github.com/ruby/prism - https://github.com/ruby/prism.git - - - - UTF-8 - UTF-8 - 21 - 21 - - 1.7.3 - 6.0.3 - - - - - - com.dylibso.chicory - bom - ${chicory.version} - pom - import - - - - - - - com.dylibso.chicory - runtime - - - com.dylibso.chicory - log - - - com.dylibso.chicory - wasi - - - com.dylibso.chicory - wasm - - - org.junit.jupiter - junit-jupiter-engine - ${junit.version} - test - - - com.dylibso.chicory - annotations - provided - - - org.jruby - jruby-complete - 10.0.4.0 - test - - - - - - release - - - - maven-source-plugin - - - attach-sources - - jar-no-fork - - - - - - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - none - - - - maven-gpg-plugin - 3.2.4 - - - sign-artifacts - verify - - sign - - - - - - --pinentry-mode - loopback - - - - - - - - - - - - org.codehaus.mojo - templating-maven-plugin - 3.1.0 - - - filtering-java-templates - - filter-sources - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.15.0 - - 21 - - - com.dylibso.chicory - annotations-processor - ${chicory.version} - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.5.5 - - - org.codehaus.mojo - build-helper-maven-plugin - 3.6.1 - - - generate-sources - - add-source - - - - ../java - - - - - - - com.dylibso.chicory - chicory-compiler-maven-plugin - ${chicory.version} - - - prism - - compile - - - org.ruby_lang.prism.wasm.PrismParser - src/test/resources/prism.wasm - - - - - - org.sonatype.central - central-publishing-maven-plugin - 0.7.0 - true - - central - - - - - - diff --git a/java/README.md b/java/README.md new file mode 100644 index 0000000000..b3062cebd2 --- /dev/null +++ b/java/README.md @@ -0,0 +1,25 @@ +# Prism Java API and bindings + +This is the top-level project for the Java API and backend bindings for the Prism Ruby language parser. + +* api/ contains the API +* native/ contains a native binding for the Prism shared library +* wasm/ contains a Chicory-based WASM build and binding + +## Updating versions + +Run the following command to update all module versions: + +``` +mvn versions:set -DnewVersion=1.2.3-SNAPSHOT +``` + +## Releasing + +Snapshots can be deployed with `mvn deploy` while the versions are `-SNAPSHOT`. + +When releasing to Maven Central, all projects should be released together using the `release` profile: + +``` +mvn clean deploy -Prelease +``` diff --git a/java/api/pom.xml b/java/api/pom.xml new file mode 100644 index 0000000000..6b3bd6d3a8 --- /dev/null +++ b/java/api/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + + org.ruby-lang + prism-parser + 0.0.2-SNAPSHOT + + + prism-parser-api + Java Prism + Java API for the Prism Ruby language parser + https://github.com/ruby/prism + + + + org.ruby-lang + prism-parser-native + 0.0.2-SNAPSHOT + provided + + + + + + + org.codehaus.mojo + templating-maven-plugin + 3.1.0 + + + filtering-java-templates + + filter-sources + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.15.0 + + 21 + + + com.dylibso.chicory + annotations-processor + ${chicory.version} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.5 + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.1 + + + generate-sources + + add-source + + + + ../java + + + + + + + + + diff --git a/java/api/src/main/java/org/ruby_lang/prism/AbstractNodeVisitor.java b/java/api/src/main/java/org/ruby_lang/prism/AbstractNodeVisitor.java new file mode 100644 index 0000000000..9c76b38d8e --- /dev/null +++ b/java/api/src/main/java/org/ruby_lang/prism/AbstractNodeVisitor.java @@ -0,0 +1,1538 @@ +/*----------------------------------------------------------------------------*/ +/* This file is generated by the templates/template.rb script and should not */ +/* be modified manually. See */ +/* templates/java/org/ruby_lang/prism/AbstractNodeVisitor.java.erb */ +/* if you are looking to modify the */ +/* template */ +/*----------------------------------------------------------------------------*/ + +package org.ruby_lang.prism; + +// GENERATED BY AbstractNodeVisitor.java.erb +// @formatter:off +public abstract class AbstractNodeVisitor { + + protected abstract T defaultVisit(Nodes.Node node); + + /** + * Visit a AliasGlobalVariableNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitAliasGlobalVariableNode(Nodes.AliasGlobalVariableNode node) { + return defaultVisit(node); + } + + /** + * Visit a AliasMethodNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitAliasMethodNode(Nodes.AliasMethodNode node) { + return defaultVisit(node); + } + + /** + * Visit a AlternationPatternNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitAlternationPatternNode(Nodes.AlternationPatternNode node) { + return defaultVisit(node); + } + + /** + * Visit a AndNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitAndNode(Nodes.AndNode node) { + return defaultVisit(node); + } + + /** + * Visit a ArgumentsNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitArgumentsNode(Nodes.ArgumentsNode node) { + return defaultVisit(node); + } + + /** + * Visit a ArrayNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitArrayNode(Nodes.ArrayNode node) { + return defaultVisit(node); + } + + /** + * Visit a ArrayPatternNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitArrayPatternNode(Nodes.ArrayPatternNode node) { + return defaultVisit(node); + } + + /** + * Visit a AssocNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitAssocNode(Nodes.AssocNode node) { + return defaultVisit(node); + } + + /** + * Visit a AssocSplatNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitAssocSplatNode(Nodes.AssocSplatNode node) { + return defaultVisit(node); + } + + /** + * Visit a BackReferenceReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBackReferenceReadNode(Nodes.BackReferenceReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a BeginNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBeginNode(Nodes.BeginNode node) { + return defaultVisit(node); + } + + /** + * Visit a BlockArgumentNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBlockArgumentNode(Nodes.BlockArgumentNode node) { + return defaultVisit(node); + } + + /** + * Visit a BlockLocalVariableNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBlockLocalVariableNode(Nodes.BlockLocalVariableNode node) { + return defaultVisit(node); + } + + /** + * Visit a BlockNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBlockNode(Nodes.BlockNode node) { + return defaultVisit(node); + } + + /** + * Visit a BlockParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBlockParameterNode(Nodes.BlockParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a BlockParametersNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBlockParametersNode(Nodes.BlockParametersNode node) { + return defaultVisit(node); + } + + /** + * Visit a BreakNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitBreakNode(Nodes.BreakNode node) { + return defaultVisit(node); + } + + /** + * Visit a CallAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCallAndWriteNode(Nodes.CallAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a CallNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCallNode(Nodes.CallNode node) { + return defaultVisit(node); + } + + /** + * Visit a CallOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCallOperatorWriteNode(Nodes.CallOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a CallOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCallOrWriteNode(Nodes.CallOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a CallTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCallTargetNode(Nodes.CallTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a CapturePatternNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCapturePatternNode(Nodes.CapturePatternNode node) { + return defaultVisit(node); + } + + /** + * Visit a CaseMatchNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCaseMatchNode(Nodes.CaseMatchNode node) { + return defaultVisit(node); + } + + /** + * Visit a CaseNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitCaseNode(Nodes.CaseNode node) { + return defaultVisit(node); + } + + /** + * Visit a ClassNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitClassNode(Nodes.ClassNode node) { + return defaultVisit(node); + } + + /** + * Visit a ClassVariableAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitClassVariableAndWriteNode(Nodes.ClassVariableAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ClassVariableOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitClassVariableOperatorWriteNode(Nodes.ClassVariableOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ClassVariableOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitClassVariableOrWriteNode(Nodes.ClassVariableOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ClassVariableReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitClassVariableReadNode(Nodes.ClassVariableReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a ClassVariableTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitClassVariableTargetNode(Nodes.ClassVariableTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a ClassVariableWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitClassVariableWriteNode(Nodes.ClassVariableWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantAndWriteNode(Nodes.ConstantAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantOperatorWriteNode(Nodes.ConstantOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantOrWriteNode(Nodes.ConstantOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantPathAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantPathAndWriteNode(Nodes.ConstantPathAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantPathNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantPathNode(Nodes.ConstantPathNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantPathOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantPathOperatorWriteNode(Nodes.ConstantPathOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantPathOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantPathOrWriteNode(Nodes.ConstantPathOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantPathTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantPathTargetNode(Nodes.ConstantPathTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantPathWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantPathWriteNode(Nodes.ConstantPathWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantReadNode(Nodes.ConstantReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantTargetNode(Nodes.ConstantTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a ConstantWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitConstantWriteNode(Nodes.ConstantWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a DefNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitDefNode(Nodes.DefNode node) { + return defaultVisit(node); + } + + /** + * Visit a DefinedNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitDefinedNode(Nodes.DefinedNode node) { + return defaultVisit(node); + } + + /** + * Visit a ElseNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitElseNode(Nodes.ElseNode node) { + return defaultVisit(node); + } + + /** + * Visit a EmbeddedStatementsNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitEmbeddedStatementsNode(Nodes.EmbeddedStatementsNode node) { + return defaultVisit(node); + } + + /** + * Visit a EmbeddedVariableNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitEmbeddedVariableNode(Nodes.EmbeddedVariableNode node) { + return defaultVisit(node); + } + + /** + * Visit a EnsureNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitEnsureNode(Nodes.EnsureNode node) { + return defaultVisit(node); + } + + /** + * Visit a FalseNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitFalseNode(Nodes.FalseNode node) { + return defaultVisit(node); + } + + /** + * Visit a FindPatternNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitFindPatternNode(Nodes.FindPatternNode node) { + return defaultVisit(node); + } + + /** + * Visit a FlipFlopNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitFlipFlopNode(Nodes.FlipFlopNode node) { + return defaultVisit(node); + } + + /** + * Visit a FloatNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitFloatNode(Nodes.FloatNode node) { + return defaultVisit(node); + } + + /** + * Visit a ForNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitForNode(Nodes.ForNode node) { + return defaultVisit(node); + } + + /** + * Visit a ForwardingArgumentsNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitForwardingArgumentsNode(Nodes.ForwardingArgumentsNode node) { + return defaultVisit(node); + } + + /** + * Visit a ForwardingParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitForwardingParameterNode(Nodes.ForwardingParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a ForwardingSuperNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitForwardingSuperNode(Nodes.ForwardingSuperNode node) { + return defaultVisit(node); + } + + /** + * Visit a GlobalVariableAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitGlobalVariableAndWriteNode(Nodes.GlobalVariableAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a GlobalVariableOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitGlobalVariableOperatorWriteNode(Nodes.GlobalVariableOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a GlobalVariableOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitGlobalVariableOrWriteNode(Nodes.GlobalVariableOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a GlobalVariableReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitGlobalVariableReadNode(Nodes.GlobalVariableReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a GlobalVariableTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitGlobalVariableTargetNode(Nodes.GlobalVariableTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a GlobalVariableWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitGlobalVariableWriteNode(Nodes.GlobalVariableWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a HashNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitHashNode(Nodes.HashNode node) { + return defaultVisit(node); + } + + /** + * Visit a HashPatternNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitHashPatternNode(Nodes.HashPatternNode node) { + return defaultVisit(node); + } + + /** + * Visit a IfNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitIfNode(Nodes.IfNode node) { + return defaultVisit(node); + } + + /** + * Visit a ImaginaryNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitImaginaryNode(Nodes.ImaginaryNode node) { + return defaultVisit(node); + } + + /** + * Visit a ImplicitNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitImplicitNode(Nodes.ImplicitNode node) { + return defaultVisit(node); + } + + /** + * Visit a ImplicitRestNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitImplicitRestNode(Nodes.ImplicitRestNode node) { + return defaultVisit(node); + } + + /** + * Visit a InNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInNode(Nodes.InNode node) { + return defaultVisit(node); + } + + /** + * Visit a IndexAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitIndexAndWriteNode(Nodes.IndexAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a IndexOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitIndexOperatorWriteNode(Nodes.IndexOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a IndexOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitIndexOrWriteNode(Nodes.IndexOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a IndexTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitIndexTargetNode(Nodes.IndexTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a InstanceVariableAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInstanceVariableAndWriteNode(Nodes.InstanceVariableAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a InstanceVariableOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInstanceVariableOperatorWriteNode(Nodes.InstanceVariableOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a InstanceVariableOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInstanceVariableOrWriteNode(Nodes.InstanceVariableOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a InstanceVariableReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInstanceVariableReadNode(Nodes.InstanceVariableReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a InstanceVariableTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInstanceVariableTargetNode(Nodes.InstanceVariableTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a InstanceVariableWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInstanceVariableWriteNode(Nodes.InstanceVariableWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a IntegerNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitIntegerNode(Nodes.IntegerNode node) { + return defaultVisit(node); + } + + /** + * Visit a InterpolatedMatchLastLineNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInterpolatedMatchLastLineNode(Nodes.InterpolatedMatchLastLineNode node) { + return defaultVisit(node); + } + + /** + * Visit a InterpolatedRegularExpressionNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInterpolatedRegularExpressionNode(Nodes.InterpolatedRegularExpressionNode node) { + return defaultVisit(node); + } + + /** + * Visit a InterpolatedStringNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInterpolatedStringNode(Nodes.InterpolatedStringNode node) { + return defaultVisit(node); + } + + /** + * Visit a InterpolatedSymbolNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInterpolatedSymbolNode(Nodes.InterpolatedSymbolNode node) { + return defaultVisit(node); + } + + /** + * Visit a InterpolatedXStringNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitInterpolatedXStringNode(Nodes.InterpolatedXStringNode node) { + return defaultVisit(node); + } + + /** + * Visit a ItLocalVariableReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitItLocalVariableReadNode(Nodes.ItLocalVariableReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a ItParametersNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitItParametersNode(Nodes.ItParametersNode node) { + return defaultVisit(node); + } + + /** + * Visit a KeywordHashNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitKeywordHashNode(Nodes.KeywordHashNode node) { + return defaultVisit(node); + } + + /** + * Visit a KeywordRestParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitKeywordRestParameterNode(Nodes.KeywordRestParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a LambdaNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitLambdaNode(Nodes.LambdaNode node) { + return defaultVisit(node); + } + + /** + * Visit a LocalVariableAndWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitLocalVariableAndWriteNode(Nodes.LocalVariableAndWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a LocalVariableOperatorWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitLocalVariableOperatorWriteNode(Nodes.LocalVariableOperatorWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a LocalVariableOrWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitLocalVariableOrWriteNode(Nodes.LocalVariableOrWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a LocalVariableReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitLocalVariableReadNode(Nodes.LocalVariableReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a LocalVariableTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitLocalVariableTargetNode(Nodes.LocalVariableTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a LocalVariableWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitLocalVariableWriteNode(Nodes.LocalVariableWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a MatchLastLineNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitMatchLastLineNode(Nodes.MatchLastLineNode node) { + return defaultVisit(node); + } + + /** + * Visit a MatchPredicateNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitMatchPredicateNode(Nodes.MatchPredicateNode node) { + return defaultVisit(node); + } + + /** + * Visit a MatchRequiredNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitMatchRequiredNode(Nodes.MatchRequiredNode node) { + return defaultVisit(node); + } + + /** + * Visit a MatchWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitMatchWriteNode(Nodes.MatchWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a MissingNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitMissingNode(Nodes.MissingNode node) { + return defaultVisit(node); + } + + /** + * Visit a ModuleNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitModuleNode(Nodes.ModuleNode node) { + return defaultVisit(node); + } + + /** + * Visit a MultiTargetNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitMultiTargetNode(Nodes.MultiTargetNode node) { + return defaultVisit(node); + } + + /** + * Visit a MultiWriteNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitMultiWriteNode(Nodes.MultiWriteNode node) { + return defaultVisit(node); + } + + /** + * Visit a NextNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitNextNode(Nodes.NextNode node) { + return defaultVisit(node); + } + + /** + * Visit a NilNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitNilNode(Nodes.NilNode node) { + return defaultVisit(node); + } + + /** + * Visit a NoBlockParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitNoBlockParameterNode(Nodes.NoBlockParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a NoKeywordsParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitNoKeywordsParameterNode(Nodes.NoKeywordsParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a NumberedParametersNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitNumberedParametersNode(Nodes.NumberedParametersNode node) { + return defaultVisit(node); + } + + /** + * Visit a NumberedReferenceReadNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitNumberedReferenceReadNode(Nodes.NumberedReferenceReadNode node) { + return defaultVisit(node); + } + + /** + * Visit a OptionalKeywordParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitOptionalKeywordParameterNode(Nodes.OptionalKeywordParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a OptionalParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitOptionalParameterNode(Nodes.OptionalParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a OrNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitOrNode(Nodes.OrNode node) { + return defaultVisit(node); + } + + /** + * Visit a ParametersNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitParametersNode(Nodes.ParametersNode node) { + return defaultVisit(node); + } + + /** + * Visit a ParenthesesNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitParenthesesNode(Nodes.ParenthesesNode node) { + return defaultVisit(node); + } + + /** + * Visit a PinnedExpressionNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitPinnedExpressionNode(Nodes.PinnedExpressionNode node) { + return defaultVisit(node); + } + + /** + * Visit a PinnedVariableNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitPinnedVariableNode(Nodes.PinnedVariableNode node) { + return defaultVisit(node); + } + + /** + * Visit a PostExecutionNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitPostExecutionNode(Nodes.PostExecutionNode node) { + return defaultVisit(node); + } + + /** + * Visit a PreExecutionNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitPreExecutionNode(Nodes.PreExecutionNode node) { + return defaultVisit(node); + } + + /** + * Visit a ProgramNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitProgramNode(Nodes.ProgramNode node) { + return defaultVisit(node); + } + + /** + * Visit a RangeNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRangeNode(Nodes.RangeNode node) { + return defaultVisit(node); + } + + /** + * Visit a RationalNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRationalNode(Nodes.RationalNode node) { + return defaultVisit(node); + } + + /** + * Visit a RedoNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRedoNode(Nodes.RedoNode node) { + return defaultVisit(node); + } + + /** + * Visit a RegularExpressionNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRegularExpressionNode(Nodes.RegularExpressionNode node) { + return defaultVisit(node); + } + + /** + * Visit a RequiredKeywordParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRequiredKeywordParameterNode(Nodes.RequiredKeywordParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a RequiredParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRequiredParameterNode(Nodes.RequiredParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a RescueModifierNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRescueModifierNode(Nodes.RescueModifierNode node) { + return defaultVisit(node); + } + + /** + * Visit a RescueNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRescueNode(Nodes.RescueNode node) { + return defaultVisit(node); + } + + /** + * Visit a RestParameterNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRestParameterNode(Nodes.RestParameterNode node) { + return defaultVisit(node); + } + + /** + * Visit a RetryNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitRetryNode(Nodes.RetryNode node) { + return defaultVisit(node); + } + + /** + * Visit a ReturnNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitReturnNode(Nodes.ReturnNode node) { + return defaultVisit(node); + } + + /** + * Visit a SelfNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSelfNode(Nodes.SelfNode node) { + return defaultVisit(node); + } + + /** + * Visit a ShareableConstantNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitShareableConstantNode(Nodes.ShareableConstantNode node) { + return defaultVisit(node); + } + + /** + * Visit a SingletonClassNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSingletonClassNode(Nodes.SingletonClassNode node) { + return defaultVisit(node); + } + + /** + * Visit a SourceEncodingNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSourceEncodingNode(Nodes.SourceEncodingNode node) { + return defaultVisit(node); + } + + /** + * Visit a SourceFileNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSourceFileNode(Nodes.SourceFileNode node) { + return defaultVisit(node); + } + + /** + * Visit a SourceLineNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSourceLineNode(Nodes.SourceLineNode node) { + return defaultVisit(node); + } + + /** + * Visit a SplatNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSplatNode(Nodes.SplatNode node) { + return defaultVisit(node); + } + + /** + * Visit a StatementsNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitStatementsNode(Nodes.StatementsNode node) { + return defaultVisit(node); + } + + /** + * Visit a StringNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitStringNode(Nodes.StringNode node) { + return defaultVisit(node); + } + + /** + * Visit a SuperNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSuperNode(Nodes.SuperNode node) { + return defaultVisit(node); + } + + /** + * Visit a SymbolNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitSymbolNode(Nodes.SymbolNode node) { + return defaultVisit(node); + } + + /** + * Visit a TrueNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitTrueNode(Nodes.TrueNode node) { + return defaultVisit(node); + } + + /** + * Visit a UndefNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitUndefNode(Nodes.UndefNode node) { + return defaultVisit(node); + } + + /** + * Visit a UnlessNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitUnlessNode(Nodes.UnlessNode node) { + return defaultVisit(node); + } + + /** + * Visit a UntilNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitUntilNode(Nodes.UntilNode node) { + return defaultVisit(node); + } + + /** + * Visit a WhenNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitWhenNode(Nodes.WhenNode node) { + return defaultVisit(node); + } + + /** + * Visit a WhileNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitWhileNode(Nodes.WhileNode node) { + return defaultVisit(node); + } + + /** + * Visit a XStringNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitXStringNode(Nodes.XStringNode node) { + return defaultVisit(node); + } + + /** + * Visit a YieldNode node. + * + * @param node The node to visit. + * @return The result of visiting the node. + */ + public T visitYieldNode(Nodes.YieldNode node) { + return defaultVisit(node); + } + +} +// @formatter:on diff --git a/java/api/src/main/java/org/ruby_lang/prism/Loader.java b/java/api/src/main/java/org/ruby_lang/prism/Loader.java new file mode 100644 index 0000000000..f084d169ad --- /dev/null +++ b/java/api/src/main/java/org/ruby_lang/prism/Loader.java @@ -0,0 +1,775 @@ +/*----------------------------------------------------------------------------*/ +/* This file is generated by the templates/template.rb script and should not */ +/* be modified manually. See */ +/* templates/java/org/ruby_lang/prism/Loader.java.erb */ +/* if you are looking to modify the */ +/* template */ +/*----------------------------------------------------------------------------*/ + +package org.ruby_lang.prism; + +import java.lang.Short; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Locale; + +// GENERATED BY Loader.java.erb +// @formatter:off +public class Loader { + + public static ParseResult load(byte[] serialized) { + return new Loader(serialized).load(); + } + + // Overridable methods + + public byte[] bytesToName(byte[] bytes) { + return bytes; + } + + private static final class ConstantPool { + + private final Loader loader; + private final int bufferOffset; + private final byte[][] cache; + + ConstantPool(Loader loader, int bufferOffset, int length) { + this.loader = loader; + this.bufferOffset = bufferOffset; + cache = new byte[length][]; + } + + byte[] get(ByteBuffer buffer, int oneBasedIndex) { + int index = oneBasedIndex - 1; + byte[] constant = cache[index]; + + if (constant == null) { + int offset = bufferOffset + index * 8; + int start = buffer.getInt(offset); + int length = buffer.getInt(offset + 4); + + byte[] bytes = new byte[length]; + buffer.get(start, bytes); + + constant = loader.bytesToName(bytes); + cache[index] = constant; + } + + return constant; + } + + } + + private final ByteBuffer buffer; + protected String encodingName; + private ConstantPool constantPool; + private Nodes.Source source = null; + + protected Loader(byte[] serialized) { + this.buffer = ByteBuffer.wrap(serialized).order(ByteOrder.nativeOrder()); + } + + protected ParseResult load() { + this.source = new Nodes.Source(); + + expect((byte) 'P', "incorrect prism header"); + expect((byte) 'R', "incorrect prism header"); + expect((byte) 'I', "incorrect prism header"); + expect((byte) 'S', "incorrect prism header"); + expect((byte) 'M', "incorrect prism header"); + + expect((byte) 1, "prism major version does not match"); + expect((byte) 9, "prism minor version does not match"); + expect((byte) 0, "prism patch version does not match"); + + expect((byte) 1, "Loader.java requires no location fields in the serialized output"); + + // This loads the name of the encoding. + int encodingLength = loadVarUInt(); + byte[] encodingNameBytes = new byte[encodingLength]; + buffer.get(encodingNameBytes); + this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII); + + source.setStartLine(loadVarSInt()); + source.setLineOffsets(loadLineOffsets()); + + ParseResult.MagicComment[] magicComments = loadMagicComments(); + Nodes.Location dataLocation = loadOptionalLocation(); + ParseResult.Error[] errors = loadErrors(); + ParseResult.Warning[] warnings = loadWarnings(); + boolean continuable = buffer.get() != 0; + + int constantPoolBufferOffset = buffer.getInt(); + int constantPoolLength = loadVarUInt(); + this.constantPool = new ConstantPool(this, constantPoolBufferOffset, constantPoolLength); + + Nodes.Node node; + if (errors.length == 0) { + node = loadNode(); + + int left = constantPoolBufferOffset - buffer.position(); + if (left != 0) { + throw new Error("Expected to consume all bytes while deserializing but there were " + left + " bytes left"); + } + + MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source); + node.accept(visitor); + } else { + node = null; + } + + return new ParseResult(node, magicComments, dataLocation, errors, warnings, continuable, source); + } + + private byte[] loadString() { + int length = loadVarUInt(); + byte[] bytes = new byte[length]; + buffer.get(bytes); + return bytes; + } + + private int[] loadLineOffsets() { + int count = loadVarUInt(); + int[] lineOffsets = new int[count]; + for (int i = 0; i < count; i++) { + lineOffsets[i] = loadVarUInt(); + } + return lineOffsets; + } + + private ParseResult.MagicComment[] loadMagicComments() { + int count = loadVarUInt(); + ParseResult.MagicComment[] magicComments = new ParseResult.MagicComment[count]; + + for (int i = 0; i < count; i++) { + Nodes.Location keyLocation = loadLocation(); + Nodes.Location valueLocation = loadLocation(); + + ParseResult.MagicComment magicComment = new ParseResult.MagicComment(keyLocation, valueLocation); + magicComments[i] = magicComment; + } + + return magicComments; + } + + private ParseResult.Error[] loadErrors() { + int count = loadVarUInt(); + ParseResult.Error[] errors = new ParseResult.Error[count]; + + // error messages only contain ASCII characters + for (int i = 0; i < count; i++) { + Nodes.ErrorType type = Nodes.ERROR_TYPES[loadVarUInt()]; + byte[] bytes = loadString(); + String message = new String(bytes, StandardCharsets.US_ASCII); + Nodes.Location location = loadLocation(); + ParseResult.ErrorLevel level = ParseResult.ERROR_LEVELS[buffer.get()]; + + ParseResult.Error error = new ParseResult.Error(type, message, location, level); + errors[i] = error; + } + + return errors; + } + + private ParseResult.Warning[] loadWarnings() { + int count = loadVarUInt(); + ParseResult.Warning[] warnings = new ParseResult.Warning[count]; + + // warning messages only contain ASCII characters + for (int i = 0; i < count; i++) { + Nodes.WarningType type = Nodes.WARNING_TYPES[loadVarUInt() - 299]; + byte[] bytes = loadString(); + String message = new String(bytes, StandardCharsets.US_ASCII); + Nodes.Location location = loadLocation(); + ParseResult.WarningLevel level = ParseResult.WARNING_LEVELS[buffer.get()]; + + ParseResult.Warning warning = new ParseResult.Warning(type, message, location, level); + warnings[i] = warning; + } + + return warnings; + } + + private Nodes.Node loadOptionalNode() { + if (buffer.get(buffer.position()) != 0) { + return loadNode(); + } else { + buffer.position(buffer.position() + 1); // continue after the 0 byte + return null; + } + } + + private byte[] loadConstant() { + return constantPool.get(buffer, loadVarUInt()); + } + + private byte[] loadOptionalConstant() { + if (buffer.get(buffer.position()) != 0) { + return loadConstant(); + } else { + buffer.position(buffer.position() + 1); // continue after the 0 byte + return null; + } + } + + private byte[][] loadConstants() { + int length = loadVarUInt(); + if (length == 0) { + return Nodes.EMPTY_IDENTIFIER_ARRAY; + } + byte[][] constants = new byte[length][]; + for (int i = 0; i < length; i++) { + constants[i] = constantPool.get(buffer, loadVarUInt()); + } + return constants; + } + + private Nodes.Location loadLocation() { + return new Nodes.Location(loadVarUInt(), loadVarUInt()); + } + + private Nodes.Location loadOptionalLocation() { + if (buffer.get() != 0) { + return loadLocation(); + } else { + return null; + } + } + + // From https://github.com/protocolbuffers/protobuf/blob/v23.1/java/core/src/main/java/com/google/protobuf/BinaryReader.java#L1507 + private int loadVarUInt() { + int x; + if ((x = buffer.get()) >= 0) { + return x; + } else if ((x ^= (buffer.get() << 7)) < 0) { + x ^= (~0 << 7); + } else if ((x ^= (buffer.get() << 14)) >= 0) { + x ^= (~0 << 7) ^ (~0 << 14); + } else if ((x ^= (buffer.get() << 21)) < 0) { + x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21); + } else { + x ^= buffer.get() << 28; + x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28); + } + return x; + } + + // From https://github.com/protocolbuffers/protobuf/blob/v25.1/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L508-L510 + private int loadVarSInt() { + int x = loadVarUInt(); + return (x >>> 1) ^ (-(x & 1)); + } + + private short loadFlags() { + int flags = loadVarUInt(); + assert flags >= 0 && flags <= Short.MAX_VALUE; + return (short) flags; + } + + private static final BigInteger UNSIGNED_LONG_MASK = BigInteger.ONE.shiftLeft(Long.SIZE).subtract(BigInteger.ONE); + + private Object loadInteger() { + boolean negative = buffer.get() != 0; + + int wordsLength = loadVarUInt(); + assert wordsLength > 0; + + // Load the first word. If it's the only word, then return an int if it + // fits into one and a long otherwise. + int firstWord = loadVarUInt(); + if (wordsLength == 1) { + if (firstWord < 0) { + if (negative && firstWord == Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } + + long words = Integer.toUnsignedLong(firstWord); + return negative ? -words : words; + } + return negative ? -firstWord : firstWord; + } + + // Load the second word. If there are only two words, then return a long + // if it fits into one and a BigInteger otherwise. + int secondWord = loadVarUInt(); + if (wordsLength == 2) { + long words = (((long) secondWord) << 32L) | Integer.toUnsignedLong(firstWord); + if (words < 0L) { + if (negative && words == Long.MIN_VALUE) { + return Long.MIN_VALUE; + } + + BigInteger result = BigInteger.valueOf(words).and(UNSIGNED_LONG_MASK); + return negative ? result.negate() : result; + } + return negative ? -words : words; + } + + // Otherwise, load the remaining words and return a BigInt. + BigInteger result = BigInteger.valueOf(Integer.toUnsignedLong(firstWord)); + result = result.or(BigInteger.valueOf(Integer.toUnsignedLong(secondWord)).shiftLeft(32)); + + for (int wordsIndex = 2; wordsIndex < wordsLength; wordsIndex++) { + result = result.or(BigInteger.valueOf(Integer.toUnsignedLong(loadVarUInt())).shiftLeft(wordsIndex * 32)); + } + + return negative ? result.negate() : result; + } + + private Nodes.Node loadNode() { + int type = buffer.get() & 0xFF; + int startOffset = loadVarUInt(); + int length = loadVarUInt(); + + switch (type) { + case 1: + return new Nodes.AliasGlobalVariableNode(startOffset, length, loadNode(), loadNode()); + case 2: + return new Nodes.AliasMethodNode(startOffset, length, loadNode(), loadNode()); + case 3: + return new Nodes.AlternationPatternNode(startOffset, length, loadNode(), loadNode()); + case 4: + return new Nodes.AndNode(startOffset, length, loadNode(), loadNode()); + case 5: + return new Nodes.ArgumentsNode(startOffset, length, loadFlags(), loadNodes()); + case 6: + return new Nodes.ArrayNode(startOffset, length, loadFlags(), loadNodes()); + case 7: + return new Nodes.ArrayPatternNode(startOffset, length, loadOptionalNode(), loadNodes(), loadOptionalNode(), loadNodes()); + case 8: + return new Nodes.AssocNode(startOffset, length, loadNode(), loadNode()); + case 9: + return new Nodes.AssocSplatNode(startOffset, length, loadOptionalNode()); + case 10: + return new Nodes.BackReferenceReadNode(startOffset, length, loadConstant()); + case 11: + return new Nodes.BeginNode(startOffset, length, (Nodes.StatementsNode) loadOptionalNode(), (Nodes.RescueNode) loadOptionalNode(), (Nodes.ElseNode) loadOptionalNode(), (Nodes.EnsureNode) loadOptionalNode()); + case 12: + return new Nodes.BlockArgumentNode(startOffset, length, loadOptionalNode()); + case 13: + return new Nodes.BlockLocalVariableNode(startOffset, length, loadFlags(), loadConstant()); + case 14: + return new Nodes.BlockNode(startOffset, length, loadConstants(), loadOptionalNode(), loadOptionalNode()); + case 15: + return new Nodes.BlockParameterNode(startOffset, length, loadFlags(), loadOptionalConstant()); + case 16: + return new Nodes.BlockParametersNode(startOffset, length, (Nodes.ParametersNode) loadOptionalNode(), loadBlockLocalVariableNodes()); + case 17: + return new Nodes.BreakNode(startOffset, length, (Nodes.ArgumentsNode) loadOptionalNode()); + case 18: + return new Nodes.CallAndWriteNode(startOffset, length, loadFlags(), loadOptionalNode(), loadConstant(), loadConstant(), loadNode()); + case 19: + return new Nodes.CallNode(startOffset, length, loadFlags(), loadOptionalNode(), loadConstant(), (Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode()); + case 20: + return new Nodes.CallOperatorWriteNode(startOffset, length, loadFlags(), loadOptionalNode(), loadConstant(), loadConstant(), loadConstant(), loadNode()); + case 21: + return new Nodes.CallOrWriteNode(startOffset, length, loadFlags(), loadOptionalNode(), loadConstant(), loadConstant(), loadNode()); + case 22: + return new Nodes.CallTargetNode(startOffset, length, loadFlags(), loadNode(), loadConstant()); + case 23: + return new Nodes.CapturePatternNode(startOffset, length, loadNode(), (Nodes.LocalVariableTargetNode) loadNode()); + case 24: + return new Nodes.CaseMatchNode(startOffset, length, loadOptionalNode(), loadInNodes(), (Nodes.ElseNode) loadOptionalNode()); + case 25: + return new Nodes.CaseNode(startOffset, length, loadOptionalNode(), loadWhenNodes(), (Nodes.ElseNode) loadOptionalNode()); + case 26: + return new Nodes.ClassNode(startOffset, length, loadConstants(), loadNode(), loadOptionalNode(), loadOptionalNode(), loadConstant()); + case 27: + return new Nodes.ClassVariableAndWriteNode(startOffset, length, loadConstant(), loadNode()); + case 28: + return new Nodes.ClassVariableOperatorWriteNode(startOffset, length, loadConstant(), loadNode(), loadConstant()); + case 29: + return new Nodes.ClassVariableOrWriteNode(startOffset, length, loadConstant(), loadNode()); + case 30: + return new Nodes.ClassVariableReadNode(startOffset, length, loadConstant()); + case 31: + return new Nodes.ClassVariableTargetNode(startOffset, length, loadConstant()); + case 32: + return new Nodes.ClassVariableWriteNode(startOffset, length, loadConstant(), loadNode()); + case 33: + return new Nodes.ConstantAndWriteNode(startOffset, length, loadConstant(), loadNode()); + case 34: + return new Nodes.ConstantOperatorWriteNode(startOffset, length, loadConstant(), loadNode(), loadConstant()); + case 35: + return new Nodes.ConstantOrWriteNode(startOffset, length, loadConstant(), loadNode()); + case 36: + return new Nodes.ConstantPathAndWriteNode(startOffset, length, (Nodes.ConstantPathNode) loadNode(), loadNode()); + case 37: + return new Nodes.ConstantPathNode(startOffset, length, loadOptionalNode(), loadOptionalConstant()); + case 38: + return new Nodes.ConstantPathOperatorWriteNode(startOffset, length, (Nodes.ConstantPathNode) loadNode(), loadNode(), loadConstant()); + case 39: + return new Nodes.ConstantPathOrWriteNode(startOffset, length, (Nodes.ConstantPathNode) loadNode(), loadNode()); + case 40: + return new Nodes.ConstantPathTargetNode(startOffset, length, loadOptionalNode(), loadOptionalConstant()); + case 41: + return new Nodes.ConstantPathWriteNode(startOffset, length, (Nodes.ConstantPathNode) loadNode(), loadNode()); + case 42: + return new Nodes.ConstantReadNode(startOffset, length, loadConstant()); + case 43: + return new Nodes.ConstantTargetNode(startOffset, length, loadConstant()); + case 44: + return new Nodes.ConstantWriteNode(startOffset, length, loadConstant(), loadNode()); + case 45: + return loadDefNode(startOffset, length); + case 46: + return new Nodes.DefinedNode(startOffset, length, loadNode()); + case 47: + return new Nodes.ElseNode(startOffset, length, (Nodes.StatementsNode) loadOptionalNode()); + case 48: + return new Nodes.EmbeddedStatementsNode(startOffset, length, (Nodes.StatementsNode) loadOptionalNode()); + case 49: + return new Nodes.EmbeddedVariableNode(startOffset, length, loadNode()); + case 50: + return new Nodes.EnsureNode(startOffset, length, (Nodes.StatementsNode) loadOptionalNode()); + case 51: + return new Nodes.FalseNode(startOffset, length); + case 52: + return new Nodes.FindPatternNode(startOffset, length, loadOptionalNode(), (Nodes.SplatNode) loadNode(), loadNodes(), (Nodes.SplatNode) loadNode()); + case 53: + return new Nodes.FlipFlopNode(startOffset, length, loadFlags(), loadOptionalNode(), loadOptionalNode()); + case 54: + return new Nodes.FloatNode(startOffset, length, buffer.getDouble()); + case 55: + return new Nodes.ForNode(startOffset, length, loadNode(), loadNode(), (Nodes.StatementsNode) loadOptionalNode()); + case 56: + return new Nodes.ForwardingArgumentsNode(startOffset, length); + case 57: + return new Nodes.ForwardingParameterNode(startOffset, length); + case 58: + return new Nodes.ForwardingSuperNode(startOffset, length, (Nodes.BlockNode) loadOptionalNode()); + case 59: + return new Nodes.GlobalVariableAndWriteNode(startOffset, length, loadConstant(), loadNode()); + case 60: + return new Nodes.GlobalVariableOperatorWriteNode(startOffset, length, loadConstant(), loadNode(), loadConstant()); + case 61: + return new Nodes.GlobalVariableOrWriteNode(startOffset, length, loadConstant(), loadNode()); + case 62: + return new Nodes.GlobalVariableReadNode(startOffset, length, loadConstant()); + case 63: + return new Nodes.GlobalVariableTargetNode(startOffset, length, loadConstant()); + case 64: + return new Nodes.GlobalVariableWriteNode(startOffset, length, loadConstant(), loadNode()); + case 65: + return new Nodes.HashNode(startOffset, length, loadNodes()); + case 66: + return new Nodes.HashPatternNode(startOffset, length, loadOptionalNode(), loadAssocNodes(), loadOptionalNode()); + case 67: + return new Nodes.IfNode(startOffset, length, loadNode(), (Nodes.StatementsNode) loadOptionalNode(), loadOptionalNode()); + case 68: + return new Nodes.ImaginaryNode(startOffset, length, loadNode()); + case 69: + return new Nodes.ImplicitNode(startOffset, length, loadNode()); + case 70: + return new Nodes.ImplicitRestNode(startOffset, length); + case 71: + return new Nodes.InNode(startOffset, length, loadNode(), (Nodes.StatementsNode) loadOptionalNode()); + case 72: + return new Nodes.IndexAndWriteNode(startOffset, length, loadFlags(), loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), (Nodes.BlockArgumentNode) loadOptionalNode(), loadNode()); + case 73: + return new Nodes.IndexOperatorWriteNode(startOffset, length, loadFlags(), loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), (Nodes.BlockArgumentNode) loadOptionalNode(), loadConstant(), loadNode()); + case 74: + return new Nodes.IndexOrWriteNode(startOffset, length, loadFlags(), loadOptionalNode(), (Nodes.ArgumentsNode) loadOptionalNode(), (Nodes.BlockArgumentNode) loadOptionalNode(), loadNode()); + case 75: + return new Nodes.IndexTargetNode(startOffset, length, loadFlags(), loadNode(), (Nodes.ArgumentsNode) loadOptionalNode(), (Nodes.BlockArgumentNode) loadOptionalNode()); + case 76: + return new Nodes.InstanceVariableAndWriteNode(startOffset, length, loadConstant(), loadNode()); + case 77: + return new Nodes.InstanceVariableOperatorWriteNode(startOffset, length, loadConstant(), loadNode(), loadConstant()); + case 78: + return new Nodes.InstanceVariableOrWriteNode(startOffset, length, loadConstant(), loadNode()); + case 79: + return new Nodes.InstanceVariableReadNode(startOffset, length, loadConstant()); + case 80: + return new Nodes.InstanceVariableTargetNode(startOffset, length, loadConstant()); + case 81: + return new Nodes.InstanceVariableWriteNode(startOffset, length, loadConstant(), loadNode()); + case 82: + return new Nodes.IntegerNode(startOffset, length, loadFlags(), loadInteger()); + case 83: + return new Nodes.InterpolatedMatchLastLineNode(startOffset, length, loadFlags(), loadNodes()); + case 84: + return new Nodes.InterpolatedRegularExpressionNode(startOffset, length, loadFlags(), loadNodes()); + case 85: + return new Nodes.InterpolatedStringNode(startOffset, length, loadFlags(), loadNodes()); + case 86: + return new Nodes.InterpolatedSymbolNode(startOffset, length, loadNodes()); + case 87: + return new Nodes.InterpolatedXStringNode(startOffset, length, loadNodes()); + case 88: + return new Nodes.ItLocalVariableReadNode(startOffset, length); + case 89: + return new Nodes.ItParametersNode(startOffset, length); + case 90: + return new Nodes.KeywordHashNode(startOffset, length, loadFlags(), loadNodes()); + case 91: + return new Nodes.KeywordRestParameterNode(startOffset, length, loadFlags(), loadOptionalConstant()); + case 92: + return new Nodes.LambdaNode(startOffset, length, loadConstants(), loadOptionalNode(), loadOptionalNode()); + case 93: + return new Nodes.LocalVariableAndWriteNode(startOffset, length, loadNode(), loadConstant(), loadVarUInt()); + case 94: + return new Nodes.LocalVariableOperatorWriteNode(startOffset, length, loadNode(), loadConstant(), loadConstant(), loadVarUInt()); + case 95: + return new Nodes.LocalVariableOrWriteNode(startOffset, length, loadNode(), loadConstant(), loadVarUInt()); + case 96: + return new Nodes.LocalVariableReadNode(startOffset, length, loadConstant(), loadVarUInt()); + case 97: + return new Nodes.LocalVariableTargetNode(startOffset, length, loadConstant(), loadVarUInt()); + case 98: + return new Nodes.LocalVariableWriteNode(startOffset, length, loadConstant(), loadVarUInt(), loadNode()); + case 99: + return new Nodes.MatchLastLineNode(startOffset, length, loadFlags(), loadString()); + case 100: + return new Nodes.MatchPredicateNode(startOffset, length, loadNode(), loadNode()); + case 101: + return new Nodes.MatchRequiredNode(startOffset, length, loadNode(), loadNode()); + case 102: + return new Nodes.MatchWriteNode(startOffset, length, (Nodes.CallNode) loadNode(), loadLocalVariableTargetNodes()); + case 103: + return new Nodes.MissingNode(startOffset, length); + case 104: + return new Nodes.ModuleNode(startOffset, length, loadConstants(), loadNode(), loadOptionalNode(), loadConstant()); + case 105: + return new Nodes.MultiTargetNode(startOffset, length, loadNodes(), loadOptionalNode(), loadNodes()); + case 106: + return new Nodes.MultiWriteNode(startOffset, length, loadNodes(), loadOptionalNode(), loadNodes(), loadNode()); + case 107: + return new Nodes.NextNode(startOffset, length, (Nodes.ArgumentsNode) loadOptionalNode()); + case 108: + return new Nodes.NilNode(startOffset, length); + case 109: + return new Nodes.NoBlockParameterNode(startOffset, length); + case 110: + return new Nodes.NoKeywordsParameterNode(startOffset, length); + case 111: + return new Nodes.NumberedParametersNode(startOffset, length, buffer.get()); + case 112: + return new Nodes.NumberedReferenceReadNode(startOffset, length, loadVarUInt()); + case 113: + return new Nodes.OptionalKeywordParameterNode(startOffset, length, loadFlags(), loadConstant(), loadNode()); + case 114: + return new Nodes.OptionalParameterNode(startOffset, length, loadFlags(), loadConstant(), loadNode()); + case 115: + return new Nodes.OrNode(startOffset, length, loadNode(), loadNode()); + case 116: + return new Nodes.ParametersNode(startOffset, length, loadNodes(), loadOptionalParameterNodes(), loadOptionalNode(), loadNodes(), loadNodes(), loadOptionalNode(), loadOptionalNode()); + case 117: + return new Nodes.ParenthesesNode(startOffset, length, loadFlags(), loadOptionalNode()); + case 118: + return new Nodes.PinnedExpressionNode(startOffset, length, loadNode()); + case 119: + return new Nodes.PinnedVariableNode(startOffset, length, loadNode()); + case 120: + return new Nodes.PostExecutionNode(startOffset, length, (Nodes.StatementsNode) loadOptionalNode()); + case 121: + return new Nodes.PreExecutionNode(startOffset, length, (Nodes.StatementsNode) loadOptionalNode()); + case 122: + return new Nodes.ProgramNode(startOffset, length, loadConstants(), (Nodes.StatementsNode) loadNode()); + case 123: + return new Nodes.RangeNode(startOffset, length, loadFlags(), loadOptionalNode(), loadOptionalNode()); + case 124: + return new Nodes.RationalNode(startOffset, length, loadFlags(), loadInteger(), loadInteger()); + case 125: + return new Nodes.RedoNode(startOffset, length); + case 126: + return new Nodes.RegularExpressionNode(startOffset, length, loadFlags(), loadString()); + case 127: + return new Nodes.RequiredKeywordParameterNode(startOffset, length, loadFlags(), loadConstant()); + case 128: + return new Nodes.RequiredParameterNode(startOffset, length, loadFlags(), loadConstant()); + case 129: + return new Nodes.RescueModifierNode(startOffset, length, loadNode(), loadNode()); + case 130: + return new Nodes.RescueNode(startOffset, length, loadNodes(), loadOptionalNode(), (Nodes.StatementsNode) loadOptionalNode(), (Nodes.RescueNode) loadOptionalNode()); + case 131: + return new Nodes.RestParameterNode(startOffset, length, loadFlags(), loadOptionalConstant()); + case 132: + return new Nodes.RetryNode(startOffset, length); + case 133: + return new Nodes.ReturnNode(startOffset, length, (Nodes.ArgumentsNode) loadOptionalNode()); + case 134: + return new Nodes.SelfNode(startOffset, length); + case 135: + return new Nodes.ShareableConstantNode(startOffset, length, loadFlags(), loadNode()); + case 136: + return new Nodes.SingletonClassNode(startOffset, length, loadConstants(), loadNode(), loadOptionalNode()); + case 137: + return new Nodes.SourceEncodingNode(startOffset, length); + case 138: + return new Nodes.SourceFileNode(startOffset, length, loadFlags(), loadString()); + case 139: + return new Nodes.SourceLineNode(startOffset, length); + case 140: + return new Nodes.SplatNode(startOffset, length, loadOptionalNode()); + case 141: + return new Nodes.StatementsNode(startOffset, length, loadNodes()); + case 142: + return new Nodes.StringNode(startOffset, length, loadFlags(), loadString()); + case 143: + return new Nodes.SuperNode(startOffset, length, (Nodes.ArgumentsNode) loadOptionalNode(), loadOptionalNode()); + case 144: + return new Nodes.SymbolNode(startOffset, length, loadFlags(), loadString()); + case 145: + return new Nodes.TrueNode(startOffset, length); + case 146: + return new Nodes.UndefNode(startOffset, length, loadNodes()); + case 147: + return new Nodes.UnlessNode(startOffset, length, loadNode(), (Nodes.StatementsNode) loadOptionalNode(), (Nodes.ElseNode) loadOptionalNode()); + case 148: + return new Nodes.UntilNode(startOffset, length, loadFlags(), loadNode(), (Nodes.StatementsNode) loadOptionalNode()); + case 149: + return new Nodes.WhenNode(startOffset, length, loadNodes(), (Nodes.StatementsNode) loadOptionalNode()); + case 150: + return new Nodes.WhileNode(startOffset, length, loadFlags(), loadNode(), (Nodes.StatementsNode) loadOptionalNode()); + case 151: + return new Nodes.XStringNode(startOffset, length, loadFlags(), loadString()); + case 152: + return new Nodes.YieldNode(startOffset, length, (Nodes.ArgumentsNode) loadOptionalNode()); + default: + throw new Error("Unknown node type: " + type); + } + } + + // Can be overridden to use createLazyDefNode instead + protected Nodes.DefNode loadDefNode(int startOffset, int length) { + return createDefNode(startOffset, length); + } + + protected Nodes.DefNode createLazyDefNode(int startOffset, int length) { + int bufferPosition = buffer.position(); + int serializedLength = buffer.getInt(); + // Load everything except the body and locals, because the name, receiver, parameters are still needed for lazily defining the method + Nodes.DefNode lazyDefNode = new Nodes.DefNode(startOffset, length, -bufferPosition, this, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), null, Nodes.EMPTY_IDENTIFIER_ARRAY); + buffer.position(bufferPosition + serializedLength); // skip past the serialized DefNode + return lazyDefNode; + } + + protected Nodes.DefNode createDefNode(int startOffset, int length) { + return new Nodes.DefNode(startOffset, length, buffer.getInt(), null, loadConstant(), loadOptionalNode(), (Nodes.ParametersNode) loadOptionalNode(), loadOptionalNode(), loadConstants()); + } + + Nodes.DefNode createDefNodeFromSavedPosition(int startOffset, int length, int bufferPosition) { + Nodes.DefNode node; + // This method mutates the buffer position and may be called from different threads so we must synchronize + synchronized (this) { + buffer.position(bufferPosition); + node = createDefNode(startOffset, length); + } + + MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source); + node.accept(visitor); + + return node; + } + + private static final Nodes.Node[] EMPTY_Node_ARRAY = {}; + + private Nodes.Node[] loadNodes() { + int length = loadVarUInt(); + if (length == 0) { + return EMPTY_Node_ARRAY; + } + Nodes.Node[] nodes = new Nodes.Node[length]; + for (int i = 0; i < length; i++) { + nodes[i] = loadNode(); + } + return nodes; + } + + private static final Nodes.BlockLocalVariableNode[] EMPTY_BlockLocalVariableNode_ARRAY = {}; + + private Nodes.BlockLocalVariableNode[] loadBlockLocalVariableNodes() { + int length = loadVarUInt(); + if (length == 0) { + return EMPTY_BlockLocalVariableNode_ARRAY; + } + Nodes.BlockLocalVariableNode[] nodes = new Nodes.BlockLocalVariableNode[length]; + for (int i = 0; i < length; i++) { + nodes[i] = (Nodes.BlockLocalVariableNode) loadNode(); + } + return nodes; + } + + private static final Nodes.InNode[] EMPTY_InNode_ARRAY = {}; + + private Nodes.InNode[] loadInNodes() { + int length = loadVarUInt(); + if (length == 0) { + return EMPTY_InNode_ARRAY; + } + Nodes.InNode[] nodes = new Nodes.InNode[length]; + for (int i = 0; i < length; i++) { + nodes[i] = (Nodes.InNode) loadNode(); + } + return nodes; + } + + private static final Nodes.WhenNode[] EMPTY_WhenNode_ARRAY = {}; + + private Nodes.WhenNode[] loadWhenNodes() { + int length = loadVarUInt(); + if (length == 0) { + return EMPTY_WhenNode_ARRAY; + } + Nodes.WhenNode[] nodes = new Nodes.WhenNode[length]; + for (int i = 0; i < length; i++) { + nodes[i] = (Nodes.WhenNode) loadNode(); + } + return nodes; + } + + private static final Nodes.AssocNode[] EMPTY_AssocNode_ARRAY = {}; + + private Nodes.AssocNode[] loadAssocNodes() { + int length = loadVarUInt(); + if (length == 0) { + return EMPTY_AssocNode_ARRAY; + } + Nodes.AssocNode[] nodes = new Nodes.AssocNode[length]; + for (int i = 0; i < length; i++) { + nodes[i] = (Nodes.AssocNode) loadNode(); + } + return nodes; + } + + private static final Nodes.LocalVariableTargetNode[] EMPTY_LocalVariableTargetNode_ARRAY = {}; + + private Nodes.LocalVariableTargetNode[] loadLocalVariableTargetNodes() { + int length = loadVarUInt(); + if (length == 0) { + return EMPTY_LocalVariableTargetNode_ARRAY; + } + Nodes.LocalVariableTargetNode[] nodes = new Nodes.LocalVariableTargetNode[length]; + for (int i = 0; i < length; i++) { + nodes[i] = (Nodes.LocalVariableTargetNode) loadNode(); + } + return nodes; + } + + private static final Nodes.OptionalParameterNode[] EMPTY_OptionalParameterNode_ARRAY = {}; + + private Nodes.OptionalParameterNode[] loadOptionalParameterNodes() { + int length = loadVarUInt(); + if (length == 0) { + return EMPTY_OptionalParameterNode_ARRAY; + } + Nodes.OptionalParameterNode[] nodes = new Nodes.OptionalParameterNode[length]; + for (int i = 0; i < length; i++) { + nodes[i] = (Nodes.OptionalParameterNode) loadNode(); + } + return nodes; + } + + private void expect(byte value, String error) { + byte b = buffer.get(); + if (b != value) { + throw new Error("Deserialization error: " + error + " (expected " + value + " but was " + b + " at position " + buffer.position() + ")"); + } + } + +} +// @formatter:on diff --git a/java/org/ruby_lang/prism/MarkNewlinesVisitor.java b/java/api/src/main/java/org/ruby_lang/prism/MarkNewlinesVisitor.java similarity index 100% rename from java/org/ruby_lang/prism/MarkNewlinesVisitor.java rename to java/api/src/main/java/org/ruby_lang/prism/MarkNewlinesVisitor.java diff --git a/java/api/src/main/java/org/ruby_lang/prism/Nodes.java b/java/api/src/main/java/org/ruby_lang/prism/Nodes.java new file mode 100644 index 0000000000..8f032d5fa0 --- /dev/null +++ b/java/api/src/main/java/org/ruby_lang/prism/Nodes.java @@ -0,0 +1,11628 @@ +/*----------------------------------------------------------------------------*/ +/* This file is generated by the templates/template.rb script and should not */ +/* be modified manually. See */ +/* templates/java/org/ruby_lang/prism/Nodes.java.erb */ +/* if you are looking to modify the */ +/* template */ +/*----------------------------------------------------------------------------*/ + +package org.ruby_lang.prism; + +import java.lang.Override; +import java.lang.String; +import java.lang.StringBuilder; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; + +// GENERATED BY Nodes.java.erb +// @formatter:off +public abstract class Nodes { + + public static final byte[][] EMPTY_IDENTIFIER_ARRAY = {}; + + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface Nullable { + } + + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface UnionType { + Class[] value(); + } + + public static final class Location { + + public static final Location[] EMPTY_ARRAY = {}; + + public final int startOffset; + public final int length; + + public Location(int startOffset, int length) { + this.startOffset = startOffset; + this.length = length; + } + + public int endOffset() { + return startOffset + length; + } + } + + public static final class Source { + private int startLine = 1; + private int[] lineOffsets = null; + + Source() { + } + + void setStartLine(int startLine) { + this.startLine = startLine; + } + + void setLineOffsets(int[] lineOffsets) { + this.lineOffsets = lineOffsets; + } + + // 1-based + public int line(int byteOffset) { + return startLine + findLine(byteOffset); + } + + // 0-based + public int findLine(int byteOffset) { + assert byteOffset >= 0 : byteOffset; + int index = Arrays.binarySearch(lineOffsets, byteOffset); + int line; + if (index < 0) { + line = -index - 2; + } else { + line = index; + } + assert line >= 0 && line <= getLineCount() : line; + return line; + } + + public int getLineCount() { + return lineOffsets.length; + } + } + + public static abstract class Node { + + public static final Node[] EMPTY_ARRAY = {}; + + public final int startOffset; + public final int length; + private boolean newLineFlag = false; + + public Node(int startOffset, int length) { + this.startOffset = startOffset; + this.length = length; + } + + public final int endOffset() { + return startOffset + length; + } + + public final boolean hasNewLineFlag() { + return newLineFlag; + } + + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + int line = source.findLine(this.startOffset); + if (!newlineMarked[line]) { + newlineMarked[line] = true; + this.newLineFlag = true; + } + } + + public void setNewLineFlag(boolean newLineFlag) { + this.newLineFlag = newLineFlag; + } + + public abstract T accept(AbstractNodeVisitor visitor); + + public abstract void visitChildNodes(AbstractNodeVisitor visitor); + + public abstract Node[] childNodes(); + + @Override + public String toString() { + return toString(""); + } + + protected abstract String toString(String indent); + } + + protected static String asString(Object value) { + return value.toString(); + } + + protected static String asString(byte[] value) { + StringBuilder buf = new StringBuilder(value.length); + for (byte b : value) { + if (b >= 0x20 && b <= 0x7e) { + buf.append((char) b); + } else { + buf.append(String.format("\\x%02x", Byte.toUnsignedInt(b))); + } + } + return buf.toString(); + } + + /** + * Flags for arguments nodes. + */ + public static final class ArgumentsNodeFlags implements Comparable { + + // if the arguments contain forwarding + public static final short CONTAINS_FORWARDING = 1 << 2; + + // if the arguments contain keywords + public static final short CONTAINS_KEYWORDS = 1 << 3; + + // if the arguments contain a keyword splat + public static final short CONTAINS_KEYWORD_SPLAT = 1 << 4; + + // if the arguments contain a splat + public static final short CONTAINS_SPLAT = 1 << 5; + + // if the arguments contain multiple splats + public static final short CONTAINS_MULTIPLE_SPLATS = 1 << 6; + + public static boolean isContainsForwarding(short flags) { + return (flags & CONTAINS_FORWARDING) != 0; + } + + public static boolean isContainsKeywords(short flags) { + return (flags & CONTAINS_KEYWORDS) != 0; + } + + public static boolean isContainsKeywordSplat(short flags) { + return (flags & CONTAINS_KEYWORD_SPLAT) != 0; + } + + public static boolean isContainsSplat(short flags) { + return (flags & CONTAINS_SPLAT) != 0; + } + + public static boolean isContainsMultipleSplats(short flags) { + return (flags & CONTAINS_MULTIPLE_SPLATS) != 0; + } + + private final short flags; + + public ArgumentsNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ArgumentsNodeFlags)) { + return false; + } + + return flags == ((ArgumentsNodeFlags) other).flags; + } + + @Override + public int compareTo(ArgumentsNodeFlags other) { + return flags - other.flags; + } + + public boolean isContainsForwarding() { + return (flags & CONTAINS_FORWARDING) != 0; + } + + public boolean isContainsKeywords() { + return (flags & CONTAINS_KEYWORDS) != 0; + } + + public boolean isContainsKeywordSplat() { + return (flags & CONTAINS_KEYWORD_SPLAT) != 0; + } + + public boolean isContainsSplat() { + return (flags & CONTAINS_SPLAT) != 0; + } + + public boolean isContainsMultipleSplats() { + return (flags & CONTAINS_MULTIPLE_SPLATS) != 0; + } + + } + + /** + * Flags for array nodes. + */ + public static final class ArrayNodeFlags implements Comparable { + + // if array contains splat nodes + public static final short CONTAINS_SPLAT = 1 << 2; + + public static boolean isContainsSplat(short flags) { + return (flags & CONTAINS_SPLAT) != 0; + } + + private final short flags; + + public ArrayNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ArrayNodeFlags)) { + return false; + } + + return flags == ((ArrayNodeFlags) other).flags; + } + + @Override + public int compareTo(ArrayNodeFlags other) { + return flags - other.flags; + } + + public boolean isContainsSplat() { + return (flags & CONTAINS_SPLAT) != 0; + } + + } + + /** + * Flags for call nodes. + */ + public static final class CallNodeFlags implements Comparable { + + // &. operator + public static final short SAFE_NAVIGATION = 1 << 2; + + // a call that could have been a local variable + public static final short VARIABLE_CALL = 1 << 3; + + // a call that is an attribute write, so the value being written should be returned + public static final short ATTRIBUTE_WRITE = 1 << 4; + + // a call that ignores method visibility + public static final short IGNORE_VISIBILITY = 1 << 5; + + public static boolean isSafeNavigation(short flags) { + return (flags & SAFE_NAVIGATION) != 0; + } + + public static boolean isVariableCall(short flags) { + return (flags & VARIABLE_CALL) != 0; + } + + public static boolean isAttributeWrite(short flags) { + return (flags & ATTRIBUTE_WRITE) != 0; + } + + public static boolean isIgnoreVisibility(short flags) { + return (flags & IGNORE_VISIBILITY) != 0; + } + + private final short flags; + + public CallNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof CallNodeFlags)) { + return false; + } + + return flags == ((CallNodeFlags) other).flags; + } + + @Override + public int compareTo(CallNodeFlags other) { + return flags - other.flags; + } + + public boolean isSafeNavigation() { + return (flags & SAFE_NAVIGATION) != 0; + } + + public boolean isVariableCall() { + return (flags & VARIABLE_CALL) != 0; + } + + public boolean isAttributeWrite() { + return (flags & ATTRIBUTE_WRITE) != 0; + } + + public boolean isIgnoreVisibility() { + return (flags & IGNORE_VISIBILITY) != 0; + } + + } + + /** + * Flags for nodes that have unescaped content. + */ + public static final class EncodingFlags implements Comparable { + + // internal bytes forced the encoding to UTF-8 + public static final short FORCED_UTF8_ENCODING = 1 << 2; + + // internal bytes forced the encoding to binary + public static final short FORCED_BINARY_ENCODING = 1 << 3; + + public static boolean isForcedUtf8Encoding(short flags) { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public static boolean isForcedBinaryEncoding(short flags) { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + private final short flags; + + public EncodingFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof EncodingFlags)) { + return false; + } + + return flags == ((EncodingFlags) other).flags; + } + + @Override + public int compareTo(EncodingFlags other) { + return flags - other.flags; + } + + public boolean isForcedUtf8Encoding() { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public boolean isForcedBinaryEncoding() { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + } + + /** + * Flags for integer nodes that correspond to the base of the integer. + */ + public static final class IntegerBaseFlags implements Comparable { + + // 0b prefix + public static final short BINARY = 1 << 2; + + // 0d or no prefix + public static final short DECIMAL = 1 << 3; + + // 0o or 0 prefix + public static final short OCTAL = 1 << 4; + + // 0x prefix + public static final short HEXADECIMAL = 1 << 5; + + public static boolean isBinary(short flags) { + return (flags & BINARY) != 0; + } + + public static boolean isDecimal(short flags) { + return (flags & DECIMAL) != 0; + } + + public static boolean isOctal(short flags) { + return (flags & OCTAL) != 0; + } + + public static boolean isHexadecimal(short flags) { + return (flags & HEXADECIMAL) != 0; + } + + private final short flags; + + public IntegerBaseFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof IntegerBaseFlags)) { + return false; + } + + return flags == ((IntegerBaseFlags) other).flags; + } + + @Override + public int compareTo(IntegerBaseFlags other) { + return flags - other.flags; + } + + public boolean isBinary() { + return (flags & BINARY) != 0; + } + + public boolean isDecimal() { + return (flags & DECIMAL) != 0; + } + + public boolean isOctal() { + return (flags & OCTAL) != 0; + } + + public boolean isHexadecimal() { + return (flags & HEXADECIMAL) != 0; + } + + } + + /** + * Flags for interpolated string nodes that indicated mutability if they are also marked as literals. + */ + public static final class InterpolatedStringNodeFlags implements Comparable { + + // frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + public static final short FROZEN = 1 << 2; + + // mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal`; only for adjacent string literals like `'a' 'b'` + public static final short MUTABLE = 1 << 3; + + public static boolean isFrozen(short flags) { + return (flags & FROZEN) != 0; + } + + public static boolean isMutable(short flags) { + return (flags & MUTABLE) != 0; + } + + private final short flags; + + public InterpolatedStringNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof InterpolatedStringNodeFlags)) { + return false; + } + + return flags == ((InterpolatedStringNodeFlags) other).flags; + } + + @Override + public int compareTo(InterpolatedStringNodeFlags other) { + return flags - other.flags; + } + + public boolean isFrozen() { + return (flags & FROZEN) != 0; + } + + public boolean isMutable() { + return (flags & MUTABLE) != 0; + } + + } + + /** + * Flags for keyword hash nodes. + */ + public static final class KeywordHashNodeFlags implements Comparable { + + // a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments + public static final short SYMBOL_KEYS = 1 << 2; + + public static boolean isSymbolKeys(short flags) { + return (flags & SYMBOL_KEYS) != 0; + } + + private final short flags; + + public KeywordHashNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof KeywordHashNodeFlags)) { + return false; + } + + return flags == ((KeywordHashNodeFlags) other).flags; + } + + @Override + public int compareTo(KeywordHashNodeFlags other) { + return flags - other.flags; + } + + public boolean isSymbolKeys() { + return (flags & SYMBOL_KEYS) != 0; + } + + } + + /** + * Flags for while and until loop nodes. + */ + public static final class LoopFlags implements Comparable { + + // a loop after a begin statement, so the body is executed first before the condition + public static final short BEGIN_MODIFIER = 1 << 2; + + public static boolean isBeginModifier(short flags) { + return (flags & BEGIN_MODIFIER) != 0; + } + + private final short flags; + + public LoopFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof LoopFlags)) { + return false; + } + + return flags == ((LoopFlags) other).flags; + } + + @Override + public int compareTo(LoopFlags other) { + return flags - other.flags; + } + + public boolean isBeginModifier() { + return (flags & BEGIN_MODIFIER) != 0; + } + + } + + /** + * Flags for parameter nodes. + */ + public static final class ParameterFlags implements Comparable { + + // a parameter name that has been repeated in the method signature + public static final short REPEATED_PARAMETER = 1 << 2; + + public static boolean isRepeatedParameter(short flags) { + return (flags & REPEATED_PARAMETER) != 0; + } + + private final short flags; + + public ParameterFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ParameterFlags)) { + return false; + } + + return flags == ((ParameterFlags) other).flags; + } + + @Override + public int compareTo(ParameterFlags other) { + return flags - other.flags; + } + + public boolean isRepeatedParameter() { + return (flags & REPEATED_PARAMETER) != 0; + } + + } + + /** + * Flags for parentheses nodes. + */ + public static final class ParenthesesNodeFlags implements Comparable { + + // parentheses that contain multiple potentially void statements + public static final short MULTIPLE_STATEMENTS = 1 << 2; + + public static boolean isMultipleStatements(short flags) { + return (flags & MULTIPLE_STATEMENTS) != 0; + } + + private final short flags; + + public ParenthesesNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ParenthesesNodeFlags)) { + return false; + } + + return flags == ((ParenthesesNodeFlags) other).flags; + } + + @Override + public int compareTo(ParenthesesNodeFlags other) { + return flags - other.flags; + } + + public boolean isMultipleStatements() { + return (flags & MULTIPLE_STATEMENTS) != 0; + } + + } + + /** + * Flags for range and flip-flop nodes. + */ + public static final class RangeFlags implements Comparable { + + // ... operator + public static final short EXCLUDE_END = 1 << 2; + + public static boolean isExcludeEnd(short flags) { + return (flags & EXCLUDE_END) != 0; + } + + private final short flags; + + public RangeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof RangeFlags)) { + return false; + } + + return flags == ((RangeFlags) other).flags; + } + + @Override + public int compareTo(RangeFlags other) { + return flags - other.flags; + } + + public boolean isExcludeEnd() { + return (flags & EXCLUDE_END) != 0; + } + + } + + /** + * Flags for regular expression and match last line nodes. + */ + public static final class RegularExpressionFlags implements Comparable { + + // i - ignores the case of characters when matching + public static final short IGNORE_CASE = 1 << 2; + + // x - ignores whitespace and allows comments in regular expressions + public static final short EXTENDED = 1 << 3; + + // m - allows $ to match the end of lines within strings + public static final short MULTI_LINE = 1 << 4; + + // o - only interpolates values into the regular expression once + public static final short ONCE = 1 << 5; + + // e - forces the EUC-JP encoding + public static final short EUC_JP = 1 << 6; + + // n - forces the ASCII-8BIT encoding + public static final short ASCII_8BIT = 1 << 7; + + // s - forces the Windows-31J encoding + public static final short WINDOWS_31J = 1 << 8; + + // u - forces the UTF-8 encoding + public static final short UTF_8 = 1 << 9; + + // internal bytes forced the encoding to UTF-8 + public static final short FORCED_UTF8_ENCODING = 1 << 10; + + // internal bytes forced the encoding to binary + public static final short FORCED_BINARY_ENCODING = 1 << 11; + + // internal bytes forced the encoding to US-ASCII + public static final short FORCED_US_ASCII_ENCODING = 1 << 12; + + public static boolean isIgnoreCase(short flags) { + return (flags & IGNORE_CASE) != 0; + } + + public static boolean isExtended(short flags) { + return (flags & EXTENDED) != 0; + } + + public static boolean isMultiLine(short flags) { + return (flags & MULTI_LINE) != 0; + } + + public static boolean isOnce(short flags) { + return (flags & ONCE) != 0; + } + + public static boolean isEucJp(short flags) { + return (flags & EUC_JP) != 0; + } + + public static boolean isAscii8bit(short flags) { + return (flags & ASCII_8BIT) != 0; + } + + public static boolean isWindows31j(short flags) { + return (flags & WINDOWS_31J) != 0; + } + + public static boolean isUtf8(short flags) { + return (flags & UTF_8) != 0; + } + + public static boolean isForcedUtf8Encoding(short flags) { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public static boolean isForcedBinaryEncoding(short flags) { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + public static boolean isForcedUsAsciiEncoding(short flags) { + return (flags & FORCED_US_ASCII_ENCODING) != 0; + } + + private final short flags; + + public RegularExpressionFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof RegularExpressionFlags)) { + return false; + } + + return flags == ((RegularExpressionFlags) other).flags; + } + + @Override + public int compareTo(RegularExpressionFlags other) { + return flags - other.flags; + } + + public boolean isIgnoreCase() { + return (flags & IGNORE_CASE) != 0; + } + + public boolean isExtended() { + return (flags & EXTENDED) != 0; + } + + public boolean isMultiLine() { + return (flags & MULTI_LINE) != 0; + } + + public boolean isOnce() { + return (flags & ONCE) != 0; + } + + public boolean isEucJp() { + return (flags & EUC_JP) != 0; + } + + public boolean isAscii8bit() { + return (flags & ASCII_8BIT) != 0; + } + + public boolean isWindows31j() { + return (flags & WINDOWS_31J) != 0; + } + + public boolean isUtf8() { + return (flags & UTF_8) != 0; + } + + public boolean isForcedUtf8Encoding() { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public boolean isForcedBinaryEncoding() { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + public boolean isForcedUsAsciiEncoding() { + return (flags & FORCED_US_ASCII_ENCODING) != 0; + } + + } + + /** + * Flags for shareable constant nodes. + */ + public static final class ShareableConstantNodeFlags implements Comparable { + + // constant writes that should be modified with shareable constant value literal + public static final short LITERAL = 1 << 2; + + // constant writes that should be modified with shareable constant value experimental everything + public static final short EXPERIMENTAL_EVERYTHING = 1 << 3; + + // constant writes that should be modified with shareable constant value experimental copy + public static final short EXPERIMENTAL_COPY = 1 << 4; + + public static boolean isLiteral(short flags) { + return (flags & LITERAL) != 0; + } + + public static boolean isExperimentalEverything(short flags) { + return (flags & EXPERIMENTAL_EVERYTHING) != 0; + } + + public static boolean isExperimentalCopy(short flags) { + return (flags & EXPERIMENTAL_COPY) != 0; + } + + private final short flags; + + public ShareableConstantNodeFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof ShareableConstantNodeFlags)) { + return false; + } + + return flags == ((ShareableConstantNodeFlags) other).flags; + } + + @Override + public int compareTo(ShareableConstantNodeFlags other) { + return flags - other.flags; + } + + public boolean isLiteral() { + return (flags & LITERAL) != 0; + } + + public boolean isExperimentalEverything() { + return (flags & EXPERIMENTAL_EVERYTHING) != 0; + } + + public boolean isExperimentalCopy() { + return (flags & EXPERIMENTAL_COPY) != 0; + } + + } + + /** + * Flags for string nodes. + */ + public static final class StringFlags implements Comparable { + + // internal bytes forced the encoding to UTF-8 + public static final short FORCED_UTF8_ENCODING = 1 << 2; + + // internal bytes forced the encoding to binary + public static final short FORCED_BINARY_ENCODING = 1 << 3; + + // frozen by virtue of a `frozen_string_literal: true` comment or `--enable-frozen-string-literal` + public static final short FROZEN = 1 << 4; + + // mutable by virtue of a `frozen_string_literal: false` comment or `--disable-frozen-string-literal` + public static final short MUTABLE = 1 << 5; + + public static boolean isForcedUtf8Encoding(short flags) { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public static boolean isForcedBinaryEncoding(short flags) { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + public static boolean isFrozen(short flags) { + return (flags & FROZEN) != 0; + } + + public static boolean isMutable(short flags) { + return (flags & MUTABLE) != 0; + } + + private final short flags; + + public StringFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof StringFlags)) { + return false; + } + + return flags == ((StringFlags) other).flags; + } + + @Override + public int compareTo(StringFlags other) { + return flags - other.flags; + } + + public boolean isForcedUtf8Encoding() { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public boolean isForcedBinaryEncoding() { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + public boolean isFrozen() { + return (flags & FROZEN) != 0; + } + + public boolean isMutable() { + return (flags & MUTABLE) != 0; + } + + } + + /** + * Flags for symbol nodes. + */ + public static final class SymbolFlags implements Comparable { + + // internal bytes forced the encoding to UTF-8 + public static final short FORCED_UTF8_ENCODING = 1 << 2; + + // internal bytes forced the encoding to binary + public static final short FORCED_BINARY_ENCODING = 1 << 3; + + // internal bytes forced the encoding to US-ASCII + public static final short FORCED_US_ASCII_ENCODING = 1 << 4; + + public static boolean isForcedUtf8Encoding(short flags) { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public static boolean isForcedBinaryEncoding(short flags) { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + public static boolean isForcedUsAsciiEncoding(short flags) { + return (flags & FORCED_US_ASCII_ENCODING) != 0; + } + + private final short flags; + + public SymbolFlags(short flags) { + this.flags = flags; + } + + @Override + public int hashCode() { + return flags; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof SymbolFlags)) { + return false; + } + + return flags == ((SymbolFlags) other).flags; + } + + @Override + public int compareTo(SymbolFlags other) { + return flags - other.flags; + } + + public boolean isForcedUtf8Encoding() { + return (flags & FORCED_UTF8_ENCODING) != 0; + } + + public boolean isForcedBinaryEncoding() { + return (flags & FORCED_BINARY_ENCODING) != 0; + } + + public boolean isForcedUsAsciiEncoding() { + return (flags & FORCED_US_ASCII_ENCODING) != 0; + } + + } + + /** + *
+     * Represents the use of the `alias` keyword to alias a global variable.
+     *
+     *     alias $foo $bar
+     *     ^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class AliasGlobalVariableNode extends Node { + /** + *
+         * Represents the new name of the global variable that can be used after aliasing.
+         *
+         *     alias $foo $bar
+         *           ^^^^
+         * 
+ */ + @UnionType({ GlobalVariableReadNode.class, BackReferenceReadNode.class, NumberedReferenceReadNode.class }) + public final Node new_name; + /** + *
+         * Represents the old name of the global variable that can be used before aliasing.
+         *
+         *     alias $foo $bar
+         *                ^^^^
+         * 
+ */ + @UnionType({ GlobalVariableReadNode.class, BackReferenceReadNode.class, NumberedReferenceReadNode.class }) + public final Node old_name; + + public AliasGlobalVariableNode(int startOffset, int length, Node new_name, Node old_name) { + super(startOffset, length); + this.new_name = new_name; + this.old_name = old_name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.new_name.accept(visitor); + this.old_name.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.new_name, this.old_name }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitAliasGlobalVariableNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("new_name: "); + builder.append(this.new_name.toString(nextIndent)); + builder.append(nextIndent); + builder.append("old_name: "); + builder.append(this.old_name.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `alias` keyword to alias a method.
+     *
+     *     alias foo bar
+     *     ^^^^^^^^^^^^^
+     * 
+ */ + public static final class AliasMethodNode extends Node { + /** + *
+         * Represents the new name of the method that will be aliased.
+         *
+         *     alias foo bar
+         *           ^^^
+         *
+         *     alias :foo :bar
+         *           ^^^^
+         *
+         *     alias :"#{foo}" :"#{bar}"
+         *           ^^^^^^^^^
+         * 
+ */ + @UnionType({ SymbolNode.class, InterpolatedSymbolNode.class }) + public final Node new_name; + /** + *
+         * Represents the old name of the method that will be aliased.
+         *
+         *     alias foo bar
+         *               ^^^
+         *
+         *     alias :foo :bar
+         *                ^^^^
+         *
+         *     alias :"#{foo}" :"#{bar}"
+         *                     ^^^^^^^^^
+         * 
+ */ + @UnionType({ SymbolNode.class, InterpolatedSymbolNode.class }) + public final Node old_name; + + public AliasMethodNode(int startOffset, int length, Node new_name, Node old_name) { + super(startOffset, length); + this.new_name = new_name; + this.old_name = old_name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.new_name.accept(visitor); + this.old_name.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.new_name, this.old_name }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitAliasMethodNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("new_name: "); + builder.append(this.new_name.toString(nextIndent)); + builder.append(nextIndent); + builder.append("old_name: "); + builder.append(this.old_name.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an alternation pattern in pattern matching.
+     *
+     *     foo => bar | baz
+     *            ^^^^^^^^^
+     * 
+ */ + public static final class AlternationPatternNode extends Node { + /** + *
+         * Represents the left side of the expression.
+         *
+         *     foo => bar | baz
+         *            ^^^
+         * 
+ */ + public final Node left; + /** + *
+         * Represents the right side of the expression.
+         *
+         *     foo => bar | baz
+         *                  ^^^
+         * 
+ */ + public final Node right; + + public AlternationPatternNode(int startOffset, int length, Node left, Node right) { + super(startOffset, length); + this.left = left; + this.right = right; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.left.accept(visitor); + this.right.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.left, this.right }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitAlternationPatternNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("left: "); + builder.append(this.left.toString(nextIndent)); + builder.append(nextIndent); + builder.append("right: "); + builder.append(this.right.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&` operator or the `and` keyword.
+     *
+     *     left and right
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class AndNode extends Node { + /** + *
+         * Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     left and right
+         *     ^^^^
+         *
+         *     1 && 2
+         *     ^
+         * 
+ */ + public final Node left; + /** + *
+         * Represents the right side of the expression.
+         *
+         *     left && right
+         *             ^^^^^
+         *
+         *     1 and 2
+         *           ^
+         * 
+ */ + public final Node right; + + public AndNode(int startOffset, int length, Node left, Node right) { + super(startOffset, length); + this.left = left; + this.right = right; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.left.accept(visitor); + this.right.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.left, this.right }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitAndNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("left: "); + builder.append(this.left.toString(nextIndent)); + builder.append(nextIndent); + builder.append("right: "); + builder.append(this.right.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a set of arguments to a method or a keyword.
+     *
+     *     return foo, bar, baz
+     *            ^^^^^^^^^^^^^
+     * 
+ */ + public static final class ArgumentsNode extends Node { + public final short flags; + /** + *
+         * The list of arguments, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo(bar, baz)
+         *         ^^^^^^^^
+         * 
+ */ + public final Node[] arguments; + + public ArgumentsNode(int startOffset, int length, short flags, Node[] arguments) { + super(startOffset, length); + this.flags = flags; + this.arguments = arguments; + } + + public boolean isContainsForwarding() { + return ArgumentsNodeFlags.isContainsForwarding(flags); + } + + public boolean isContainsKeywords() { + return ArgumentsNodeFlags.isContainsKeywords(flags); + } + + public boolean isContainsKeywordSplat() { + return ArgumentsNodeFlags.isContainsKeywordSplat(flags); + } + + public boolean isContainsSplat() { + return ArgumentsNodeFlags.isContainsSplat(flags); + } + + public boolean isContainsMultipleSplats() { + return ArgumentsNodeFlags.isContainsMultipleSplats(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.arguments) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.arguments)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitArgumentsNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("ArgumentsNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append('\n'); + for (Node child : this.arguments) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i.
+     *
+     *     [1, 2, 3]
+     *     ^^^^^^^^^
+     * 
+ */ + public static final class ArrayNode extends Node { + public final short flags; + /** + *
+         * Represent the list of zero or more [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression) within the array.
+         * 
+ */ + public final Node[] elements; + + public ArrayNode(int startOffset, int length, short flags, Node[] elements) { + super(startOffset, length); + this.flags = flags; + this.elements = elements; + } + + public boolean isContainsSplat() { + return ArrayNodeFlags.isContainsSplat(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.elements) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.elements)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitArrayNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("ArrayNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("elements: "); + builder.append('\n'); + for (Node child : this.elements) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents an array pattern in pattern matching.
+     *
+     *     foo in 1, 2
+     *            ^^^^
+     *
+     *     foo in [1, 2]
+     *            ^^^^^^
+     *
+     *     foo in *bar
+     *            ^^^^
+     *
+     *     foo in Bar[]
+     *            ^^^^^
+     *
+     *     foo in Bar[1, 2, 3]
+     *            ^^^^^^^^^^^^
+     * 
+ */ + public static final class ArrayPatternNode extends Node { + /** + *
+         * Represents the optional constant preceding the Array
+         *
+         *     foo in Bar[]
+         *            ^^^
+         *
+         *     foo in Bar[1, 2, 3]
+         *            ^^^
+         *
+         *     foo in Bar::Baz[1, 2, 3]
+         *            ^^^^^^^^
+         * 
+ */ + @Nullable + @UnionType({ ConstantPathNode.class, ConstantReadNode.class }) + public final Node constant; + /** + *
+         * Represents the required elements of the array pattern.
+         *
+         *     foo in [1, 2]
+         *             ^  ^
+         * 
+ */ + public final Node[] requireds; + /** + *
+         * Represents the rest element of the array pattern.
+         *
+         *     foo in *bar
+         *            ^^^^
+         * 
+ */ + @Nullable + public final Node rest; + /** + *
+         * Represents the elements after the rest element of the array pattern.
+         *
+         *     foo in *bar, baz
+         *                  ^^^
+         * 
+ */ + public final Node[] posts; + + public ArrayPatternNode(int startOffset, int length, Node constant, Node[] requireds, Node rest, Node[] posts) { + super(startOffset, length); + this.constant = constant; + this.requireds = requireds; + this.rest = rest; + this.posts = posts; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.constant != null) { + this.constant.accept(visitor); + } + for (Nodes.Node child : this.requireds) { + child.accept(visitor); + } + if (this.rest != null) { + this.rest.accept(visitor); + } + for (Nodes.Node child : this.posts) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.add(this.constant); + childNodes.addAll(Arrays.asList(this.requireds)); + childNodes.add(this.rest); + childNodes.addAll(Arrays.asList(this.posts)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitArrayPatternNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("constant: "); + builder.append(this.constant == null ? "null\n" : this.constant.toString(nextIndent)); + builder.append(nextIndent); + builder.append("requireds: "); + builder.append('\n'); + for (Node child : this.requireds) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); + builder.append(nextIndent); + builder.append("posts: "); + builder.append('\n'); + for (Node child : this.posts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a hash key/value pair.
+     *
+     *     { a => b }
+     *       ^^^^^^
+     * 
+ */ + public static final class AssocNode extends Node { + /** + *
+         * The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     { a: b }
+         *       ^
+         *
+         *     { foo => bar }
+         *       ^^^
+         *
+         *     { def a; end => 1 }
+         *       ^^^^^^^^^^
+         * 
+ */ + public final Node key; + /** + *
+         * The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     { foo => bar }
+         *              ^^^
+         *
+         *     { x: 1 }
+         *          ^
+         * 
+ */ + public final Node value; + + public AssocNode(int startOffset, int length, Node key, Node value) { + super(startOffset, length); + this.key = key; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.key.accept(visitor); + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.key, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitAssocNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("key: "); + builder.append(this.key.toString(nextIndent)); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a splat in a hash literal.
+     *
+     *     { **foo }
+     *       ^^^^^
+     * 
+ */ + public static final class AssocSplatNode extends Node { + /** + *
+         * The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used.
+         *
+         *     { **foo }
+         *         ^^^
+         * 
+ */ + @Nullable + public final Node value; + + public AssocSplatNode(int startOffset, int length, Node value) { + super(startOffset, length); + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.value != null) { + this.value.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitAssocSplatNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value == null ? "null\n" : this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents reading a reference to a field in the previous match.
+     *
+     *     $'
+     *     ^^
+     * 
+ */ + public static final class BackReferenceReadNode extends Node { + /** + *
+         * The name of the back-reference variable, including the leading `$`.
+         *
+         *     $& # name `:$&`
+         *
+         *     $+ # name `:$+`
+         * 
+ */ + public final byte[] name; + + public BackReferenceReadNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBackReferenceReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents a begin statement.
+     *
+     *     begin
+     *       foo
+     *     end
+     *     ^^^^^
+     * 
+ */ + public static final class BeginNode extends Node { + /** + *
+         * Represents the statements within the begin block.
+         *
+         *     begin x end
+         *           ^
+         * 
+ */ + @Nullable + public final StatementsNode statements; + /** + *
+         * Represents the rescue clause within the begin block.
+         *
+         *     begin x; rescue y; end
+         *              ^^^^^^^^
+         * 
+ */ + @Nullable + public final RescueNode rescue_clause; + /** + *
+         * Represents the else clause within the begin block.
+         *
+         *     begin x; rescue y; else z; end
+         *                        ^^^^^^^^^^^
+         * 
+ */ + @Nullable + public final ElseNode else_clause; + /** + *
+         * Represents the ensure clause within the begin block.
+         *
+         *     begin x; ensure y; end
+         *              ^^^^^^^^
+         * 
+ */ + @Nullable + public final EnsureNode ensure_clause; + + public BeginNode(int startOffset, int length, StatementsNode statements, RescueNode rescue_clause, ElseNode else_clause, EnsureNode ensure_clause) { + super(startOffset, length); + this.statements = statements; + this.rescue_clause = rescue_clause; + this.else_clause = else_clause; + this.ensure_clause = ensure_clause; + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + // Never mark BeginNode with a newline flag, mark children instead + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.statements != null) { + this.statements.accept(visitor); + } + if (this.rescue_clause != null) { + this.rescue_clause.accept(visitor); + } + if (this.else_clause != null) { + this.else_clause.accept(visitor); + } + if (this.ensure_clause != null) { + this.ensure_clause.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.statements, this.rescue_clause, this.else_clause, this.ensure_clause }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBeginNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + builder.append(nextIndent); + builder.append("rescue_clause: "); + builder.append(this.rescue_clause == null ? "null\n" : this.rescue_clause.toString(nextIndent)); + builder.append(nextIndent); + builder.append("else_clause: "); + builder.append(this.else_clause == null ? "null\n" : this.else_clause.toString(nextIndent)); + builder.append(nextIndent); + builder.append("ensure_clause: "); + builder.append(this.ensure_clause == null ? "null\n" : this.ensure_clause.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a block argument using `&`.
+     *
+     *     bar(&args)
+     *         ^^^^^
+     * 
+ */ + public static final class BlockArgumentNode extends Node { + /** + *
+         * The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo(&args)
+         *          ^^^^
+         * 
+ */ + @Nullable + public final Node expression; + + public BlockArgumentNode(int startOffset, int length, Node expression) { + super(startOffset, length); + this.expression = expression; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.expression != null) { + this.expression.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.expression }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBlockArgumentNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("expression: "); + builder.append(this.expression == null ? "null\n" : this.expression.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a block local variable.
+     *
+     *     a { |; b| }
+     *            ^
+     * 
+ */ + public static final class BlockLocalVariableNode extends Node { + public final short flags; + /** + *
+         * The name of the block local variable.
+         *
+         *     a { |; b| } # name `:b`
+         *            ^
+         * 
+ */ + public final byte[] name; + + public BlockLocalVariableNode(int startOffset, int length, short flags, byte[] name) { + super(startOffset, length); + this.flags = flags; + this.name = name; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBlockLocalVariableNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents a block of ruby code.
+     *
+     *     [1, 2, 3].each { |i| puts x }
+     *                    ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class BlockNode extends Node { + /** + *
+         * The local variables declared in the block.
+         *
+         *     [1, 2, 3].each { |i| puts x } # locals: [:i]
+         *                       ^
+         * 
+ */ + public final byte[][] locals; + /** + *
+         * The parameters of the block.
+         *
+         *     [1, 2, 3].each { |i| puts x }
+         *                      ^^^
+         *     [1, 2, 3].each { puts _1 }
+         *                    ^^^^^^^^^^^
+         *     [1, 2, 3].each { puts it }
+         *                    ^^^^^^^^^^^
+         * 
+ */ + @Nullable + @UnionType({ BlockParametersNode.class, NumberedParametersNode.class, ItParametersNode.class }) + public final Node parameters; + /** + *
+         * The body of the block.
+         *
+         *     [1, 2, 3].each { |i| puts x }
+         *                          ^^^^^^
+         * 
+ */ + @Nullable + @UnionType({ StatementsNode.class, BeginNode.class }) + public final Node body; + + public BlockNode(int startOffset, int length, byte[][] locals, Node parameters, Node body) { + super(startOffset, length); + this.locals = locals; + this.parameters = parameters; + this.body = body; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.parameters != null) { + this.parameters.accept(visitor); + } + if (this.body != null) { + this.body.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.parameters, this.body }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBlockNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (byte[] constant : this.locals) { + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); + } + builder.append(nextIndent); + builder.append("parameters: "); + builder.append(this.parameters == null ? "null\n" : this.parameters.toString(nextIndent)); + builder.append(nextIndent); + builder.append("body: "); + builder.append(this.body == null ? "null\n" : this.body.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a block parameter of a method, block, or lambda definition.
+     *
+     *     def a(&b)
+     *           ^^
+     *     end
+     * 
+ */ + public static final class BlockParameterNode extends Node { + public final short flags; + /** + *
+         * The name of the block parameter.
+         *
+         *     def a(&b) # name `:b`
+         *            ^
+         *     end
+         * 
+ */ + @Nullable + public final byte[] name; + + public BlockParameterNode(int startOffset, int length, short flags, byte[] name) { + super(startOffset, length); + this.flags = flags; + this.name = name; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBlockParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append(this.name == null ? "null" : "\"" + asString(this.name) + "\""); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents a block's parameters declaration.
+     *
+     *     -> (a, b = 1; local) { }
+     *        ^^^^^^^^^^^^^^^^^
+     *
+     *     foo do |a, b = 1; local|
+     *            ^^^^^^^^^^^^^^^^^
+     *     end
+     * 
+ */ + public static final class BlockParametersNode extends Node { + /** + *
+         * Represents the parameters of the block.
+         *
+         *     -> (a, b = 1; local) { }
+         *         ^^^^^^^^
+         *
+         *     foo do |a, b = 1; local|
+         *             ^^^^^^^^
+         *     end
+         * 
+ */ + @Nullable + public final ParametersNode parameters; + /** + *
+         * Represents the local variables of the block.
+         *
+         *     -> (a, b = 1; local) { }
+         *                   ^^^^^
+         *
+         *     foo do |a, b = 1; local|
+         *                       ^^^^^
+         *     end
+         * 
+ */ + public final BlockLocalVariableNode[] locals; + + public BlockParametersNode(int startOffset, int length, ParametersNode parameters, BlockLocalVariableNode[] locals) { + super(startOffset, length); + this.parameters = parameters; + this.locals = locals; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.parameters != null) { + this.parameters.accept(visitor); + } + for (Nodes.Node child : this.locals) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.add(this.parameters); + childNodes.addAll(Arrays.asList(this.locals)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBlockParametersNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("parameters: "); + builder.append(this.parameters == null ? "null\n" : this.parameters.toString(nextIndent)); + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (Node child : this.locals) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `break` keyword.
+     *
+     *     break foo
+     *     ^^^^^^^^^
+     * 
+ */ + public static final class BreakNode extends Node { + /** + *
+         * The arguments to the break statement, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     break foo
+         *           ^^^
+         * 
+ */ + @Nullable + public final ArgumentsNode arguments; + + public BreakNode(int startOffset, int length, ArgumentsNode arguments) { + super(startOffset, length); + this.arguments = arguments; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.arguments != null) { + this.arguments.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.arguments }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitBreakNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator on a call.
+     *
+     *     foo.bar &&= value
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class CallAndWriteNode extends Node { + public final short flags; + /** + *
+         * The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo.bar &&= value
+         *     ^^^
+         * 
+ */ + @Nullable + public final Node receiver; + /** + *
+         * Represents the name of the method being called.
+         *
+         *     foo.bar &&= value # read_name `:bar`
+         *         ^^^
+         * 
+ */ + public final byte[] read_name; + /** + *
+         * Represents the name of the method being written to.
+         *
+         *     foo.bar &&= value # write_name `:bar=`
+         *         ^^^
+         * 
+ */ + public final byte[] write_name; + /** + *
+         * Represents the value being assigned.
+         *
+         *     foo.bar &&= value
+         *                 ^^^^^
+         * 
+ */ + public final Node value; + + public CallAndWriteNode(int startOffset, int length, short flags, Node receiver, byte[] read_name, byte[] write_name, Node value) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.read_name = read_name; + this.write_name = write_name; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCallAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("read_name: "); + builder.append('"').append(asString(this.read_name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("write_name: "); + builder.append('"').append(asString(this.write_name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a method call, in all of the various forms that can take.
+     *
+     *     foo
+     *     ^^^
+     *
+     *     foo()
+     *     ^^^^^
+     *
+     *     +foo
+     *     ^^^^
+     *
+     *     foo + bar
+     *     ^^^^^^^^^
+     *
+     *     foo.bar
+     *     ^^^^^^^
+     *
+     *     foo&.bar
+     *     ^^^^^^^^
+     * 
+ */ + public static final class CallNode extends Node { + public final short flags; + /** + *
+         * The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo.bar
+         *     ^^^
+         *
+         *     +foo
+         *      ^^^
+         *
+         *     foo + bar
+         *     ^^^
+         * 
+ */ + @Nullable + public final Node receiver; + /** + *
+         * Represents the name of the method being called.
+         *
+         *     foo.bar # name `:foo`
+         *     ^^^
+         * 
+ */ + public final byte[] name; + /** + *
+         * Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo(bar)
+         *         ^^^
+         * 
+ */ + @Nullable + public final ArgumentsNode arguments; + /** + *
+         * Represents the block that is being passed to the method.
+         *
+         *     foo { |a| a }
+         *         ^^^^^^^^^
+         * 
+ */ + @Nullable + @UnionType({ BlockNode.class, BlockArgumentNode.class }) + public final Node block; + + public CallNode(int startOffset, int length, short flags, Node receiver, byte[] name, ArgumentsNode arguments, Node block) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.name = name; + this.arguments = arguments; + this.block = block; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCallNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of an assignment operator on a call.
+     *
+     *     foo.bar += baz
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class CallOperatorWriteNode extends Node { + public final short flags; + /** + *
+         * The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo.bar += value
+         *     ^^^
+         * 
+ */ + @Nullable + public final Node receiver; + /** + *
+         * Represents the name of the method being called.
+         *
+         *     foo.bar += value # read_name `:bar`
+         *         ^^^
+         * 
+ */ + public final byte[] read_name; + /** + *
+         * Represents the name of the method being written to.
+         *
+         *     foo.bar += value # write_name `:bar=`
+         *         ^^^
+         * 
+ */ + public final byte[] write_name; + /** + *
+         * Represents the binary operator being used.
+         *
+         *     foo.bar += value # binary_operator `:+`
+         *             ^
+         * 
+ */ + public final byte[] binary_operator; + /** + *
+         * Represents the value being assigned.
+         *
+         *     foo.bar += value
+         *                ^^^^^
+         * 
+ */ + public final Node value; + + public CallOperatorWriteNode(int startOffset, int length, short flags, Node receiver, byte[] read_name, byte[] write_name, byte[] binary_operator, Node value) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.read_name = read_name; + this.write_name = write_name; + this.binary_operator = binary_operator; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCallOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("read_name: "); + builder.append('"').append(asString(this.read_name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("write_name: "); + builder.append('"').append(asString(this.write_name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator on a call.
+     *
+     *     foo.bar ||= value
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class CallOrWriteNode extends Node { + public final short flags; + /** + *
+         * The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo.bar ||= value
+         *     ^^^
+         * 
+ */ + @Nullable + public final Node receiver; + /** + *
+         * Represents the name of the method being called.
+         *
+         *     foo.bar ||= value # read_name `:bar`
+         *         ^^^
+         * 
+ */ + public final byte[] read_name; + /** + *
+         * Represents the name of the method being written to.
+         *
+         *     foo.bar ||= value # write_name `:bar=`
+         *         ^^^
+         * 
+ */ + public final byte[] write_name; + /** + *
+         * Represents the value being assigned.
+         *
+         *     foo.bar ||= value
+         *                 ^^^^^
+         * 
+ */ + public final Node value; + + public CallOrWriteNode(int startOffset, int length, short flags, Node receiver, byte[] read_name, byte[] write_name, Node value) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.read_name = read_name; + this.write_name = write_name; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCallOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("read_name: "); + builder.append('"').append(asString(this.read_name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("write_name: "); + builder.append('"').append(asString(this.write_name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to a method call.
+     *
+     *     foo.bar, = 1
+     *     ^^^^^^^
+     *
+     *     begin
+     *     rescue => foo.bar
+     *               ^^^^^^^
+     *     end
+     *
+     *     for foo.bar in baz do end
+     *         ^^^^^^^
+     * 
+ */ + public static final class CallTargetNode extends Node { + public final short flags; + /** + *
+         * The object that the method is being called on. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo.bar = 1
+         *     ^^^
+         * 
+ */ + public final Node receiver; + /** + *
+         * Represents the name of the method being called.
+         *
+         *     foo.bar = 1 # name `:foo`
+         *     ^^^
+         * 
+ */ + public final byte[] name; + + public CallTargetNode(int startOffset, int length, short flags, Node receiver, byte[] name) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.name = name; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.receiver.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCallTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to a local variable in pattern matching.
+     *
+     *     foo => [bar => baz]
+     *             ^^^^^^^^^^
+     * 
+ */ + public static final class CapturePatternNode extends Node { + /** + *
+         * Represents the value to capture.
+         *
+         *     foo => bar
+         *            ^^^
+         * 
+ */ + public final Node value; + /** + *
+         * Represents the target of the capture.
+         *
+         *     foo => bar
+         *     ^^^
+         * 
+ */ + public final LocalVariableTargetNode target; + + public CapturePatternNode(int startOffset, int length, Node value, LocalVariableTargetNode target) { + super(startOffset, length); + this.value = value; + this.target = target; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + this.target.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value, this.target }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCapturePatternNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("target: "); + builder.append(this.target.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of a case statement for pattern matching.
+     *
+     *     case true
+     *     in false
+     *     end
+     *     ^^^^^^^^^
+     * 
+ */ + public static final class CaseMatchNode extends Node { + /** + *
+         * Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     case true; in false; end
+         *          ^^^^
+         * 
+ */ + @Nullable + public final Node predicate; + /** + *
+         * Represents the conditions of the case match.
+         *
+         *     case true; in false; end
+         *                ^^^^^^^^
+         * 
+ */ + public final InNode[] conditions; + /** + *
+         * Represents the else clause of the case match.
+         *
+         *     case true; in false; else; end
+         *                          ^^^^^^^^^
+         * 
+ */ + @Nullable + public final ElseNode else_clause; + + public CaseMatchNode(int startOffset, int length, Node predicate, InNode[] conditions, ElseNode else_clause) { + super(startOffset, length); + this.predicate = predicate; + this.conditions = conditions; + this.else_clause = else_clause; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.predicate != null) { + this.predicate.accept(visitor); + } + for (Nodes.Node child : this.conditions) { + child.accept(visitor); + } + if (this.else_clause != null) { + this.else_clause.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.add(this.predicate); + childNodes.addAll(Arrays.asList(this.conditions)); + childNodes.add(this.else_clause); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCaseMatchNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("predicate: "); + builder.append(this.predicate == null ? "null\n" : this.predicate.toString(nextIndent)); + builder.append(nextIndent); + builder.append("conditions: "); + builder.append('\n'); + for (Node child : this.conditions) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("else_clause: "); + builder.append(this.else_clause == null ? "null\n" : this.else_clause.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of a case statement.
+     *
+     *     case true
+     *     when false
+     *     end
+     *     ^^^^^^^^^^
+     * 
+ */ + public static final class CaseNode extends Node { + /** + *
+         * Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     case true; when false; end
+         *          ^^^^
+         * 
+ */ + @Nullable + public final Node predicate; + /** + *
+         * Represents the conditions of the case statement.
+         *
+         *     case true; when false; end
+         *                ^^^^^^^^^^
+         * 
+ */ + public final WhenNode[] conditions; + /** + *
+         * Represents the else clause of the case statement.
+         *
+         *     case true; when false; else; end
+         *                            ^^^^^^^^^
+         * 
+ */ + @Nullable + public final ElseNode else_clause; + + public CaseNode(int startOffset, int length, Node predicate, WhenNode[] conditions, ElseNode else_clause) { + super(startOffset, length); + this.predicate = predicate; + this.conditions = conditions; + this.else_clause = else_clause; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.predicate != null) { + this.predicate.accept(visitor); + } + for (Nodes.Node child : this.conditions) { + child.accept(visitor); + } + if (this.else_clause != null) { + this.else_clause.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.add(this.predicate); + childNodes.addAll(Arrays.asList(this.conditions)); + childNodes.add(this.else_clause); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitCaseNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("predicate: "); + builder.append(this.predicate == null ? "null\n" : this.predicate.toString(nextIndent)); + builder.append(nextIndent); + builder.append("conditions: "); + builder.append('\n'); + for (Node child : this.conditions) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("else_clause: "); + builder.append(this.else_clause == null ? "null\n" : this.else_clause.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a class declaration involving the `class` keyword.
+     *
+     *     class Foo end
+     *     ^^^^^^^^^^^^^
+     * 
+ */ + public static final class ClassNode extends Node { + public final byte[][] locals; + @UnionType({ ConstantReadNode.class, ConstantPathNode.class }) + public final Node constant_path; + /** + *
+         * Represents the superclass of the class.
+         *
+         *     class Foo < Bar
+         *                 ^^^
+         * 
+ */ + @Nullable + public final Node superclass; + /** + *
+         * Represents the body of the class.
+         *
+         *     class Foo; bar; end
+         *                ^^^
+         * 
+ */ + @Nullable + @UnionType({ StatementsNode.class, BeginNode.class }) + public final Node body; + /** + *
+         * The name of the class.
+         *
+         *     class Foo end # name `:Foo`
+         * 
+ */ + public final byte[] name; + + public ClassNode(int startOffset, int length, byte[][] locals, Node constant_path, Node superclass, Node body, byte[] name) { + super(startOffset, length); + this.locals = locals; + this.constant_path = constant_path; + this.superclass = superclass; + this.body = body; + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.constant_path.accept(visitor); + if (this.superclass != null) { + this.superclass.accept(visitor); + } + if (this.body != null) { + this.body.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.constant_path, this.superclass, this.body }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitClassNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (byte[] constant : this.locals) { + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); + } + builder.append(nextIndent); + builder.append("constant_path: "); + builder.append(this.constant_path.toString(nextIndent)); + builder.append(nextIndent); + builder.append("superclass: "); + builder.append(this.superclass == null ? "null\n" : this.superclass.toString(nextIndent)); + builder.append(nextIndent); + builder.append("body: "); + builder.append(this.body == null ? "null\n" : this.body.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator for assignment to a class variable.
+     *
+     *     @@target &&= value
+     *     ^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ClassVariableAndWriteNode extends Node { + /** + *
+         * The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+         *
+         *     @@target &&= value # name `:@@target`
+         *     ^^^^^^^^
+         * 
+ */ + public final byte[] name; + /** + *
+         * Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     @@target &&= value
+         *                  ^^^^^
+         * 
+ */ + public final Node value; + + public ClassVariableAndWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitClassVariableAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to a class variable using an operator that isn't `=`.
+     *
+     *     @@target += value
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ClassVariableOperatorWriteNode extends Node { + public final byte[] name; + public final Node value; + public final byte[] binary_operator; + + public ClassVariableOperatorWriteNode(int startOffset, int length, byte[] name, Node value, byte[] binary_operator) { + super(startOffset, length); + this.name = name; + this.value = value; + this.binary_operator = binary_operator; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitClassVariableOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator for assignment to a class variable.
+     *
+     *     @@target ||= value
+     *     ^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ClassVariableOrWriteNode extends Node { + public final byte[] name; + public final Node value; + + public ClassVariableOrWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitClassVariableOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents referencing a class variable.
+     *
+     *     @@foo
+     *     ^^^^^
+     * 
+ */ + public static final class ClassVariableReadNode extends Node { + /** + *
+         * The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+         *
+         *     @@abc   # name `:@@abc`
+         *
+         *     @@_test # name `:@@_test`
+         * 
+ */ + public final byte[] name; + + public ClassVariableReadNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitClassVariableReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a class variable in a context that doesn't have an explicit value.
+     *
+     *     @@foo, @@bar = baz
+     *     ^^^^^  ^^^^^
+     * 
+ */ + public static final class ClassVariableTargetNode extends Node { + public final byte[] name; + + public ClassVariableTargetNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitClassVariableTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a class variable.
+     *
+     *     @@foo = 1
+     *     ^^^^^^^^^
+     * 
+ */ + public static final class ClassVariableWriteNode extends Node { + /** + *
+         * The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+         *
+         *     @@abc = 123     # name `@@abc`
+         *
+         *     @@_test = :test # name `@@_test`
+         * 
+ */ + public final byte[] name; + /** + *
+         * The value to write to the class variable. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     @@foo = :bar
+         *             ^^^^
+         *
+         *     @@_xyz = 123
+         *              ^^^
+         * 
+ */ + public final Node value; + + public ClassVariableWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitClassVariableWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator for assignment to a constant.
+     *
+     *     Target &&= value
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ConstantAndWriteNode extends Node { + public final byte[] name; + public final Node value; + + public ConstantAndWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to a constant using an operator that isn't `=`.
+     *
+     *     Target += value
+     *     ^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ConstantOperatorWriteNode extends Node { + public final byte[] name; + public final Node value; + public final byte[] binary_operator; + + public ConstantOperatorWriteNode(int startOffset, int length, byte[] name, Node value, byte[] binary_operator) { + super(startOffset, length); + this.name = name; + this.value = value; + this.binary_operator = binary_operator; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator for assignment to a constant.
+     *
+     *     Target ||= value
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ConstantOrWriteNode extends Node { + public final byte[] name; + public final Node value; + + public ConstantOrWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator for assignment to a constant path.
+     *
+     *     Parent::Child &&= value
+     *     ^^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ConstantPathAndWriteNode extends Node { + public final ConstantPathNode target; + public final Node value; + + public ConstantPathAndWriteNode(int startOffset, int length, ConstantPathNode target, Node value) { + super(startOffset, length); + this.target = target; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.target.accept(visitor); + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.target, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantPathAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("target: "); + builder.append(this.target.toString(nextIndent)); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents accessing a constant through a path of `::` operators.
+     *
+     *     Foo::Bar
+     *     ^^^^^^^^
+     * 
+ */ + public static final class ConstantPathNode extends Node { + /** + *
+         * The left-hand node of the path, if present. It can be `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It will be `nil` when the constant lookup is at the root of the module tree.
+         *
+         *     Foo::Bar
+         *     ^^^
+         *
+         *     self::Test
+         *     ^^^^
+         *
+         *     a.b::C
+         *     ^^^
+         * 
+ */ + @Nullable + public final Node parent; + /** + *
+         * The name of the constant being accessed. This could be `nil` in the event of a syntax error.
+         * 
+ */ + @Nullable + public final byte[] name; + + public ConstantPathNode(int startOffset, int length, Node parent, byte[] name) { + super(startOffset, length); + this.parent = parent; + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.parent != null) { + this.parent.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.parent }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantPathNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("parent: "); + builder.append(this.parent == null ? "null\n" : this.parent.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append(this.name == null ? "null" : "\"" + asString(this.name) + "\""); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to a constant path using an operator that isn't `=`.
+     *
+     *     Parent::Child += value
+     *     ^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ConstantPathOperatorWriteNode extends Node { + public final ConstantPathNode target; + public final Node value; + public final byte[] binary_operator; + + public ConstantPathOperatorWriteNode(int startOffset, int length, ConstantPathNode target, Node value, byte[] binary_operator) { + super(startOffset, length); + this.target = target; + this.value = value; + this.binary_operator = binary_operator; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.target.accept(visitor); + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.target, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantPathOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("target: "); + builder.append(this.target.toString(nextIndent)); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator for assignment to a constant path.
+     *
+     *     Parent::Child ||= value
+     *     ^^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ConstantPathOrWriteNode extends Node { + public final ConstantPathNode target; + public final Node value; + + public ConstantPathOrWriteNode(int startOffset, int length, ConstantPathNode target, Node value) { + super(startOffset, length); + this.target = target; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.target.accept(visitor); + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.target, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantPathOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("target: "); + builder.append(this.target.toString(nextIndent)); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a constant path in a context that doesn't have an explicit value.
+     *
+     *     Foo::Foo, Bar::Bar = baz
+     *     ^^^^^^^^  ^^^^^^^^
+     * 
+ */ + public static final class ConstantPathTargetNode extends Node { + @Nullable + public final Node parent; + @Nullable + public final byte[] name; + + public ConstantPathTargetNode(int startOffset, int length, Node parent, byte[] name) { + super(startOffset, length); + this.parent = parent; + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.parent != null) { + this.parent.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.parent }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantPathTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("parent: "); + builder.append(this.parent == null ? "null\n" : this.parent.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append(this.name == null ? "null" : "\"" + asString(this.name) + "\""); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a constant path.
+     *
+     *     ::Foo = 1
+     *     ^^^^^^^^^
+     *
+     *     Foo::Bar = 1
+     *     ^^^^^^^^^^^^
+     *
+     *     ::Foo::Bar = 1
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ConstantPathWriteNode extends Node { + /** + *
+         * A node representing the constant path being written to.
+         *
+         *     Foo::Bar = 1
+         *     ^^^^^^^^
+         *
+         *     ::Foo = :abc
+         *     ^^^^^
+         * 
+ */ + public final ConstantPathNode target; + /** + *
+         * The value to write to the constant path. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     FOO::BAR = :abc
+         *                ^^^^
+         * 
+ */ + public final Node value; + + public ConstantPathWriteNode(int startOffset, int length, ConstantPathNode target, Node value) { + super(startOffset, length); + this.target = target; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.target.accept(visitor); + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.target, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantPathWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("target: "); + builder.append(this.target.toString(nextIndent)); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents referencing a constant.
+     *
+     *     Foo
+     *     ^^^
+     * 
+ */ + public static final class ConstantReadNode extends Node { + /** + *
+         * The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants).
+         *
+         *     X              # name `:X`
+         *
+         *     SOME_CONSTANT  # name `:SOME_CONSTANT`
+         * 
+ */ + public final byte[] name; + + public ConstantReadNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a constant in a context that doesn't have an explicit value.
+     *
+     *     Foo, Bar = baz
+     *     ^^^  ^^^
+     * 
+ */ + public static final class ConstantTargetNode extends Node { + public final byte[] name; + + public ConstantTargetNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a constant.
+     *
+     *     Foo = 1
+     *     ^^^^^^^
+     * 
+ */ + public static final class ConstantWriteNode extends Node { + /** + *
+         * The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants).
+         *
+         *     Foo = :bar # name `:Foo`
+         *
+         *     XYZ = 1    # name `:XYZ`
+         * 
+ */ + public final byte[] name; + /** + *
+         * The value to write to the constant. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     FOO = :bar
+         *           ^^^^
+         *
+         *     MyClass = Class.new
+         *               ^^^^^^^^^
+         * 
+ */ + public final Node value; + + public ConstantWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitConstantWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a method definition.
+     *
+     *     def method
+     *     end
+     *     ^^^^^^^^^^
+     * 
+ */ + public static final class DefNode extends Node { + public final int serializedLength; + public final Loader loader; + public final byte[] name; + @Nullable + public final Node receiver; + @Nullable + public final ParametersNode parameters; + @Nullable + @UnionType({ StatementsNode.class, BeginNode.class }) + public final Node body; + public final byte[][] locals; + + public DefNode(int startOffset, int length, int serializedLength, Loader loader, byte[] name, Node receiver, ParametersNode parameters, Node body, byte[][] locals) { + super(startOffset, length); + this.serializedLength = serializedLength; + this.loader = loader; + this.name = name; + this.receiver = receiver; + this.parameters = parameters; + this.body = body; + this.locals = locals; + } + + public boolean isLazy() { + return serializedLength < 0; + } + + public DefNode getNonLazy() { + if (isLazy()) { + return loader.createDefNodeFromSavedPosition(startOffset, length, -serializedLength); + } else { + return this; + } + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.parameters != null) { + this.parameters.accept(visitor); + } + if (this.body != null) { + this.body.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.parameters, this.body }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitDefNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("parameters: "); + builder.append(this.parameters == null ? "null\n" : this.parameters.toString(nextIndent)); + builder.append(nextIndent); + builder.append("body: "); + builder.append(this.body == null ? "null\n" : this.body.toString(nextIndent)); + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (byte[] constant : this.locals) { + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); + } + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `defined?` keyword.
+     *
+     *     defined?(a)
+     *     ^^^^^^^^^^^
+     * 
+ */ + public static final class DefinedNode extends Node { + public final Node value; + + public DefinedNode(int startOffset, int length, Node value) { + super(startOffset, length); + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitDefinedNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an `else` clause in a `case`, `if`, or `unless` statement.
+     *
+     *     if a then b else c end
+     *                 ^^^^^^^^^^
+     * 
+ */ + public static final class ElseNode extends Node { + @Nullable + public final StatementsNode statements; + + public ElseNode(int startOffset, int length, StatementsNode statements) { + super(startOffset, length); + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitElseNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an interpolated set of statements.
+     *
+     *     "foo #{bar}"
+     *          ^^^^^^
+     * 
+ */ + public static final class EmbeddedStatementsNode extends Node { + @Nullable + public final StatementsNode statements; + + public EmbeddedStatementsNode(int startOffset, int length, StatementsNode statements) { + super(startOffset, length); + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitEmbeddedStatementsNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an interpolated variable.
+     *
+     *     "foo #@bar"
+     *          ^^^^^
+     * 
+ */ + public static final class EmbeddedVariableNode extends Node { + @UnionType({ InstanceVariableReadNode.class, ClassVariableReadNode.class, GlobalVariableReadNode.class, BackReferenceReadNode.class, NumberedReferenceReadNode.class }) + public final Node variable; + + public EmbeddedVariableNode(int startOffset, int length, Node variable) { + super(startOffset, length); + this.variable = variable; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.variable.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.variable }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitEmbeddedVariableNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("variable: "); + builder.append(this.variable.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an `ensure` clause in a `begin` statement.
+     *
+     *     begin
+     *       foo
+     *     ensure
+     *     ^^^^^^
+     *       bar
+     *     end
+     * 
+ */ + public static final class EnsureNode extends Node { + @Nullable + public final StatementsNode statements; + + public EnsureNode(int startOffset, int length, StatementsNode statements) { + super(startOffset, length); + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitEnsureNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the literal `false` keyword.
+     *
+     *     false
+     *     ^^^^^
+     * 
+ */ + public static final class FalseNode extends Node { + + public FalseNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitFalseNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents a find pattern in pattern matching.
+     *
+     *     foo in *bar, baz, *qux
+     *            ^^^^^^^^^^^^^^^
+     *
+     *     foo in [*bar, baz, *qux]
+     *            ^^^^^^^^^^^^^^^^^
+     *
+     *     foo in Foo(*bar, baz, *qux)
+     *            ^^^^^^^^^^^^^^^^^^^^
+     *
+     *     foo => *bar, baz, *qux
+     *            ^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class FindPatternNode extends Node { + /** + *
+         * Represents the optional constant preceding the pattern
+         *
+         *     foo in Foo(*bar, baz, *qux)
+         *            ^^^
+         * 
+ */ + @Nullable + @UnionType({ ConstantPathNode.class, ConstantReadNode.class }) + public final Node constant; + /** + *
+         * Represents the first wildcard node in the pattern.
+         *
+         *     foo in *bar, baz, *qux
+         *            ^^^^
+         *
+         *     foo in Foo(*bar, baz, *qux)
+         *                ^^^^
+         * 
+ */ + public final SplatNode left; + /** + *
+         * Represents the nodes in between the wildcards.
+         *
+         *     foo in *bar, baz, *qux
+         *                  ^^^
+         *
+         *     foo in Foo(*bar, baz, 1, *qux)
+         *                      ^^^^^^
+         * 
+ */ + public final Node[] requireds; + /** + *
+         * Represents the second wildcard node in the pattern.
+         *
+         *     foo in *bar, baz, *qux
+         *                       ^^^^
+         *
+         *     foo in Foo(*bar, baz, *qux)
+         *                           ^^^^
+         * 
+ */ + public final SplatNode right; + + public FindPatternNode(int startOffset, int length, Node constant, SplatNode left, Node[] requireds, SplatNode right) { + super(startOffset, length); + this.constant = constant; + this.left = left; + this.requireds = requireds; + this.right = right; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.constant != null) { + this.constant.accept(visitor); + } + this.left.accept(visitor); + for (Nodes.Node child : this.requireds) { + child.accept(visitor); + } + this.right.accept(visitor); + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.add(this.constant); + childNodes.add(this.left); + childNodes.addAll(Arrays.asList(this.requireds)); + childNodes.add(this.right); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitFindPatternNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("constant: "); + builder.append(this.constant == null ? "null\n" : this.constant.toString(nextIndent)); + builder.append(nextIndent); + builder.append("left: "); + builder.append(this.left.toString(nextIndent)); + builder.append(nextIndent); + builder.append("requireds: "); + builder.append('\n'); + for (Node child : this.requireds) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("right: "); + builder.append(this.right.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `..` or `...` operators to create flip flops.
+     *
+     *     baz if foo .. bar
+     *            ^^^^^^^^^^
+     * 
+ */ + public static final class FlipFlopNode extends Node { + public final short flags; + @Nullable + public final Node left; + @Nullable + public final Node right; + + public FlipFlopNode(int startOffset, int length, short flags, Node left, Node right) { + super(startOffset, length); + this.flags = flags; + this.left = left; + this.right = right; + } + + public boolean isExcludeEnd() { + return RangeFlags.isExcludeEnd(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.left != null) { + this.left.accept(visitor); + } + if (this.right != null) { + this.right.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.left, this.right }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitFlipFlopNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("RangeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("left: "); + builder.append(this.left == null ? "null\n" : this.left.toString(nextIndent)); + builder.append(nextIndent); + builder.append("right: "); + builder.append(this.right == null ? "null\n" : this.right.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a floating point number literal.
+     *
+     *     1.0
+     *     ^^^
+     * 
+ */ + public static final class FloatNode extends Node { + /** + *
+         * The value of the floating point number as a Float.
+         * 
+ */ + public final double value; + + public FloatNode(int startOffset, int length, double value) { + super(startOffset, length); + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitFloatNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `for` keyword.
+     *
+     *     for i in a end
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ForNode extends Node { + /** + *
+         * The index expression for `for` loops.
+         *
+         *     for i in a end
+         *         ^
+         * 
+ */ + @UnionType({ LocalVariableTargetNode.class, InstanceVariableTargetNode.class, ClassVariableTargetNode.class, GlobalVariableTargetNode.class, ConstantTargetNode.class, ConstantPathTargetNode.class, CallTargetNode.class, IndexTargetNode.class, MultiTargetNode.class }) + public final Node index; + /** + *
+         * The collection to iterate over.
+         *
+         *     for i in a end
+         *              ^
+         * 
+ */ + public final Node collection; + /** + *
+         * Represents the body of statements to execute for each iteration of the loop.
+         *
+         *     for i in a
+         *       foo(i)
+         *       ^^^^^^
+         *     end
+         * 
+ */ + @Nullable + public final StatementsNode statements; + + public ForNode(int startOffset, int length, Node index, Node collection, StatementsNode statements) { + super(startOffset, length); + this.index = index; + this.collection = collection; + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.index.accept(visitor); + this.collection.accept(visitor); + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.index, this.collection, this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitForNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("index: "); + builder.append(this.index.toString(nextIndent)); + builder.append(nextIndent); + builder.append("collection: "); + builder.append(this.collection.toString(nextIndent)); + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents forwarding all arguments to this method to another method.
+     *
+     *     def foo(...)
+     *       bar(...)
+     *           ^^^
+     *     end
+     * 
+ */ + public static final class ForwardingArgumentsNode extends Node { + + public ForwardingArgumentsNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitForwardingArgumentsNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the forwarding parameter in a method, block, or lambda declaration.
+     *
+     *     def foo(...)
+     *             ^^^
+     *     end
+     * 
+ */ + public static final class ForwardingParameterNode extends Node { + + public ForwardingParameterNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitForwardingParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `super` keyword without parentheses or arguments, but which might have a block.
+     *
+     *     super
+     *     ^^^^^
+     *
+     *     super { 123 }
+     *     ^^^^^^^^^^^^^
+     *
+     * If it has any other arguments, it would be a `SuperNode` instead.
+     * 
+ */ + public static final class ForwardingSuperNode extends Node { + /** + *
+         * All other arguments are forwarded as normal, except the original block is replaced with the new block.
+         * 
+ */ + @Nullable + public final BlockNode block; + + public ForwardingSuperNode(int startOffset, int length, BlockNode block) { + super(startOffset, length); + this.block = block; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.block != null) { + this.block.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.block }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitForwardingSuperNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator for assignment to a global variable.
+     *
+     *     $target &&= value
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class GlobalVariableAndWriteNode extends Node { + public final byte[] name; + public final Node value; + + public GlobalVariableAndWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitGlobalVariableAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to a global variable using an operator that isn't `=`.
+     *
+     *     $target += value
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class GlobalVariableOperatorWriteNode extends Node { + public final byte[] name; + public final Node value; + public final byte[] binary_operator; + + public GlobalVariableOperatorWriteNode(int startOffset, int length, byte[] name, Node value, byte[] binary_operator) { + super(startOffset, length); + this.name = name; + this.value = value; + this.binary_operator = binary_operator; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitGlobalVariableOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator for assignment to a global variable.
+     *
+     *     $target ||= value
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class GlobalVariableOrWriteNode extends Node { + public final byte[] name; + public final Node value; + + public GlobalVariableOrWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitGlobalVariableOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents referencing a global variable.
+     *
+     *     $foo
+     *     ^^^^
+     * 
+ */ + public static final class GlobalVariableReadNode extends Node { + /** + *
+         * The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol.
+         *
+         *     $foo   # name `:$foo`
+         *
+         *     $_Test # name `:$_Test`
+         * 
+ */ + public final byte[] name; + + public GlobalVariableReadNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitGlobalVariableReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a global variable in a context that doesn't have an explicit value.
+     *
+     *     $foo, $bar = baz
+     *     ^^^^  ^^^^
+     * 
+ */ + public static final class GlobalVariableTargetNode extends Node { + public final byte[] name; + + public GlobalVariableTargetNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitGlobalVariableTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a global variable.
+     *
+     *     $foo = 1
+     *     ^^^^^^^^
+     * 
+ */ + public static final class GlobalVariableWriteNode extends Node { + /** + *
+         * The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol.
+         *
+         *     $foo = :bar  # name `:$foo`
+         *
+         *     $_Test = 123 # name `:$_Test`
+         * 
+ */ + public final byte[] name; + /** + *
+         * The value to write to the global variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     $foo = :bar
+         *            ^^^^
+         *
+         *     $-xyz = 123
+         *             ^^^
+         * 
+ */ + public final Node value; + + public GlobalVariableWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitGlobalVariableWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a hash literal.
+     *
+     *     { a => b }
+     *     ^^^^^^^^^^
+     * 
+ */ + public static final class HashNode extends Node { + /** + *
+         * The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s.
+         *
+         *     { a: b }
+         *       ^^^^
+         *
+         *     { **foo }
+         *       ^^^^^
+         * 
+ */ + @UnionType({ AssocNode.class, AssocSplatNode.class }) + public final Node[] elements; + + public HashNode(int startOffset, int length, Node[] elements) { + super(startOffset, length); + this.elements = elements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.elements) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.elements)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitHashNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("elements: "); + builder.append('\n'); + for (Node child : this.elements) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a hash pattern in pattern matching.
+     *
+     *     foo => { a: 1, b: 2 }
+     *            ^^^^^^^^^^^^^^
+     *
+     *     foo => { a: 1, b: 2, **c }
+     *            ^^^^^^^^^^^^^^^^^^^
+     *
+     *     foo => Bar[a: 1, b: 2]
+     *            ^^^^^^^^^^^^^^^
+     *
+     *     foo in { a: 1, b: 2 }
+     *            ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class HashPatternNode extends Node { + /** + *
+         * Represents the optional constant preceding the Hash.
+         *
+         *     foo => Bar[a: 1, b: 2]
+         *          ^^^
+         *
+         *     foo => Bar::Baz[a: 1, b: 2]
+         *          ^^^^^^^^
+         * 
+ */ + @Nullable + @UnionType({ ConstantPathNode.class, ConstantReadNode.class }) + public final Node constant; + /** + *
+         * Represents the explicit named hash keys and values.
+         *
+         *     foo => { a: 1, b:, ** }
+         *              ^^^^^^^^
+         * 
+ */ + public final AssocNode[] elements; + /** + *
+         * Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`.
+         *
+         *     foo => { a: 1, b:, **c }
+         *                        ^^^
+         *
+         *     foo => { a: 1, b:, ** }
+         *                        ^^
+         *
+         *     foo => { a: 1, b:, **nil }
+         *                        ^^^^^
+         * 
+ */ + @Nullable + @UnionType({ AssocSplatNode.class, NoKeywordsParameterNode.class }) + public final Node rest; + + public HashPatternNode(int startOffset, int length, Node constant, AssocNode[] elements, Node rest) { + super(startOffset, length); + this.constant = constant; + this.elements = elements; + this.rest = rest; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.constant != null) { + this.constant.accept(visitor); + } + for (Nodes.Node child : this.elements) { + child.accept(visitor); + } + if (this.rest != null) { + this.rest.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.add(this.constant); + childNodes.addAll(Arrays.asList(this.elements)); + childNodes.add(this.rest); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitHashPatternNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("constant: "); + builder.append(this.constant == null ? "null\n" : this.constant.toString(nextIndent)); + builder.append(nextIndent); + builder.append("elements: "); + builder.append('\n'); + for (Node child : this.elements) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `if` keyword, either in the block form or the modifier form, or a ternary expression.
+     *
+     *     bar if foo
+     *     ^^^^^^^^^^
+     *
+     *     if foo then bar end
+     *     ^^^^^^^^^^^^^^^^^^^
+     *
+     *     foo ? bar : baz
+     *     ^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class IfNode extends Node { + /** + *
+         * The node for the condition the `IfNode` is testing.
+         *
+         *     if foo
+         *        ^^^
+         *       bar
+         *     end
+         *
+         *     bar if foo
+         *            ^^^
+         *
+         *     foo ? bar : baz
+         *     ^^^
+         * 
+ */ + public final Node predicate; + /** + *
+         * Represents the body of statements that will be executed when the predicate is evaluated as truthy. Will be `nil` when no body is provided.
+         *
+         *     if foo
+         *       bar
+         *       ^^^
+         *       baz
+         *       ^^^
+         *     end
+         * 
+ */ + @Nullable + public final StatementsNode statements; + /** + *
+         * Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement.
+         *
+         *     if foo
+         *       bar
+         *     elsif baz
+         *     ^^^^^^^^^
+         *       qux
+         *       ^^^
+         *     end
+         *     ^^^
+         *
+         *     if foo then bar else baz end
+         *                     ^^^^^^^^^^^^
+         * 
+ */ + @Nullable + @UnionType({ ElseNode.class, IfNode.class }) + public final Node subsequent; + + public IfNode(int startOffset, int length, Node predicate, StatementsNode statements, Node subsequent) { + super(startOffset, length); + this.predicate = predicate; + this.statements = statements; + this.subsequent = subsequent; + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + this.predicate.setNewLineFlag(source, newlineMarked); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.predicate.accept(visitor); + if (this.statements != null) { + this.statements.accept(visitor); + } + if (this.subsequent != null) { + this.subsequent.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.predicate, this.statements, this.subsequent }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIfNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("predicate: "); + builder.append(this.predicate.toString(nextIndent)); + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + builder.append(nextIndent); + builder.append("subsequent: "); + builder.append(this.subsequent == null ? "null\n" : this.subsequent.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an imaginary number literal.
+     *
+     *     1.0i
+     *     ^^^^
+     * 
+ */ + public static final class ImaginaryNode extends Node { + @UnionType({ FloatNode.class, IntegerNode.class, RationalNode.class }) + public final Node numeric; + + public ImaginaryNode(int startOffset, int length, Node numeric) { + super(startOffset, length); + this.numeric = numeric; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.numeric.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.numeric }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitImaginaryNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("numeric: "); + builder.append(this.numeric.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source.
+     *
+     *     { foo: }
+     *       ^^^^
+     *
+     *     { Foo: }
+     *       ^^^^
+     *
+     *     foo in { bar: }
+     *              ^^^^
+     * 
+ */ + public static final class ImplicitNode extends Node { + @UnionType({ LocalVariableReadNode.class, CallNode.class, ConstantReadNode.class, LocalVariableTargetNode.class }) + public final Node value; + + public ImplicitNode(int startOffset, int length, Node value) { + super(startOffset, length); + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitImplicitNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents using a trailing comma to indicate an implicit rest parameter.
+     *
+     *     foo { |bar,| }
+     *               ^
+     *
+     *     foo in [bar,]
+     *                ^
+     *
+     *     for foo, in bar do end
+     *            ^
+     *
+     *     foo, = bar
+     *        ^
+     * 
+ */ + public static final class ImplicitRestNode extends Node { + + public ImplicitRestNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitImplicitRestNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `in` keyword in a case statement.
+     *
+     *     case a; in b then c end
+     *             ^^^^^^^^^^^
+     * 
+ */ + public static final class InNode extends Node { + public final Node pattern; + @Nullable + public final StatementsNode statements; + + public InNode(int startOffset, int length, Node pattern, StatementsNode statements) { + super(startOffset, length); + this.pattern = pattern; + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.pattern.accept(visitor); + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.pattern, this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("pattern: "); + builder.append(this.pattern.toString(nextIndent)); + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator on a call to the `[]` method.
+     *
+     *     foo.bar[baz] &&= value
+     *     ^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class IndexAndWriteNode extends Node { + public final short flags; + @Nullable + public final Node receiver; + @Nullable + public final ArgumentsNode arguments; + @Nullable + public final BlockArgumentNode block; + public final Node value; + + public IndexAndWriteNode(int startOffset, int length, short flags, Node receiver, ArgumentsNode arguments, BlockArgumentNode block, Node value) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.arguments = arguments; + this.block = block; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIndexAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of an assignment operator on a call to `[]`.
+     *
+     *     foo.bar[baz] += value
+     *     ^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class IndexOperatorWriteNode extends Node { + public final short flags; + @Nullable + public final Node receiver; + @Nullable + public final ArgumentsNode arguments; + @Nullable + public final BlockArgumentNode block; + public final byte[] binary_operator; + public final Node value; + + public IndexOperatorWriteNode(int startOffset, int length, short flags, Node receiver, ArgumentsNode arguments, BlockArgumentNode block, byte[] binary_operator, Node value) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.arguments = arguments; + this.block = block; + this.binary_operator = binary_operator; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIndexOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator on a call to `[]`.
+     *
+     *     foo.bar[baz] ||= value
+     *     ^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class IndexOrWriteNode extends Node { + public final short flags; + @Nullable + public final Node receiver; + @Nullable + public final ArgumentsNode arguments; + @Nullable + public final BlockArgumentNode block; + public final Node value; + + public IndexOrWriteNode(int startOffset, int length, short flags, Node receiver, ArgumentsNode arguments, BlockArgumentNode block, Node value) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.arguments = arguments; + this.block = block; + this.value = value; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.receiver != null) { + this.receiver.accept(visitor); + } + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block, this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIndexOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver == null ? "null\n" : this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to an index.
+     *
+     *     foo[bar], = 1
+     *     ^^^^^^^^
+     *
+     *     begin
+     *     rescue => foo[bar]
+     *               ^^^^^^^^
+     *     end
+     *
+     *     for foo[bar] in baz do end
+     *         ^^^^^^^^
+     * 
+ */ + public static final class IndexTargetNode extends Node { + public final short flags; + public final Node receiver; + @Nullable + public final ArgumentsNode arguments; + @Nullable + public final BlockArgumentNode block; + + public IndexTargetNode(int startOffset, int length, short flags, Node receiver, ArgumentsNode arguments, BlockArgumentNode block) { + super(startOffset, length); + this.flags = flags; + this.receiver = receiver; + this.arguments = arguments; + this.block = block; + } + + public boolean isSafeNavigation() { + return CallNodeFlags.isSafeNavigation(flags); + } + + public boolean isVariableCall() { + return CallNodeFlags.isVariableCall(flags); + } + + public boolean isAttributeWrite() { + return CallNodeFlags.isAttributeWrite(flags); + } + + public boolean isIgnoreVisibility() { + return CallNodeFlags.isIgnoreVisibility(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.receiver.accept(visitor); + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.receiver, this.arguments, this.block }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIndexTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("CallNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("receiver: "); + builder.append(this.receiver.toString(nextIndent)); + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator for assignment to an instance variable.
+     *
+     *     @target &&= value
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InstanceVariableAndWriteNode extends Node { + public final byte[] name; + public final Node value; + + public InstanceVariableAndWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInstanceVariableAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to an instance variable using an operator that isn't `=`.
+     *
+     *     @target += value
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InstanceVariableOperatorWriteNode extends Node { + public final byte[] name; + public final Node value; + public final byte[] binary_operator; + + public InstanceVariableOperatorWriteNode(int startOffset, int length, byte[] name, Node value, byte[] binary_operator) { + super(startOffset, length); + this.name = name; + this.value = value; + this.binary_operator = binary_operator; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInstanceVariableOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator for assignment to an instance variable.
+     *
+     *     @target ||= value
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InstanceVariableOrWriteNode extends Node { + public final byte[] name; + public final Node value; + + public InstanceVariableOrWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInstanceVariableOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents referencing an instance variable.
+     *
+     *     @foo
+     *     ^^^^
+     * 
+ */ + public static final class InstanceVariableReadNode extends Node { + /** + *
+         * The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+         *
+         *     @x     # name `:@x`
+         *
+         *     @_test # name `:@_test`
+         * 
+ */ + public final byte[] name; + + public InstanceVariableReadNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInstanceVariableReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to an instance variable in a context that doesn't have an explicit value.
+     *
+     *     @foo, @bar = baz
+     *     ^^^^  ^^^^
+     * 
+ */ + public static final class InstanceVariableTargetNode extends Node { + public final byte[] name; + + public InstanceVariableTargetNode(int startOffset, int length, byte[] name) { + super(startOffset, length); + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInstanceVariableTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to an instance variable.
+     *
+     *     @foo = 1
+     *     ^^^^^^^^
+     * 
+ */ + public static final class InstanceVariableWriteNode extends Node { + /** + *
+         * The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+         *
+         *     @x = :y       # name `:@x`
+         *
+         *     @_foo = "bar" # name `@_foo`
+         * 
+ */ + public final byte[] name; + /** + *
+         * The value to write to the instance variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     @foo = :bar
+         *            ^^^^
+         *
+         *     @_x = 1234
+         *           ^^^^
+         * 
+ */ + public final Node value; + + public InstanceVariableWriteNode(int startOffset, int length, byte[] name, Node value) { + super(startOffset, length); + this.name = name; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInstanceVariableWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an integer number literal.
+     *
+     *     1
+     *     ^
+     * 
+ */ + public static final class IntegerNode extends Node { + public final short flags; + /** + *
+         * The value of the integer literal as a number.
+         * 
+ */ + public final Object value; + + public IntegerNode(int startOffset, int length, short flags, Object value) { + super(startOffset, length); + this.flags = flags; + this.value = value; + } + + public boolean isBinary() { + return IntegerBaseFlags.isBinary(flags); + } + + public boolean isDecimal() { + return IntegerBaseFlags.isDecimal(flags); + } + + public boolean isOctal() { + return IntegerBaseFlags.isOctal(flags); + } + + public boolean isHexadecimal() { + return IntegerBaseFlags.isHexadecimal(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitIntegerNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("IntegerBaseFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object.
+     *
+     *     if /foo #{bar} baz/ then end
+     *        ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InterpolatedMatchLastLineNode extends Node { + public final short flags; + @UnionType({ StringNode.class, EmbeddedStatementsNode.class, EmbeddedVariableNode.class }) + public final Node[] parts; + + public InterpolatedMatchLastLineNode(int startOffset, int length, short flags, Node[] parts) { + super(startOffset, length); + this.flags = flags; + this.parts = parts; + } + + public boolean isIgnoreCase() { + return RegularExpressionFlags.isIgnoreCase(flags); + } + + public boolean isExtended() { + return RegularExpressionFlags.isExtended(flags); + } + + public boolean isMultiLine() { + return RegularExpressionFlags.isMultiLine(flags); + } + + public boolean isOnce() { + return RegularExpressionFlags.isOnce(flags); + } + + public boolean isEucJp() { + return RegularExpressionFlags.isEucJp(flags); + } + + public boolean isAscii8bit() { + return RegularExpressionFlags.isAscii8bit(flags); + } + + public boolean isWindows31j() { + return RegularExpressionFlags.isWindows31j(flags); + } + + public boolean isUtf8() { + return RegularExpressionFlags.isUtf8(flags); + } + + public boolean isForcedUtf8Encoding() { + return RegularExpressionFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return RegularExpressionFlags.isForcedBinaryEncoding(flags); + } + + public boolean isForcedUsAsciiEncoding() { + return RegularExpressionFlags.isForcedUsAsciiEncoding(flags); + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + Node first = this.parts.length > 0 ? this.parts[0] : null; + if (first != null) { + first.setNewLineFlag(source, newlineMarked); + } + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.parts) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.parts)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInterpolatedMatchLastLineNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("RegularExpressionFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("parts: "); + builder.append('\n'); + for (Node child : this.parts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a regular expression literal that contains interpolation.
+     *
+     *     /foo #{bar} baz/
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InterpolatedRegularExpressionNode extends Node { + public final short flags; + @UnionType({ StringNode.class, EmbeddedStatementsNode.class, EmbeddedVariableNode.class }) + public final Node[] parts; + + public InterpolatedRegularExpressionNode(int startOffset, int length, short flags, Node[] parts) { + super(startOffset, length); + this.flags = flags; + this.parts = parts; + } + + public boolean isIgnoreCase() { + return RegularExpressionFlags.isIgnoreCase(flags); + } + + public boolean isExtended() { + return RegularExpressionFlags.isExtended(flags); + } + + public boolean isMultiLine() { + return RegularExpressionFlags.isMultiLine(flags); + } + + public boolean isOnce() { + return RegularExpressionFlags.isOnce(flags); + } + + public boolean isEucJp() { + return RegularExpressionFlags.isEucJp(flags); + } + + public boolean isAscii8bit() { + return RegularExpressionFlags.isAscii8bit(flags); + } + + public boolean isWindows31j() { + return RegularExpressionFlags.isWindows31j(flags); + } + + public boolean isUtf8() { + return RegularExpressionFlags.isUtf8(flags); + } + + public boolean isForcedUtf8Encoding() { + return RegularExpressionFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return RegularExpressionFlags.isForcedBinaryEncoding(flags); + } + + public boolean isForcedUsAsciiEncoding() { + return RegularExpressionFlags.isForcedUsAsciiEncoding(flags); + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + Node first = this.parts.length > 0 ? this.parts[0] : null; + if (first != null) { + first.setNewLineFlag(source, newlineMarked); + } + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.parts) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.parts)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInterpolatedRegularExpressionNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("RegularExpressionFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("parts: "); + builder.append('\n'); + for (Node child : this.parts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a string literal that contains interpolation.
+     *
+     *     "foo #{bar} baz"
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InterpolatedStringNode extends Node { + public final short flags; + @UnionType({ StringNode.class, EmbeddedStatementsNode.class, EmbeddedVariableNode.class, InterpolatedStringNode.class }) + public final Node[] parts; + + public InterpolatedStringNode(int startOffset, int length, short flags, Node[] parts) { + super(startOffset, length); + this.flags = flags; + this.parts = parts; + } + + public boolean isFrozen() { + return InterpolatedStringNodeFlags.isFrozen(flags); + } + + public boolean isMutable() { + return InterpolatedStringNodeFlags.isMutable(flags); + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + Node first = this.parts.length > 0 ? this.parts[0] : null; + if (first != null) { + first.setNewLineFlag(source, newlineMarked); + } + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.parts) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.parts)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInterpolatedStringNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("InterpolatedStringNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("parts: "); + builder.append('\n'); + for (Node child : this.parts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a symbol literal that contains interpolation.
+     *
+     *     :"foo #{bar} baz"
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InterpolatedSymbolNode extends Node { + @UnionType({ StringNode.class, EmbeddedStatementsNode.class, EmbeddedVariableNode.class }) + public final Node[] parts; + + public InterpolatedSymbolNode(int startOffset, int length, Node[] parts) { + super(startOffset, length); + this.parts = parts; + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + Node first = this.parts.length > 0 ? this.parts[0] : null; + if (first != null) { + first.setNewLineFlag(source, newlineMarked); + } + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.parts) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.parts)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInterpolatedSymbolNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("parts: "); + builder.append('\n'); + for (Node child : this.parts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents an xstring literal that contains interpolation.
+     *
+     *     `foo #{bar} baz`
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class InterpolatedXStringNode extends Node { + @UnionType({ StringNode.class, EmbeddedStatementsNode.class, EmbeddedVariableNode.class }) + public final Node[] parts; + + public InterpolatedXStringNode(int startOffset, int length, Node[] parts) { + super(startOffset, length); + this.parts = parts; + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + Node first = this.parts.length > 0 ? this.parts[0] : null; + if (first != null) { + first.setNewLineFlag(source, newlineMarked); + } + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.parts) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.parts)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitInterpolatedXStringNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("parts: "); + builder.append('\n'); + for (Node child : this.parts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents reading from the implicit `it` local variable.
+     *
+     *     -> { it }
+     *          ^^
+     * 
+ */ + public static final class ItLocalVariableReadNode extends Node { + + public ItLocalVariableReadNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitItLocalVariableReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda.
+     *
+     *     -> { it + it }
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ItParametersNode extends Node { + + public ItParametersNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitItParametersNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents a hash literal without opening and closing braces.
+     *
+     *     foo(a: b)
+     *         ^^^^
+     * 
+ */ + public static final class KeywordHashNode extends Node { + public final short flags; + @UnionType({ AssocNode.class, AssocSplatNode.class }) + public final Node[] elements; + + public KeywordHashNode(int startOffset, int length, short flags, Node[] elements) { + super(startOffset, length); + this.flags = flags; + this.elements = elements; + } + + public boolean isSymbolKeys() { + return KeywordHashNodeFlags.isSymbolKeys(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.elements) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.elements)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitKeywordHashNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("KeywordHashNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("elements: "); + builder.append('\n'); + for (Node child : this.elements) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a keyword rest parameter to a method, block, or lambda definition.
+     *
+     *     def a(**b)
+     *           ^^^
+     *     end
+     * 
+ */ + public static final class KeywordRestParameterNode extends Node { + public final short flags; + @Nullable + public final byte[] name; + + public KeywordRestParameterNode(int startOffset, int length, short flags, byte[] name) { + super(startOffset, length); + this.flags = flags; + this.name = name; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitKeywordRestParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append(this.name == null ? "null" : "\"" + asString(this.name) + "\""); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents using a lambda literal (not the lambda method call).
+     *
+     *     ->(value) { value * 2 }
+     *     ^^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class LambdaNode extends Node { + public final byte[][] locals; + @Nullable + @UnionType({ BlockParametersNode.class, NumberedParametersNode.class, ItParametersNode.class }) + public final Node parameters; + @Nullable + @UnionType({ StatementsNode.class, BeginNode.class }) + public final Node body; + + public LambdaNode(int startOffset, int length, byte[][] locals, Node parameters, Node body) { + super(startOffset, length); + this.locals = locals; + this.parameters = parameters; + this.body = body; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.parameters != null) { + this.parameters.accept(visitor); + } + if (this.body != null) { + this.body.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.parameters, this.body }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitLambdaNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (byte[] constant : this.locals) { + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); + } + builder.append(nextIndent); + builder.append("parameters: "); + builder.append(this.parameters == null ? "null\n" : this.parameters.toString(nextIndent)); + builder.append(nextIndent); + builder.append("body: "); + builder.append(this.body == null ? "null\n" : this.body.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `&&=` operator for assignment to a local variable.
+     *
+     *     target &&= value
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class LocalVariableAndWriteNode extends Node { + public final Node value; + public final byte[] name; + public final int depth; + + public LocalVariableAndWriteNode(int startOffset, int length, Node value, byte[] name, int depth) { + super(startOffset, length); + this.value = value; + this.name = name; + this.depth = depth; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitLocalVariableAndWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("depth: "); + builder.append(this.depth); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents assigning to a local variable using an operator that isn't `=`.
+     *
+     *     target += value
+     *     ^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class LocalVariableOperatorWriteNode extends Node { + public final Node value; + public final byte[] name; + public final byte[] binary_operator; + public final int depth; + + public LocalVariableOperatorWriteNode(int startOffset, int length, Node value, byte[] name, byte[] binary_operator, int depth) { + super(startOffset, length); + this.value = value; + this.name = name; + this.binary_operator = binary_operator; + this.depth = depth; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitLocalVariableOperatorWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("binary_operator: "); + builder.append('"').append(asString(this.binary_operator)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("depth: "); + builder.append(this.depth); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||=` operator for assignment to a local variable.
+     *
+     *     target ||= value
+     *     ^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class LocalVariableOrWriteNode extends Node { + public final Node value; + public final byte[] name; + public final int depth; + + public LocalVariableOrWriteNode(int startOffset, int length, Node value, byte[] name, int depth) { + super(startOffset, length); + this.value = value; + this.name = name; + this.depth = depth; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitLocalVariableOrWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("depth: "); + builder.append(this.depth); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call.
+     *
+     *     foo
+     *     ^^^
+     * 
+ */ + public static final class LocalVariableReadNode extends Node { + /** + *
+         * The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+         *
+         *     x      # name `:x`
+         *
+         *     _Test  # name `:_Test`
+         *
+         * Note that this can also be an underscore followed by a number for the default block parameters.
+         *
+         *     _1     # name `:_1`
+         * 
+ */ + public final byte[] name; + /** + *
+         * The number of visible scopes that should be searched to find the origin of this local variable.
+         *
+         *     foo = 1; foo # depth 0
+         *
+         *     bar = 2; tap { bar } # depth 1
+         *
+         * The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md).
+         * 
+ */ + public final int depth; + + public LocalVariableReadNode(int startOffset, int length, byte[] name, int depth) { + super(startOffset, length); + this.name = name; + this.depth = depth; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitLocalVariableReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("depth: "); + builder.append(this.depth); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a local variable in a context that doesn't have an explicit value.
+     *
+     *     foo, bar = baz
+     *     ^^^  ^^^
+     *
+     *     foo => baz
+     *            ^^^
+     * 
+ */ + public static final class LocalVariableTargetNode extends Node { + public final byte[] name; + public final int depth; + + public LocalVariableTargetNode(int startOffset, int length, byte[] name, int depth) { + super(startOffset, length); + this.name = name; + this.depth = depth; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitLocalVariableTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("depth: "); + builder.append(this.depth); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents writing to a local variable.
+     *
+     *     foo = 1
+     *     ^^^^^^^
+     * 
+ */ + public static final class LocalVariableWriteNode extends Node { + /** + *
+         * The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+         *
+         *     foo = :bar # name `:foo`
+         *
+         *     abc = 123  # name `:abc`
+         * 
+ */ + public final byte[] name; + /** + *
+         * The number of semantic scopes we have to traverse to find the declaration of this variable.
+         *
+         *     foo = 1         # depth 0
+         *
+         *     tap { foo = 1 } # depth 1
+         *
+         * The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md).
+         * 
+ */ + public final int depth; + /** + *
+         * The value to write to the local variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     foo = :bar
+         *           ^^^^
+         *
+         *     abc = 1234
+         *           ^^^^
+         *
+         * Note that since the name of a local variable is known before the value is parsed, it is valid for a local variable to appear within the value of its own write.
+         *
+         *     foo = foo
+         * 
+ */ + public final Node value; + + public LocalVariableWriteNode(int startOffset, int length, byte[] name, int depth, Node value) { + super(startOffset, length); + this.name = name; + this.depth = depth; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitLocalVariableWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("depth: "); + builder.append(this.depth); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object.
+     *
+     *     if /foo/i then end
+     *        ^^^^^^
+     * 
+ */ + public static final class MatchLastLineNode extends Node { + public final short flags; + public final byte[] unescaped; + + public MatchLastLineNode(int startOffset, int length, short flags, byte[] unescaped) { + super(startOffset, length); + this.flags = flags; + this.unescaped = unescaped; + } + + public boolean isIgnoreCase() { + return RegularExpressionFlags.isIgnoreCase(flags); + } + + public boolean isExtended() { + return RegularExpressionFlags.isExtended(flags); + } + + public boolean isMultiLine() { + return RegularExpressionFlags.isMultiLine(flags); + } + + public boolean isOnce() { + return RegularExpressionFlags.isOnce(flags); + } + + public boolean isEucJp() { + return RegularExpressionFlags.isEucJp(flags); + } + + public boolean isAscii8bit() { + return RegularExpressionFlags.isAscii8bit(flags); + } + + public boolean isWindows31j() { + return RegularExpressionFlags.isWindows31j(flags); + } + + public boolean isUtf8() { + return RegularExpressionFlags.isUtf8(flags); + } + + public boolean isForcedUtf8Encoding() { + return RegularExpressionFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return RegularExpressionFlags.isForcedBinaryEncoding(flags); + } + + public boolean isForcedUsAsciiEncoding() { + return RegularExpressionFlags.isForcedUsAsciiEncoding(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitMatchLastLineNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("RegularExpressionFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("unescaped: "); + builder.append('"' + asString(this.unescaped) + '"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the modifier `in` operator.
+     *
+     *     foo in bar
+     *     ^^^^^^^^^^
+     * 
+ */ + public static final class MatchPredicateNode extends Node { + public final Node value; + public final Node pattern; + + public MatchPredicateNode(int startOffset, int length, Node value, Node pattern) { + super(startOffset, length); + this.value = value; + this.pattern = pattern; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + this.pattern.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value, this.pattern }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitMatchPredicateNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("pattern: "); + builder.append(this.pattern.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `=>` operator.
+     *
+     *     foo => bar
+     *     ^^^^^^^^^^
+     * 
+ */ + public static final class MatchRequiredNode extends Node { + /** + *
+         * Represents the left-hand side of the operator.
+         *
+         *     foo => bar
+         *     ^^^
+         * 
+ */ + public final Node value; + /** + *
+         * Represents the right-hand side of the operator. The type of the node depends on the expression.
+         *
+         * Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`.
+         *
+         *     foo => a # This is equivalent to writing `a = foo`
+         *            ^
+         *
+         * Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant.
+         *
+         *     foo => [a]
+         *            ^^^
+         *
+         *     foo => a, b
+         *            ^^^^
+         *
+         *     foo => Bar[a, b]
+         *            ^^^^^^^^^
+         *
+         * If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead.
+         *
+         *     foo => *, 1, *a
+         *            ^^^^^
+         *
+         * Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`.
+         *
+         *     foo => { a: 1, b: }
+         *
+         *     foo => Bar[a: 1, b:]
+         *
+         *     foo => Bar[**]
+         *
+         * To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode`
+         *
+         *     foo => ^a
+         *            ^^
+         *
+         * Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`.
+         *
+         *     foo => ^(a + 1)
+         *
+         * Anything else will result in the regular node for that expression, for example a `ConstantReadNode`.
+         *
+         *     foo => CONST
+         * 
+ */ + public final Node pattern; + + public MatchRequiredNode(int startOffset, int length, Node value, Node pattern) { + super(startOffset, length); + this.value = value; + this.pattern = pattern; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + this.pattern.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value, this.pattern }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitMatchRequiredNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + builder.append(nextIndent); + builder.append("pattern: "); + builder.append(this.pattern.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents writing local variables using a regular expression match with named capture groups.
+     *
+     *     /(?<foo>bar)/ =~ baz
+     *     ^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class MatchWriteNode extends Node { + public final CallNode call; + public final LocalVariableTargetNode[] targets; + + public MatchWriteNode(int startOffset, int length, CallNode call, LocalVariableTargetNode[] targets) { + super(startOffset, length); + this.call = call; + this.targets = targets; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.call.accept(visitor); + for (Nodes.Node child : this.targets) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.add(this.call); + childNodes.addAll(Arrays.asList(this.targets)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitMatchWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("call: "); + builder.append(this.call.toString(nextIndent)); + builder.append(nextIndent); + builder.append("targets: "); + builder.append('\n'); + for (Node child : this.targets) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a node that is missing from the source and results in a syntax error.
+     * 
+ */ + public static final class MissingNode extends Node { + + public MissingNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitMissingNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents a module declaration involving the `module` keyword.
+     *
+     *     module Foo end
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class ModuleNode extends Node { + public final byte[][] locals; + @UnionType({ ConstantReadNode.class, ConstantPathNode.class }) + public final Node constant_path; + @Nullable + @UnionType({ StatementsNode.class, BeginNode.class }) + public final Node body; + public final byte[] name; + + public ModuleNode(int startOffset, int length, byte[][] locals, Node constant_path, Node body, byte[] name) { + super(startOffset, length); + this.locals = locals; + this.constant_path = constant_path; + this.body = body; + this.name = name; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.constant_path.accept(visitor); + if (this.body != null) { + this.body.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.constant_path, this.body }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitModuleNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (byte[] constant : this.locals) { + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); + } + builder.append(nextIndent); + builder.append("constant_path: "); + builder.append(this.constant_path.toString(nextIndent)); + builder.append(nextIndent); + builder.append("body: "); + builder.append(this.body == null ? "null\n" : this.body.toString(nextIndent)); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents a multi-target expression.
+     *
+     *     a, (b, c) = 1, 2, 3
+     *        ^^^^^^
+     *
+     * This can be a part of `MultiWriteNode` as above, or the target of a `for` loop
+     *
+     *     for a, b in [[1, 2], [3, 4]]
+     *         ^^^^
+     * 
+ */ + public static final class MultiTargetNode extends Node { + /** + *
+         * Represents the targets expressions before a splat node.
+         *
+         *     a, (b, c, *) = 1, 2, 3, 4, 5
+         *         ^^^^
+         *
+         * The splat node can be absent, in that case all target expressions are in the left field.
+         *
+         *     a, (b, c) = 1, 2, 3, 4, 5
+         *         ^^^^
+         * 
+ */ + @UnionType({ LocalVariableTargetNode.class, InstanceVariableTargetNode.class, ClassVariableTargetNode.class, GlobalVariableTargetNode.class, ConstantTargetNode.class, ConstantPathTargetNode.class, CallTargetNode.class, IndexTargetNode.class, MultiTargetNode.class, RequiredParameterNode.class }) + public final Node[] lefts; + /** + *
+         * Represents a splat node in the target expression.
+         *
+         *     a, (b, *c) = 1, 2, 3, 4
+         *            ^^
+         *
+         * The variable can be empty, this results in a `SplatNode` with a `nil` expression field.
+         *
+         *     a, (b, *) = 1, 2, 3, 4
+         *            ^
+         *
+         * If the `*` is omitted, this field will contain an `ImplicitRestNode`
+         *
+         *     a, (b,) = 1, 2, 3, 4
+         *          ^
+         * 
+ */ + @Nullable + @UnionType({ ImplicitRestNode.class, SplatNode.class }) + public final Node rest; + /** + *
+         * Represents the targets expressions after a splat node.
+         *
+         *     a, (*, b, c) = 1, 2, 3, 4, 5
+         *            ^^^^
+         * 
+ */ + @UnionType({ LocalVariableTargetNode.class, InstanceVariableTargetNode.class, ClassVariableTargetNode.class, GlobalVariableTargetNode.class, ConstantTargetNode.class, ConstantPathTargetNode.class, CallTargetNode.class, IndexTargetNode.class, MultiTargetNode.class, RequiredParameterNode.class }) + public final Node[] rights; + + public MultiTargetNode(int startOffset, int length, Node[] lefts, Node rest, Node[] rights) { + super(startOffset, length); + this.lefts = lefts; + this.rest = rest; + this.rights = rights; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.lefts) { + child.accept(visitor); + } + if (this.rest != null) { + this.rest.accept(visitor); + } + for (Nodes.Node child : this.rights) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.lefts)); + childNodes.add(this.rest); + childNodes.addAll(Arrays.asList(this.rights)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitMultiTargetNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("lefts: "); + builder.append('\n'); + for (Node child : this.lefts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); + builder.append(nextIndent); + builder.append("rights: "); + builder.append('\n'); + for (Node child : this.rights) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a write to a multi-target expression.
+     *
+     *     a, b, c = 1, 2, 3
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class MultiWriteNode extends Node { + /** + *
+         * Represents the targets expressions before a splat node.
+         *
+         *     a, b, * = 1, 2, 3, 4, 5
+         *     ^^^^
+         *
+         * The splat node can be absent, in that case all target expressions are in the left field.
+         *
+         *     a, b, c = 1, 2, 3, 4, 5
+         *     ^^^^^^^
+         * 
+ */ + @UnionType({ LocalVariableTargetNode.class, InstanceVariableTargetNode.class, ClassVariableTargetNode.class, GlobalVariableTargetNode.class, ConstantTargetNode.class, ConstantPathTargetNode.class, CallTargetNode.class, IndexTargetNode.class, MultiTargetNode.class }) + public final Node[] lefts; + /** + *
+         * Represents a splat node in the target expression.
+         *
+         *     a, b, *c = 1, 2, 3, 4
+         *           ^^
+         *
+         * The variable can be empty, this results in a `SplatNode` with a `nil` expression field.
+         *
+         *     a, b, * = 1, 2, 3, 4
+         *           ^
+         *
+         * If the `*` is omitted, this field will contain an `ImplicitRestNode`
+         *
+         *     a, b, = 1, 2, 3, 4
+         *         ^
+         * 
+ */ + @Nullable + @UnionType({ ImplicitRestNode.class, SplatNode.class }) + public final Node rest; + /** + *
+         * Represents the targets expressions after a splat node.
+         *
+         *     a, *, b, c = 1, 2, 3, 4, 5
+         *           ^^^^
+         * 
+ */ + @UnionType({ LocalVariableTargetNode.class, InstanceVariableTargetNode.class, ClassVariableTargetNode.class, GlobalVariableTargetNode.class, ConstantTargetNode.class, ConstantPathTargetNode.class, CallTargetNode.class, IndexTargetNode.class, MultiTargetNode.class }) + public final Node[] rights; + /** + *
+         * The value to write to the targets. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     a, b, c = 1, 2, 3
+         *               ^^^^^^^
+         * 
+ */ + public final Node value; + + public MultiWriteNode(int startOffset, int length, Node[] lefts, Node rest, Node[] rights, Node value) { + super(startOffset, length); + this.lefts = lefts; + this.rest = rest; + this.rights = rights; + this.value = value; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.lefts) { + child.accept(visitor); + } + if (this.rest != null) { + this.rest.accept(visitor); + } + for (Nodes.Node child : this.rights) { + child.accept(visitor); + } + this.value.accept(visitor); + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.lefts)); + childNodes.add(this.rest); + childNodes.addAll(Arrays.asList(this.rights)); + childNodes.add(this.value); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitMultiWriteNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("lefts: "); + builder.append('\n'); + for (Node child : this.lefts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); + builder.append(nextIndent); + builder.append("rights: "); + builder.append('\n'); + for (Node child : this.rights) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `next` keyword.
+     *
+     *     next 1
+     *     ^^^^^^
+     * 
+ */ + public static final class NextNode extends Node { + @Nullable + public final ArgumentsNode arguments; + + public NextNode(int startOffset, int length, ArgumentsNode arguments) { + super(startOffset, length); + this.arguments = arguments; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.arguments != null) { + this.arguments.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.arguments }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitNextNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `nil` keyword.
+     *
+     *     nil
+     *     ^^^
+     * 
+ */ + public static final class NilNode extends Node { + + public NilNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitNilNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of `&nil` inside method arguments.
+     *
+     *     def a(&nil)
+     *           ^^^^
+     *     end
+     * 
+ */ + public static final class NoBlockParameterNode extends Node { + + public NoBlockParameterNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitNoBlockParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of `**nil` inside method arguments.
+     *
+     *     def a(**nil)
+     *           ^^^^^
+     *     end
+     * 
+ */ + public static final class NoKeywordsParameterNode extends Node { + + public NoKeywordsParameterNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitNoKeywordsParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents an implicit set of parameters through the use of numbered parameters within a block or lambda.
+     *
+     *     -> { _1 + _2 }
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class NumberedParametersNode extends Node { + public final int maximum; + + public NumberedParametersNode(int startOffset, int length, int maximum) { + super(startOffset, length); + this.maximum = maximum; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitNumberedParametersNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("maximum: "); + builder.append(this.maximum); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents reading a numbered reference to a capture in the previous match.
+     *
+     *     $1
+     *     ^^
+     * 
+ */ + public static final class NumberedReferenceReadNode extends Node { + /** + *
+         * The (1-indexed, from the left) number of the capture group. Numbered references that are too large result in this value being `0`.
+         *
+         *     $1          # number `1`
+         *
+         *     $5432       # number `5432`
+         *
+         *     $4294967296 # number `0`
+         * 
+ */ + public final int number; + + public NumberedReferenceReadNode(int startOffset, int length, int number) { + super(startOffset, length); + this.number = number; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitNumberedReferenceReadNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("number: "); + builder.append(this.number); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents an optional keyword parameter to a method, block, or lambda definition.
+     *
+     *     def a(b: 1)
+     *           ^^^^
+     *     end
+     * 
+ */ + public static final class OptionalKeywordParameterNode extends Node { + public final short flags; + public final byte[] name; + public final Node value; + + public OptionalKeywordParameterNode(int startOffset, int length, short flags, byte[] name, Node value) { + super(startOffset, length); + this.flags = flags; + this.name = name; + this.value = value; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitOptionalKeywordParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an optional parameter to a method, block, or lambda definition.
+     *
+     *     def a(b = 1)
+     *           ^^^^^
+     *     end
+     * 
+ */ + public static final class OptionalParameterNode extends Node { + public final short flags; + public final byte[] name; + public final Node value; + + public OptionalParameterNode(int startOffset, int length, short flags, byte[] name, Node value) { + super(startOffset, length); + this.flags = flags; + this.name = name; + this.value = value; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.value.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.value }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitOptionalParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + builder.append(nextIndent); + builder.append("value: "); + builder.append(this.value.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `||` operator or the `or` keyword.
+     *
+     *     left or right
+     *     ^^^^^^^^^^^^^
+     * 
+ */ + public static final class OrNode extends Node { + /** + *
+         * Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     left or right
+         *     ^^^^
+         *
+         *     1 || 2
+         *     ^
+         * 
+ */ + public final Node left; + /** + *
+         * Represents the right side of the expression.
+         *
+         *     left || right
+         *             ^^^^^
+         *
+         *     1 or 2
+         *          ^
+         * 
+ */ + public final Node right; + + public OrNode(int startOffset, int length, Node left, Node right) { + super(startOffset, length); + this.left = left; + this.right = right; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.left.accept(visitor); + this.right.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.left, this.right }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitOrNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("left: "); + builder.append(this.left.toString(nextIndent)); + builder.append(nextIndent); + builder.append("right: "); + builder.append(this.right.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the list of parameters on a method, block, or lambda definition.
+     *
+     *     def a(b, c, d)
+     *           ^^^^^^^
+     *     end
+     * 
+ */ + public static final class ParametersNode extends Node { + @UnionType({ RequiredParameterNode.class, MultiTargetNode.class }) + public final Node[] requireds; + public final OptionalParameterNode[] optionals; + @Nullable + @UnionType({ RestParameterNode.class, ImplicitRestNode.class }) + public final Node rest; + @UnionType({ RequiredParameterNode.class, MultiTargetNode.class }) + public final Node[] posts; + @UnionType({ RequiredKeywordParameterNode.class, OptionalKeywordParameterNode.class }) + public final Node[] keywords; + @Nullable + @UnionType({ KeywordRestParameterNode.class, ForwardingParameterNode.class, NoKeywordsParameterNode.class }) + public final Node keyword_rest; + @Nullable + @UnionType({ BlockParameterNode.class, NoBlockParameterNode.class }) + public final Node block; + + public ParametersNode(int startOffset, int length, Node[] requireds, OptionalParameterNode[] optionals, Node rest, Node[] posts, Node[] keywords, Node keyword_rest, Node block) { + super(startOffset, length); + this.requireds = requireds; + this.optionals = optionals; + this.rest = rest; + this.posts = posts; + this.keywords = keywords; + this.keyword_rest = keyword_rest; + this.block = block; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.requireds) { + child.accept(visitor); + } + for (Nodes.Node child : this.optionals) { + child.accept(visitor); + } + if (this.rest != null) { + this.rest.accept(visitor); + } + for (Nodes.Node child : this.posts) { + child.accept(visitor); + } + for (Nodes.Node child : this.keywords) { + child.accept(visitor); + } + if (this.keyword_rest != null) { + this.keyword_rest.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.requireds)); + childNodes.addAll(Arrays.asList(this.optionals)); + childNodes.add(this.rest); + childNodes.addAll(Arrays.asList(this.posts)); + childNodes.addAll(Arrays.asList(this.keywords)); + childNodes.add(this.keyword_rest); + childNodes.add(this.block); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitParametersNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("requireds: "); + builder.append('\n'); + for (Node child : this.requireds) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("optionals: "); + builder.append('\n'); + for (Node child : this.optionals) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("rest: "); + builder.append(this.rest == null ? "null\n" : this.rest.toString(nextIndent)); + builder.append(nextIndent); + builder.append("posts: "); + builder.append('\n'); + for (Node child : this.posts) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("keywords: "); + builder.append('\n'); + for (Node child : this.keywords) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("keyword_rest: "); + builder.append(this.keyword_rest == null ? "null\n" : this.keyword_rest.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a parenthesized expression
+     *
+     *     (10 + 34)
+     *     ^^^^^^^^^
+     * 
+ */ + public static final class ParenthesesNode extends Node { + public final short flags; + @Nullable + public final Node body; + + public ParenthesesNode(int startOffset, int length, short flags, Node body) { + super(startOffset, length); + this.flags = flags; + this.body = body; + } + + public boolean isMultipleStatements() { + return ParenthesesNodeFlags.isMultipleStatements(flags); + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + // Never mark ParenthesesNode with a newline flag, mark children instead + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.body != null) { + this.body.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.body }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitParenthesesNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParenthesesNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("body: "); + builder.append(this.body == null ? "null\n" : this.body.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `^` operator for pinning an expression in a pattern matching expression.
+     *
+     *     foo in ^(bar)
+     *            ^^^^^^
+     * 
+ */ + public static final class PinnedExpressionNode extends Node { + /** + *
+         * The expression used in the pinned expression
+         *
+         *     foo in ^(bar)
+         *              ^^^
+         * 
+ */ + public final Node expression; + + public PinnedExpressionNode(int startOffset, int length, Node expression) { + super(startOffset, length); + this.expression = expression; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.expression.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.expression }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitPinnedExpressionNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("expression: "); + builder.append(this.expression.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `^` operator for pinning a variable in a pattern matching expression.
+     *
+     *     foo in ^bar
+     *            ^^^^
+     * 
+ */ + public static final class PinnedVariableNode extends Node { + /** + *
+         * The variable used in the pinned expression
+         *
+         *     foo in ^bar
+         *             ^^^
+         * 
+ */ + @UnionType({ LocalVariableReadNode.class, InstanceVariableReadNode.class, ClassVariableReadNode.class, GlobalVariableReadNode.class, BackReferenceReadNode.class, NumberedReferenceReadNode.class, ItLocalVariableReadNode.class }) + public final Node variable; + + public PinnedVariableNode(int startOffset, int length, Node variable) { + super(startOffset, length); + this.variable = variable; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.variable.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.variable }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitPinnedVariableNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("variable: "); + builder.append(this.variable.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `END` keyword.
+     *
+     *     END { foo }
+     *     ^^^^^^^^^^^
+     * 
+ */ + public static final class PostExecutionNode extends Node { + @Nullable + public final StatementsNode statements; + + public PostExecutionNode(int startOffset, int length, StatementsNode statements) { + super(startOffset, length); + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitPostExecutionNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `BEGIN` keyword.
+     *
+     *     BEGIN { foo }
+     *     ^^^^^^^^^^^^^
+     * 
+ */ + public static final class PreExecutionNode extends Node { + @Nullable + public final StatementsNode statements; + + public PreExecutionNode(int startOffset, int length, StatementsNode statements) { + super(startOffset, length); + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitPreExecutionNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * The top level node of any parse tree.
+     * 
+ */ + public static final class ProgramNode extends Node { + public final byte[][] locals; + public final StatementsNode statements; + + public ProgramNode(int startOffset, int length, byte[][] locals, StatementsNode statements) { + super(startOffset, length); + this.locals = locals; + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.statements.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitProgramNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (byte[] constant : this.locals) { + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); + } + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `..` or `...` operators.
+     *
+     *     1..2
+     *     ^^^^
+     *
+     *     c if a =~ /left/ ... b =~ /right/
+     *          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class RangeNode extends Node { + public final short flags; + /** + *
+         * The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     1...
+         *     ^
+         *
+         *     hello...goodbye
+         *     ^^^^^
+         * 
+ */ + @Nullable + public final Node left; + /** + *
+         * The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     ..5
+         *       ^
+         *
+         *     1...foo
+         *         ^^^
+         * If neither right-hand or left-hand side was included, this will be a MissingNode.
+         * 
+ */ + @Nullable + public final Node right; + + public RangeNode(int startOffset, int length, short flags, Node left, Node right) { + super(startOffset, length); + this.flags = flags; + this.left = left; + this.right = right; + } + + public boolean isExcludeEnd() { + return RangeFlags.isExcludeEnd(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.left != null) { + this.left.accept(visitor); + } + if (this.right != null) { + this.right.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.left, this.right }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRangeNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("RangeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("left: "); + builder.append(this.left == null ? "null\n" : this.left.toString(nextIndent)); + builder.append(nextIndent); + builder.append("right: "); + builder.append(this.right == null ? "null\n" : this.right.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a rational number literal.
+     *
+     *     1.0r
+     *     ^^^^
+     * 
+ */ + public static final class RationalNode extends Node { + public final short flags; + /** + *
+         * The numerator of the rational number.
+         *
+         *     1.5r # numerator 3
+         * 
+ */ + public final Object numerator; + /** + *
+         * The denominator of the rational number.
+         *
+         *     1.5r # denominator 2
+         * 
+ */ + public final Object denominator; + + public RationalNode(int startOffset, int length, short flags, Object numerator, Object denominator) { + super(startOffset, length); + this.flags = flags; + this.numerator = numerator; + this.denominator = denominator; + } + + public boolean isBinary() { + return IntegerBaseFlags.isBinary(flags); + } + + public boolean isDecimal() { + return IntegerBaseFlags.isDecimal(flags); + } + + public boolean isOctal() { + return IntegerBaseFlags.isOctal(flags); + } + + public boolean isHexadecimal() { + return IntegerBaseFlags.isHexadecimal(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRationalNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("IntegerBaseFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("numerator: "); + builder.append(this.numerator); + builder.append('\n'); + builder.append(nextIndent); + builder.append("denominator: "); + builder.append(this.denominator); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `redo` keyword.
+     *
+     *     redo
+     *     ^^^^
+     * 
+ */ + public static final class RedoNode extends Node { + + public RedoNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRedoNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents a regular expression literal with no interpolation.
+     *
+     *     /foo/i
+     *     ^^^^^^
+     * 
+ */ + public static final class RegularExpressionNode extends Node { + public final short flags; + public final byte[] unescaped; + + public RegularExpressionNode(int startOffset, int length, short flags, byte[] unescaped) { + super(startOffset, length); + this.flags = flags; + this.unescaped = unescaped; + } + + public boolean isIgnoreCase() { + return RegularExpressionFlags.isIgnoreCase(flags); + } + + public boolean isExtended() { + return RegularExpressionFlags.isExtended(flags); + } + + public boolean isMultiLine() { + return RegularExpressionFlags.isMultiLine(flags); + } + + public boolean isOnce() { + return RegularExpressionFlags.isOnce(flags); + } + + public boolean isEucJp() { + return RegularExpressionFlags.isEucJp(flags); + } + + public boolean isAscii8bit() { + return RegularExpressionFlags.isAscii8bit(flags); + } + + public boolean isWindows31j() { + return RegularExpressionFlags.isWindows31j(flags); + } + + public boolean isUtf8() { + return RegularExpressionFlags.isUtf8(flags); + } + + public boolean isForcedUtf8Encoding() { + return RegularExpressionFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return RegularExpressionFlags.isForcedBinaryEncoding(flags); + } + + public boolean isForcedUsAsciiEncoding() { + return RegularExpressionFlags.isForcedUsAsciiEncoding(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRegularExpressionNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("RegularExpressionFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("unescaped: "); + builder.append('"' + asString(this.unescaped) + '"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents a required keyword parameter to a method, block, or lambda definition.
+     *
+     *     def a(b: )
+     *           ^^
+     *     end
+     * 
+ */ + public static final class RequiredKeywordParameterNode extends Node { + public final short flags; + public final byte[] name; + + public RequiredKeywordParameterNode(int startOffset, int length, short flags, byte[] name) { + super(startOffset, length); + this.flags = flags; + this.name = name; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRequiredKeywordParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents a required parameter to a method, block, or lambda definition.
+     *
+     *     def a(b)
+     *           ^
+     *     end
+     * 
+ */ + public static final class RequiredParameterNode extends Node { + public final short flags; + public final byte[] name; + + public RequiredParameterNode(int startOffset, int length, short flags, byte[] name) { + super(startOffset, length); + this.flags = flags; + this.name = name; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRequiredParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append('"').append(asString(this.name)).append('"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents an expression modified with a rescue.
+     *
+     *     foo rescue nil
+     *     ^^^^^^^^^^^^^^
+     * 
+ */ + public static final class RescueModifierNode extends Node { + public final Node expression; + public final Node rescue_expression; + + public RescueModifierNode(int startOffset, int length, Node expression, Node rescue_expression) { + super(startOffset, length); + this.expression = expression; + this.rescue_expression = rescue_expression; + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + this.expression.setNewLineFlag(source, newlineMarked); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.expression.accept(visitor); + this.rescue_expression.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.expression, this.rescue_expression }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRescueModifierNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("expression: "); + builder.append(this.expression.toString(nextIndent)); + builder.append(nextIndent); + builder.append("rescue_expression: "); + builder.append(this.rescue_expression.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a rescue statement.
+     *
+     *     begin
+     *     rescue Foo, *splat, Bar => ex
+     *       foo
+     *     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+     *     end
+     *
+     * `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field.
+     * 
+ */ + public static final class RescueNode extends Node { + public final Node[] exceptions; + @Nullable + @UnionType({ LocalVariableTargetNode.class, InstanceVariableTargetNode.class, ClassVariableTargetNode.class, GlobalVariableTargetNode.class, ConstantTargetNode.class, ConstantPathTargetNode.class, CallTargetNode.class, IndexTargetNode.class }) + public final Node reference; + @Nullable + public final StatementsNode statements; + @Nullable + public final RescueNode subsequent; + + public RescueNode(int startOffset, int length, Node[] exceptions, Node reference, StatementsNode statements, RescueNode subsequent) { + super(startOffset, length); + this.exceptions = exceptions; + this.reference = reference; + this.statements = statements; + this.subsequent = subsequent; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.exceptions) { + child.accept(visitor); + } + if (this.reference != null) { + this.reference.accept(visitor); + } + if (this.statements != null) { + this.statements.accept(visitor); + } + if (this.subsequent != null) { + this.subsequent.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.exceptions)); + childNodes.add(this.reference); + childNodes.add(this.statements); + childNodes.add(this.subsequent); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRescueNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("exceptions: "); + builder.append('\n'); + for (Node child : this.exceptions) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("reference: "); + builder.append(this.reference == null ? "null\n" : this.reference.toString(nextIndent)); + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + builder.append(nextIndent); + builder.append("subsequent: "); + builder.append(this.subsequent == null ? "null\n" : this.subsequent.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a rest parameter to a method, block, or lambda definition.
+     *
+     *     def a(*b)
+     *           ^^
+     *     end
+     * 
+ */ + public static final class RestParameterNode extends Node { + public final short flags; + @Nullable + public final byte[] name; + + public RestParameterNode(int startOffset, int length, short flags, byte[] name) { + super(startOffset, length); + this.flags = flags; + this.name = name; + } + + public boolean isRepeatedParameter() { + return ParameterFlags.isRepeatedParameter(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRestParameterNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ParameterFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("name: "); + builder.append(this.name == null ? "null" : "\"" + asString(this.name) + "\""); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `retry` keyword.
+     *
+     *     retry
+     *     ^^^^^
+     * 
+ */ + public static final class RetryNode extends Node { + + public RetryNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitRetryNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `return` keyword.
+     *
+     *     return 1
+     *     ^^^^^^^^
+     * 
+ */ + public static final class ReturnNode extends Node { + @Nullable + public final ArgumentsNode arguments; + + public ReturnNode(int startOffset, int length, ArgumentsNode arguments) { + super(startOffset, length); + this.arguments = arguments; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.arguments != null) { + this.arguments.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.arguments }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitReturnNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the `self` keyword.
+     *
+     *     self
+     *     ^^^^
+     * 
+ */ + public static final class SelfNode extends Node { + + public SelfNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSelfNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * This node wraps a constant write to indicate that when the value is written, it should have its shareability state modified.
+     *
+     *     # shareable_constant_value: literal
+     *     C = { a: 1 }
+     *     ^^^^^^^^^^^^
+     * 
+ */ + public static final class ShareableConstantNode extends Node { + public final short flags; + /** + *
+         * The constant write that should be modified with the shareability state.
+         * 
+ */ + @UnionType({ ConstantWriteNode.class, ConstantAndWriteNode.class, ConstantOrWriteNode.class, ConstantOperatorWriteNode.class, ConstantPathWriteNode.class, ConstantPathAndWriteNode.class, ConstantPathOrWriteNode.class, ConstantPathOperatorWriteNode.class }) + public final Node write; + + public ShareableConstantNode(int startOffset, int length, short flags, Node write) { + super(startOffset, length); + this.flags = flags; + this.write = write; + } + + public boolean isLiteral() { + return ShareableConstantNodeFlags.isLiteral(flags); + } + + public boolean isExperimentalEverything() { + return ShareableConstantNodeFlags.isExperimentalEverything(flags); + } + + public boolean isExperimentalCopy() { + return ShareableConstantNodeFlags.isExperimentalCopy(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.write.accept(visitor); + } + + public Node[] childNodes() { + return new Node[] { this.write }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitShareableConstantNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("ShareableConstantNodeFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("write: "); + builder.append(this.write.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a singleton class declaration involving the `class` keyword.
+     *
+     *     class << self end
+     *     ^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class SingletonClassNode extends Node { + public final byte[][] locals; + public final Node expression; + @Nullable + @UnionType({ StatementsNode.class, BeginNode.class }) + public final Node body; + + public SingletonClassNode(int startOffset, int length, byte[][] locals, Node expression, Node body) { + super(startOffset, length); + this.locals = locals; + this.expression = expression; + this.body = body; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.expression.accept(visitor); + if (this.body != null) { + this.body.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.expression, this.body }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSingletonClassNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("locals: "); + builder.append('\n'); + for (byte[] constant : this.locals) { + builder.append(nextNextIndent).append('"').append(asString(constant)).append('"').append('\n'); + } + builder.append(nextIndent); + builder.append("expression: "); + builder.append(this.expression.toString(nextIndent)); + builder.append(nextIndent); + builder.append("body: "); + builder.append(this.body == null ? "null\n" : this.body.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `__ENCODING__` keyword.
+     *
+     *     __ENCODING__
+     *     ^^^^^^^^^^^^
+     * 
+ */ + public static final class SourceEncodingNode extends Node { + + public SourceEncodingNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSourceEncodingNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `__FILE__` keyword.
+     *
+     *     __FILE__
+     *     ^^^^^^^^
+     * 
+ */ + public static final class SourceFileNode extends Node { + public final short flags; + /** + *
+         * Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism.parse*` APIs.
+         * 
+ */ + public final byte[] filepath; + + public SourceFileNode(int startOffset, int length, short flags, byte[] filepath) { + super(startOffset, length); + this.flags = flags; + this.filepath = filepath; + } + + public boolean isForcedUtf8Encoding() { + return StringFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return StringFlags.isForcedBinaryEncoding(flags); + } + + public boolean isFrozen() { + return StringFlags.isFrozen(flags); + } + + public boolean isMutable() { + return StringFlags.isMutable(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSourceFileNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("StringFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("filepath: "); + builder.append('"' + asString(this.filepath) + '"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `__LINE__` keyword.
+     *
+     *     __LINE__
+     *     ^^^^^^^^
+     * 
+ */ + public static final class SourceLineNode extends Node { + + public SourceLineNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSourceLineNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the splat operator.
+     *
+     *     [*a]
+     *      ^^
+     * 
+ */ + public static final class SplatNode extends Node { + @Nullable + public final Node expression; + + public SplatNode(int startOffset, int length, Node expression) { + super(startOffset, length); + this.expression = expression; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.expression != null) { + this.expression.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.expression }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSplatNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("expression: "); + builder.append(this.expression == null ? "null\n" : this.expression.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a set of statements contained within some scope.
+     *
+     *     foo; bar; baz
+     *     ^^^^^^^^^^^^^
+     * 
+ */ + public static final class StatementsNode extends Node { + public final Node[] body; + + public StatementsNode(int startOffset, int length, Node[] body) { + super(startOffset, length); + this.body = body; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.body) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.body)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitStatementsNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("body: "); + builder.append('\n'); + for (Node child : this.body) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string.
+     *
+     *     "foo"
+     *     ^^^^^
+     *
+     *     %w[foo]
+     *        ^^^
+     *
+     *     "foo #{bar} baz"
+     *      ^^^^      ^^^^
+     * 
+ */ + public static final class StringNode extends Node { + public final short flags; + public final byte[] unescaped; + + public StringNode(int startOffset, int length, short flags, byte[] unescaped) { + super(startOffset, length); + this.flags = flags; + this.unescaped = unescaped; + } + + public boolean isForcedUtf8Encoding() { + return StringFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return StringFlags.isForcedBinaryEncoding(flags); + } + + public boolean isFrozen() { + return StringFlags.isFrozen(flags); + } + + public boolean isMutable() { + return StringFlags.isMutable(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitStringNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("StringFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("unescaped: "); + builder.append('"' + asString(this.unescaped) + '"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `super` keyword with parentheses or arguments.
+     *
+     *     super()
+     *     ^^^^^^^
+     *
+     *     super foo, bar
+     *     ^^^^^^^^^^^^^^
+     *
+     * If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead.
+     * 
+ */ + public static final class SuperNode extends Node { + /** + *
+         * Can be only `nil` when there are empty parentheses, like `super()`.
+         * 
+ */ + @Nullable + public final ArgumentsNode arguments; + @Nullable + @UnionType({ BlockNode.class, BlockArgumentNode.class }) + public final Node block; + + public SuperNode(int startOffset, int length, ArgumentsNode arguments, Node block) { + super(startOffset, length); + this.arguments = arguments; + this.block = block; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.arguments != null) { + this.arguments.accept(visitor); + } + if (this.block != null) { + this.block.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.arguments, this.block }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSuperNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + builder.append(nextIndent); + builder.append("block: "); + builder.append(this.block == null ? "null\n" : this.block.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents a symbol literal or a symbol contained within a `%i` list.
+     *
+     *     :foo
+     *     ^^^^
+     *
+     *     %i[foo]
+     *        ^^^
+     * 
+ */ + public static final class SymbolNode extends Node { + public final short flags; + public final byte[] unescaped; + + public SymbolNode(int startOffset, int length, short flags, byte[] unescaped) { + super(startOffset, length); + this.flags = flags; + this.unescaped = unescaped; + } + + public boolean isForcedUtf8Encoding() { + return SymbolFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return SymbolFlags.isForcedBinaryEncoding(flags); + } + + public boolean isForcedUsAsciiEncoding() { + return SymbolFlags.isForcedUsAsciiEncoding(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitSymbolNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("SymbolFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("unescaped: "); + builder.append('"' + asString(this.unescaped) + '"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the literal `true` keyword.
+     *
+     *     true
+     *     ^^^^
+     * 
+ */ + public static final class TrueNode extends Node { + + public TrueNode(int startOffset, int length) { + super(startOffset, length); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitTrueNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `undef` keyword.
+     *
+     *     undef :foo, :bar, :baz
+     *     ^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class UndefNode extends Node { + @UnionType({ SymbolNode.class, InterpolatedSymbolNode.class }) + public final Node[] names; + + public UndefNode(int startOffset, int length, Node[] names) { + super(startOffset, length); + this.names = names; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.names) { + child.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.names)); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitUndefNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("names: "); + builder.append('\n'); + for (Node child : this.names) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `unless` keyword, either in the block form or the modifier form.
+     *
+     *     bar unless foo
+     *     ^^^^^^^^^^^^^^
+     *
+     *     unless foo then bar end
+     *     ^^^^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class UnlessNode extends Node { + /** + *
+         * The condition to be evaluated for the unless expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+         *
+         *     unless cond then bar end
+         *            ^^^^
+         *
+         *     bar unless cond
+         *                ^^^^
+         * 
+ */ + public final Node predicate; + /** + *
+         * The body of statements that will executed if the unless condition is
+         * falsey. Will be `nil` if no body is provided.
+         *
+         *     unless cond then bar end
+         *                      ^^^
+         * 
+ */ + @Nullable + public final StatementsNode statements; + /** + *
+         * The else clause of the unless expression, if present.
+         *
+         *     unless cond then bar else baz end
+         *                          ^^^^^^^^^^^^
+         * 
+ */ + @Nullable + public final ElseNode else_clause; + + public UnlessNode(int startOffset, int length, Node predicate, StatementsNode statements, ElseNode else_clause) { + super(startOffset, length); + this.predicate = predicate; + this.statements = statements; + this.else_clause = else_clause; + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + this.predicate.setNewLineFlag(source, newlineMarked); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.predicate.accept(visitor); + if (this.statements != null) { + this.statements.accept(visitor); + } + if (this.else_clause != null) { + this.else_clause.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.predicate, this.statements, this.else_clause }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitUnlessNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("predicate: "); + builder.append(this.predicate.toString(nextIndent)); + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + builder.append(nextIndent); + builder.append("else_clause: "); + builder.append(this.else_clause == null ? "null\n" : this.else_clause.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `until` keyword, either in the block form or the modifier form.
+     *
+     *     bar until foo
+     *     ^^^^^^^^^^^^^
+     *
+     *     until foo do bar end
+     *     ^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class UntilNode extends Node { + public final short flags; + public final Node predicate; + @Nullable + public final StatementsNode statements; + + public UntilNode(int startOffset, int length, short flags, Node predicate, StatementsNode statements) { + super(startOffset, length); + this.flags = flags; + this.predicate = predicate; + this.statements = statements; + } + + public boolean isBeginModifier() { + return LoopFlags.isBeginModifier(flags); + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + this.predicate.setNewLineFlag(source, newlineMarked); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.predicate.accept(visitor); + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.predicate, this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitUntilNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("LoopFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("predicate: "); + builder.append(this.predicate.toString(nextIndent)); + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `when` keyword within a case statement.
+     *
+     *     case true
+     *     when true
+     *     ^^^^^^^^^
+     *     end
+     * 
+ */ + public static final class WhenNode extends Node { + public final Node[] conditions; + @Nullable + public final StatementsNode statements; + + public WhenNode(int startOffset, int length, Node[] conditions, StatementsNode statements) { + super(startOffset, length); + this.conditions = conditions; + this.statements = statements; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + for (Nodes.Node child : this.conditions) { + child.accept(visitor); + } + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + ArrayList childNodes = new ArrayList<>(); + childNodes.addAll(Arrays.asList(this.conditions)); + childNodes.add(this.statements); + return childNodes.toArray(EMPTY_ARRAY); + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitWhenNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + String nextNextIndent = nextIndent + " "; + builder.append(nextIndent); + builder.append("conditions: "); + builder.append('\n'); + for (Node child : this.conditions) { + builder.append(nextNextIndent).append(child.toString(nextNextIndent)); + } + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `while` keyword, either in the block form or the modifier form.
+     *
+     *     bar while foo
+     *     ^^^^^^^^^^^^^
+     *
+     *     while foo do bar end
+     *     ^^^^^^^^^^^^^^^^^^^^
+     * 
+ */ + public static final class WhileNode extends Node { + public final short flags; + public final Node predicate; + @Nullable + public final StatementsNode statements; + + public WhileNode(int startOffset, int length, short flags, Node predicate, StatementsNode statements) { + super(startOffset, length); + this.flags = flags; + this.predicate = predicate; + this.statements = statements; + } + + public boolean isBeginModifier() { + return LoopFlags.isBeginModifier(flags); + } + + @Override + public void setNewLineFlag(Source source, boolean[] newlineMarked) { + this.predicate.setNewLineFlag(source, newlineMarked); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + this.predicate.accept(visitor); + if (this.statements != null) { + this.statements.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.predicate, this.statements }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitWhileNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("LoopFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("predicate: "); + builder.append(this.predicate.toString(nextIndent)); + builder.append(nextIndent); + builder.append("statements: "); + builder.append(this.statements == null ? "null\n" : this.statements.toString(nextIndent)); + return builder.toString(); + } + } + + /** + *
+     * Represents an xstring literal with no interpolation.
+     *
+     *     `foo`
+     *     ^^^^^
+     * 
+ */ + public static final class XStringNode extends Node { + public final short flags; + public final byte[] unescaped; + + public XStringNode(int startOffset, int length, short flags, byte[] unescaped) { + super(startOffset, length); + this.flags = flags; + this.unescaped = unescaped; + } + + public boolean isForcedUtf8Encoding() { + return EncodingFlags.isForcedUtf8Encoding(flags); + } + + public boolean isForcedBinaryEncoding() { + return EncodingFlags.isForcedBinaryEncoding(flags); + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + } + + public Node[] childNodes() { + return EMPTY_ARRAY; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitXStringNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("EncodingFlags: "); + builder.append(flags); + builder.append('\n'); + builder.append(nextIndent); + builder.append("unescaped: "); + builder.append('"' + asString(this.unescaped) + '"'); + builder.append('\n'); + return builder.toString(); + } + } + + /** + *
+     * Represents the use of the `yield` keyword.
+     *
+     *     yield 1
+     *     ^^^^^^^
+     * 
+ */ + public static final class YieldNode extends Node { + @Nullable + public final ArgumentsNode arguments; + + public YieldNode(int startOffset, int length, ArgumentsNode arguments) { + super(startOffset, length); + this.arguments = arguments; + } + + public void visitChildNodes(AbstractNodeVisitor visitor) { + if (this.arguments != null) { + this.arguments.accept(visitor); + } + } + + public Node[] childNodes() { + return new Node[] { this.arguments }; + } + + public T accept(AbstractNodeVisitor visitor) { + return visitor.visitYieldNode(this); + } + + @Override + protected String toString(String indent) { + StringBuilder builder = new StringBuilder(); + builder.append(this.getClass().getSimpleName()); + if (hasNewLineFlag()) { + builder.append("[Li]"); + } + builder.append('\n'); + String nextIndent = indent + " "; + builder.append(nextIndent); + builder.append("arguments: "); + builder.append(this.arguments == null ? "null\n" : this.arguments.toString(nextIndent)); + return builder.toString(); + } + } + + public enum ErrorType { + ALIAS_ARGUMENT, + ALIAS_ARGUMENT_NUMBERED_REFERENCE, + AMPAMPEQ_MULTI_ASSIGN, + ARGUMENT_AFTER_BLOCK, + ARGUMENT_AFTER_FORWARDING_ELLIPSES, + ARGUMENT_BARE_HASH, + ARGUMENT_BLOCK_FORWARDING, + ARGUMENT_BLOCK_MULTI, + ARGUMENT_CONFLICT_AMPERSAND, + ARGUMENT_CONFLICT_STAR, + ARGUMENT_CONFLICT_STAR_STAR, + ARGUMENT_FORMAL_CLASS, + ARGUMENT_FORMAL_CONSTANT, + ARGUMENT_FORMAL_GLOBAL, + ARGUMENT_FORMAL_IVAR, + ARGUMENT_FORWARDING_UNBOUND, + ARGUMENT_NO_FORWARDING_AMPERSAND, + ARGUMENT_NO_FORWARDING_ELLIPSES, + ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA, + ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK, + ARGUMENT_NO_FORWARDING_STAR, + ARGUMENT_NO_FORWARDING_STAR_STAR, + ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT, + ARGUMENT_SPLAT_AFTER_SPLAT, + ARGUMENT_TERM_PAREN, + ARGUMENT_UNEXPECTED_BLOCK, + ARRAY_ELEMENT, + ARRAY_EXPRESSION, + ARRAY_EXPRESSION_AFTER_STAR, + ARRAY_SEPARATOR, + ARRAY_TERM, + BEGIN_LONELY_ELSE, + BEGIN_TERM, + BEGIN_UPCASE_BRACE, + BEGIN_UPCASE_TERM, + BEGIN_UPCASE_TOPLEVEL, + BLOCK_PARAM_LOCAL_VARIABLE, + BLOCK_PARAM_PIPE_TERM, + BLOCK_TERM_BRACE, + BLOCK_TERM_END, + CANNOT_PARSE_EXPRESSION, + CANNOT_PARSE_STRING_PART, + CASE_EXPRESSION_AFTER_CASE, + CASE_EXPRESSION_AFTER_WHEN, + CASE_MATCH_MISSING_PREDICATE, + CASE_MISSING_CONDITIONS, + CASE_TERM, + CLASS_IN_METHOD, + CLASS_NAME, + CLASS_SUPERCLASS, + CLASS_TERM, + CLASS_UNEXPECTED_END, + CLASS_VARIABLE_BARE, + CONDITIONAL_ELSIF_PREDICATE, + CONDITIONAL_IF_PREDICATE, + CONDITIONAL_PREDICATE_TERM, + CONDITIONAL_TERM, + CONDITIONAL_TERM_ELSE, + CONDITIONAL_UNLESS_PREDICATE, + CONDITIONAL_UNTIL_PREDICATE, + CONDITIONAL_WHILE_PREDICATE, + CONSTANT_PATH_COLON_COLON_CONSTANT, + DEF_ENDLESS, + DEF_ENDLESS_PARAMETERS, + DEF_ENDLESS_SETTER, + DEF_ENDLESS_DO_BLOCK, + DEF_NAME, + DEF_PARAMS_TERM, + DEF_PARAMS_TERM_PAREN, + DEF_RECEIVER, + DEF_RECEIVER_TERM, + DEF_TERM, + DEFINED_EXPRESSION, + EMBDOC_TERM, + EMBEXPR_END, + EMBVAR_INVALID, + END_UPCASE_BRACE, + END_UPCASE_TERM, + ESCAPE_INVALID_CONTROL, + ESCAPE_INVALID_CONTROL_REPEAT, + ESCAPE_INVALID_HEXADECIMAL, + ESCAPE_INVALID_META, + ESCAPE_INVALID_META_REPEAT, + ESCAPE_INVALID_UNICODE, + ESCAPE_INVALID_UNICODE_CM_FLAGS, + ESCAPE_INVALID_UNICODE_LIST, + ESCAPE_INVALID_UNICODE_LITERAL, + ESCAPE_INVALID_UNICODE_LONG, + ESCAPE_INVALID_UNICODE_SHORT, + ESCAPE_INVALID_UNICODE_TERM, + EXPECT_ARGUMENT, + EXPECT_EOL_AFTER_STATEMENT, + EXPECT_EXPRESSION_AFTER_AMPAMPEQ, + EXPECT_EXPRESSION_AFTER_COMMA, + EXPECT_EXPRESSION_AFTER_EQUAL, + EXPECT_EXPRESSION_AFTER_LESS_LESS, + EXPECT_EXPRESSION_AFTER_LPAREN, + EXPECT_EXPRESSION_AFTER_OPERATOR, + EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, + EXPECT_EXPRESSION_AFTER_QUESTION, + EXPECT_EXPRESSION_AFTER_SPLAT, + EXPECT_EXPRESSION_AFTER_SPLAT_HASH, + EXPECT_EXPRESSION_AFTER_STAR, + EXPECT_FOR_DELIMITER, + EXPECT_IDENT_REQ_PARAMETER, + EXPECT_IN_DELIMITER, + EXPECT_LPAREN_AFTER_NOT_LPAREN, + EXPECT_LPAREN_AFTER_NOT_OTHER, + EXPECT_LPAREN_REQ_PARAMETER, + EXPECT_MESSAGE, + EXPECT_RBRACKET, + EXPECT_RPAREN, + EXPECT_RPAREN_AFTER_MULTI, + EXPECT_RPAREN_REQ_PARAMETER, + EXPECT_SINGLETON_CLASS_DELIMITER, + EXPECT_STRING_CONTENT, + EXPECT_WHEN_DELIMITER, + EXPRESSION_BARE_HASH, + EXPRESSION_NOT_WRITABLE, + EXPRESSION_NOT_WRITABLE_ENCODING, + EXPRESSION_NOT_WRITABLE_FALSE, + EXPRESSION_NOT_WRITABLE_FILE, + EXPRESSION_NOT_WRITABLE_LINE, + EXPRESSION_NOT_WRITABLE_NIL, + EXPRESSION_NOT_WRITABLE_NUMBERED, + EXPRESSION_NOT_WRITABLE_SELF, + EXPRESSION_NOT_WRITABLE_TRUE, + FLOAT_PARSE, + FOR_COLLECTION, + FOR_IN, + FOR_INDEX, + FOR_TERM, + GLOBAL_VARIABLE_BARE, + HASH_EXPRESSION_AFTER_LABEL, + HASH_KEY, + HASH_ROCKET, + HASH_TERM, + HASH_VALUE, + HEREDOC_IDENTIFIER, + HEREDOC_TERM, + INCOMPLETE_QUESTION_MARK, + INCOMPLETE_VARIABLE_CLASS, + INCOMPLETE_VARIABLE_CLASS_3_3, + INCOMPLETE_VARIABLE_INSTANCE, + INCOMPLETE_VARIABLE_INSTANCE_3_3, + INSTANCE_VARIABLE_BARE, + INVALID_BLOCK_EXIT, + INVALID_CHARACTER, + INVALID_COMMA, + INVALID_ENCODING_MAGIC_COMMENT, + INVALID_ESCAPE_CHARACTER, + INVALID_FLOAT_EXPONENT, + INVALID_LOCAL_VARIABLE_READ, + INVALID_LOCAL_VARIABLE_WRITE, + INVALID_MULTIBYTE_CHAR, + INVALID_MULTIBYTE_CHARACTER, + INVALID_MULTIBYTE_ESCAPE, + INVALID_NUMBER_BINARY, + INVALID_NUMBER_DECIMAL, + INVALID_NUMBER_FRACTION, + INVALID_NUMBER_HEXADECIMAL, + INVALID_NUMBER_OCTAL, + INVALID_NUMBER_UNDERSCORE_INNER, + INVALID_NUMBER_UNDERSCORE_TRAILING, + INVALID_PERCENT, + INVALID_PERCENT_EOF, + INVALID_PRINTABLE_CHARACTER, + INVALID_RETRY_AFTER_ELSE, + INVALID_RETRY_AFTER_ENSURE, + INVALID_RETRY_WITHOUT_RESCUE, + INVALID_SYMBOL, + INVALID_VARIABLE_GLOBAL, + INVALID_VARIABLE_GLOBAL_3_3, + INVALID_YIELD, + IT_NOT_ALLOWED_NUMBERED, + IT_NOT_ALLOWED_ORDINARY, + LAMBDA_OPEN, + LAMBDA_TERM_BRACE, + LAMBDA_TERM_END, + LIST_I_LOWER_ELEMENT, + LIST_I_LOWER_TERM, + LIST_I_UPPER_ELEMENT, + LIST_I_UPPER_TERM, + LIST_W_LOWER_ELEMENT, + LIST_W_LOWER_TERM, + LIST_W_UPPER_ELEMENT, + LIST_W_UPPER_TERM, + MALLOC_FAILED, + MIXED_ENCODING, + MODULE_IN_METHOD, + MODULE_NAME, + MODULE_TERM, + MULTI_ASSIGN_MULTI_SPLATS, + MULTI_ASSIGN_UNEXPECTED_REST, + NESTING_TOO_DEEP, + NO_LOCAL_VARIABLE, + NON_ASSOCIATIVE_OPERATOR, + NOT_EXPRESSION, + NUMBER_LITERAL_UNDERSCORE, + NUMBERED_PARAMETER_INNER_BLOCK, + NUMBERED_PARAMETER_IT, + NUMBERED_PARAMETER_ORDINARY, + NUMBERED_PARAMETER_OUTER_BLOCK, + OPERATOR_MULTI_ASSIGN, + OPERATOR_WRITE_ARGUMENTS, + OPERATOR_WRITE_BLOCK, + PARAMETER_ASSOC_SPLAT_MULTI, + PARAMETER_BLOCK_MULTI, + PARAMETER_CIRCULAR, + PARAMETER_FORWARDING_AFTER_REST, + PARAMETER_METHOD_NAME, + PARAMETER_NAME_DUPLICATED, + PARAMETER_NO_DEFAULT, + PARAMETER_NO_DEFAULT_KW, + PARAMETER_NUMBERED_RESERVED, + PARAMETER_ORDER, + PARAMETER_SPLAT_MULTI, + PARAMETER_STAR, + PARAMETER_UNEXPECTED_FWD, + PARAMETER_UNEXPECTED_NO_KW, + PARAMETER_WILD_LOOSE_COMMA, + PATTERN_ARRAY_MULTIPLE_RESTS, + PATTERN_CAPTURE_DUPLICATE, + PATTERN_CAPTURE_IN_ALTERNATIVE, + PATTERN_EXPRESSION_AFTER_BRACKET, + PATTERN_EXPRESSION_AFTER_COMMA, + PATTERN_EXPRESSION_AFTER_HROCKET, + PATTERN_EXPRESSION_AFTER_IN, + PATTERN_EXPRESSION_AFTER_KEY, + PATTERN_EXPRESSION_AFTER_PAREN, + PATTERN_EXPRESSION_AFTER_PIN, + PATTERN_EXPRESSION_AFTER_PIPE, + PATTERN_EXPRESSION_AFTER_RANGE, + PATTERN_EXPRESSION_AFTER_REST, + PATTERN_FIND_MISSING_INNER, + PATTERN_HASH_IMPLICIT, + PATTERN_HASH_KEY, + PATTERN_HASH_KEY_DUPLICATE, + PATTERN_HASH_KEY_INTERPOLATED, + PATTERN_HASH_KEY_LABEL, + PATTERN_HASH_KEY_LOCALS, + PATTERN_IDENT_AFTER_HROCKET, + PATTERN_LABEL_AFTER_COMMA, + PATTERN_REST, + PATTERN_TERM_BRACE, + PATTERN_TERM_BRACKET, + PATTERN_TERM_PAREN, + PIPEPIPEEQ_MULTI_ASSIGN, + REGEXP_ENCODING_OPTION_MISMATCH, + REGEXP_ESCAPED_NON_ASCII_IN_UTF8, + REGEXP_INCOMPAT_CHAR_ENCODING, + REGEXP_INVALID_CHAR_PROPERTY, + REGEXP_INVALID_UNICODE_RANGE, + REGEXP_NON_ESCAPED_MBC, + REGEXP_PARSE_ERROR, + REGEXP_TERM, + REGEXP_UNKNOWN_OPTIONS, + REGEXP_UTF8_CHAR_NON_UTF8_REGEXP, + RESCUE_EXPRESSION, + RESCUE_MODIFIER_VALUE, + RESCUE_TERM, + RESCUE_VARIABLE, + RETURN_INVALID, + SCRIPT_NOT_FOUND, + SINGLETON_FOR_LITERALS, + STATEMENT_ALIAS, + STATEMENT_POSTEXE_END, + STATEMENT_PREEXE_BEGIN, + STATEMENT_UNDEF, + STRING_CONCATENATION, + STRING_INTERPOLATED_TERM, + STRING_LITERAL_EOF, + STRING_LITERAL_TERM, + SYMBOL_INVALID, + SYMBOL_TERM_DYNAMIC, + SYMBOL_TERM_INTERPOLATED, + TERNARY_COLON, + TERNARY_EXPRESSION_FALSE, + TERNARY_EXPRESSION_TRUE, + UNARY_DISALLOWED, + UNARY_RECEIVER, + UNDEF_ARGUMENT, + UNEXPECTED_BLOCK_ARGUMENT, + UNEXPECTED_INDEX_BLOCK, + UNEXPECTED_INDEX_KEYWORDS, + UNEXPECTED_LABEL, + UNEXPECTED_MULTI_WRITE, + UNEXPECTED_PARAMETER_DEFAULT_VALUE, + UNEXPECTED_RANGE_OPERATOR, + UNEXPECTED_SAFE_NAVIGATION, + UNEXPECTED_TOKEN_CLOSE_CONTEXT, + UNEXPECTED_TOKEN_IGNORE, + UNTIL_TERM, + VOID_EXPRESSION, + WHILE_TERM, + WRITE_TARGET_IN_METHOD, + WRITE_TARGET_READONLY, + WRITE_TARGET_UNEXPECTED, + XSTRING_TERM, + } + + public static ErrorType[] ERROR_TYPES = ErrorType.values(); + + public enum WarningType { + AMBIGUOUS_BINARY_OPERATOR, + AMBIGUOUS_FIRST_ARGUMENT_MINUS, + AMBIGUOUS_FIRST_ARGUMENT_PLUS, + AMBIGUOUS_PREFIX_AMPERSAND, + AMBIGUOUS_PREFIX_STAR, + AMBIGUOUS_PREFIX_STAR_STAR, + AMBIGUOUS_SLASH, + COMPARISON_AFTER_COMPARISON, + DOT_DOT_DOT_EOL, + EQUAL_IN_CONDITIONAL, + EQUAL_IN_CONDITIONAL_3_3, + END_IN_METHOD, + DUPLICATED_HASH_KEY, + DUPLICATED_WHEN_CLAUSE, + FLOAT_OUT_OF_RANGE, + IGNORED_FROZEN_STRING_LITERAL, + INDENTATION_MISMATCH, + INTEGER_IN_FLIP_FLOP, + INVALID_CHARACTER, + INVALID_MAGIC_COMMENT_VALUE, + INVALID_NUMBERED_REFERENCE, + KEYWORD_EOL, + LITERAL_IN_CONDITION_DEFAULT, + LITERAL_IN_CONDITION_VERBOSE, + SHAREABLE_CONSTANT_VALUE_LINE, + SHEBANG_CARRIAGE_RETURN, + UNEXPECTED_CARRIAGE_RETURN, + UNREACHABLE_STATEMENT, + UNUSED_LOCAL_VARIABLE, + VOID_STATEMENT, + } + + public static WarningType[] WARNING_TYPES = WarningType.values(); +} +// @formatter:on diff --git a/java/org/ruby_lang/prism/ParseResult.java b/java/api/src/main/java/org/ruby_lang/prism/ParseResult.java similarity index 100% rename from java/org/ruby_lang/prism/ParseResult.java rename to java/api/src/main/java/org/ruby_lang/prism/ParseResult.java diff --git a/java/org/ruby_lang/prism/ParsingOptions.java b/java/api/src/main/java/org/ruby_lang/prism/ParsingOptions.java similarity index 100% rename from java/org/ruby_lang/prism/ParsingOptions.java rename to java/api/src/main/java/org/ruby_lang/prism/ParsingOptions.java diff --git a/java/native/pom.xml b/java/native/pom.xml new file mode 100644 index 0000000000..96d6b6e26a --- /dev/null +++ b/java/native/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + + org.ruby-lang + prism-parser + 0.0.2-SNAPSHOT + + + prism-parser-native + Java Prism Native + Java native bindings Prism parser shared library + https://github.com/ruby/prism + + + + + org.codehaus.mojo + templating-maven-plugin + 3.1.0 + + + filtering-java-templates + + filter-sources + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.15.0 + + 21 + + + com.dylibso.chicory + annotations-processor + ${chicory.version} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.5 + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.1 + + + generate-sources + + add-source + + + + ../java + + + + + + + + + diff --git a/java/org/ruby_lang/prism/Parser.java b/java/native/src/main/java/org/ruby_lang/prism/Parser.java similarity index 100% rename from java/org/ruby_lang/prism/Parser.java rename to java/native/src/main/java/org/ruby_lang/prism/Parser.java diff --git a/java/pom.xml b/java/pom.xml new file mode 100644 index 0000000000..618b48d71c --- /dev/null +++ b/java/pom.xml @@ -0,0 +1,157 @@ + + + 4.0.0 + + org.ruby-lang + prism-parser + 0.0.2-SNAPSHOT + pom + Java Prism + Java API for the Prism Ruby language parser + https://github.com/ruby/prism + + + + MIT + + + + + + Kevin Newton + kddnewton@gmail.com + + + Benoit Daloze + eregontp@gmail.com + + + Charles Oliver Nutter + headius@headius.com + + + Thomas E Enebo + tom.enebo@gmail.com + + + + + https://github.com/ruby/prism + https://github.com/ruby/prism.git + + + + UTF-8 + UTF-8 + 21 + 21 + + 1.7.3 + 6.0.3 + + + + api + native + wasm + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.4 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.15.0 + + + org.apache.maven.plugins + maven-source-plugin + 3.4.0 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.12.0 + + + org.sonatype.central + central-publishing-maven-plugin + 0.7.0 + + + + + + + release + + + + maven-gpg-plugin + 3.2.4 + + + sign-artifacts + verify + + sign + + + + + + --pinentry-mode + loopback + + + + + + + + + + + + maven-source-plugin + + + attach-sources + + jar-no-fork + + + + + + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + none + + + + org.sonatype.central + central-publishing-maven-plugin + 0.7.0 + true + + central + + + + + + diff --git a/java-wasm/.gitignore b/java/wasm/.gitignore similarity index 100% rename from java-wasm/.gitignore rename to java/wasm/.gitignore diff --git a/java-wasm/README.md b/java/wasm/README.md similarity index 88% rename from java-wasm/README.md rename to java/wasm/README.md index 47aa48a774..64b42732fc 100644 --- a/java-wasm/README.md +++ b/java/wasm/README.md @@ -17,12 +17,12 @@ make java-wasm WASI_SDK_PATH=.../wasi-sdk-25.0-arm64-macos Build the AOT-compiled machine and wrapper library: ``` -mvn -f java-wasm/pom.xml clean package +mvn -f java/wasm/pom.xml clean package ``` This should build the chicory-wasm jar file and pass some basic tests. -The jar will be under `java-wasm/target/chicory-prism-#####-SNAPSHOT.jar` or can be installed by using `install` instead of `pacakge` in the `mvn` command line above. +The jar will be under `java/wasm/target/chicory-prism-#####-SNAPSHOT.jar` or can be installed by using `install` instead of `pacakge` in the `mvn` command line above. ## Releasing diff --git a/java-wasm/perf-test/.gitignore b/java/wasm/perf-test/.gitignore similarity index 100% rename from java-wasm/perf-test/.gitignore rename to java/wasm/perf-test/.gitignore diff --git a/java-wasm/perf-test/bench.sh b/java/wasm/perf-test/bench.sh similarity index 100% rename from java-wasm/perf-test/bench.sh rename to java/wasm/perf-test/bench.sh diff --git a/java-wasm/perf-test/test b/java/wasm/perf-test/test similarity index 100% rename from java-wasm/perf-test/test rename to java/wasm/perf-test/test diff --git a/java/wasm/pom.xml b/java/wasm/pom.xml new file mode 100644 index 0000000000..d652780606 --- /dev/null +++ b/java/wasm/pom.xml @@ -0,0 +1,126 @@ + + + 4.0.0 + + + org.ruby-lang + prism-parser + 0.0.2-SNAPSHOT + + + prism-parser-wasm + Java Prism WASM + Java WASM bindings for the Prism parser shared library + https://github.com/ruby/prism + + + 1.7.3 + + + + + + com.dylibso.chicory + bom + ${chicory.version} + pom + import + + + + + + + org.ruby-lang + prism-parser-api + 0.0.2-SNAPSHOT + + + com.dylibso.chicory + runtime + + + com.dylibso.chicory + log + + + com.dylibso.chicory + wasi + + + com.dylibso.chicory + wasm + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + com.dylibso.chicory + annotations + provided + + + org.jruby + jruby-complete + 10.0.4.0 + test + + + + + + + org.codehaus.mojo + templating-maven-plugin + 3.1.0 + + + filtering-java-templates + + filter-sources + + + + + + maven-compiler-plugin + + 21 + + + com.dylibso.chicory + annotations-processor + ${chicory.version} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.5 + + + com.dylibso.chicory + chicory-compiler-maven-plugin + ${chicory.version} + + + prism + + compile + + + org.ruby_lang.prism.wasm.PrismParser + src/test/resources/prism.wasm + + + + + + + + diff --git a/java/wasm/prism-parser.iml b/java/wasm/prism-parser.iml new file mode 100644 index 0000000000..99039ba2ed --- /dev/null +++ b/java/wasm/prism-parser.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java b/java/wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java similarity index 100% rename from java-wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java rename to java/wasm/src/main/java-templates/org/ruby_lang/prism/wasm/WasmResource.java diff --git a/java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java b/java/wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java similarity index 100% rename from java-wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java rename to java/wasm/src/main/java/org/ruby_lang/prism/wasm/Prism.java diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java b/java/wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java similarity index 100% rename from java-wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java rename to java/wasm/src/test/java/org/jruby/parser/prism/JRubyTest.java diff --git a/java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java b/java/wasm/src/test/java/org/jruby/parser/prism/WASMTest.java similarity index 100% rename from java-wasm/src/test/java/org/jruby/parser/prism/WASMTest.java rename to java/wasm/src/test/java/org/jruby/parser/prism/WASMTest.java diff --git a/java-wasm/src/test/resources/.gitignore b/java/wasm/src/test/resources/.gitignore similarity index 100% rename from java-wasm/src/test/resources/.gitignore rename to java/wasm/src/test/resources/.gitignore diff --git a/rakelib/check_manifest.rake b/rakelib/check_manifest.rake index 2c8fced816..ff88543fa9 100644 --- a/rakelib/check_manifest.rake +++ b/rakelib/check_manifest.rake @@ -19,7 +19,7 @@ task check_manifest: :templates do gemfiles javascript java - java-wasm + java/wasm pkg rakelib rust diff --git a/templates/template.rb b/templates/template.rb index 5d1afc9506..c455b36d03 100755 --- a/templates/template.rb +++ b/templates/template.rb @@ -688,9 +688,9 @@ def locals "javascript/src/deserialize.js", "javascript/src/nodes.js", "javascript/src/visitor.js", - "java/org/ruby_lang/prism/Loader.java", - "java/org/ruby_lang/prism/Nodes.java", - "java/org/ruby_lang/prism/AbstractNodeVisitor.java", + "java/api/src/main/java/org/ruby_lang/prism/Loader.java", + "java/api/src/main/java/org/ruby_lang/prism/Nodes.java", + "java/api/src/main/java/org/ruby_lang/prism/AbstractNodeVisitor.java", "lib/prism/compiler.rb", "lib/prism/dispatcher.rb", "lib/prism/dot_visitor.rb",
- - C -

C reference

-
- - Ruby -

Ruby reference

-
- - Rust -

Rust reference

-
- - Java -

Java reference

-
+
+

Try it

+

Parse Ruby code in your browser — no installation required.

+ Open playground → +
+ +
+

Getting started

+

Prism is bundled with CRuby 3.3+ and available as a gem for earlier versions.

+
gem install prism
+
+ +
+

API Reference

+ +
+ +
+

Guides

+ +