From 0e162457d686946c69caba6558fb400ace5d8b78 Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Fri, 11 Aug 2023 18:22:21 -0500 Subject: [PATCH 001/158] [DOC] Don't suppress autolinks (#8208) --- string.c | 62 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/string.c b/string.c index d3ebca1d8d59e8..ab4541dad7f5a2 100644 --- a/string.c +++ b/string.c @@ -2276,7 +2276,7 @@ rb_str_times(VALUE str, VALUE times) * "%05d" % 123 # => "00123" * * If +self+ contains multiple substitutions, +object+ must be - * an \Array or \Hash containing the values to be substituted: + * an Array or Hash containing the values to be substituted: * * "%-5s: %016x" % [ "ID", self.object_id ] # => "ID : 00002b054ec93168" * "foo = %{foo}" % {foo: 'bar'} # => "foo = bar" @@ -3308,7 +3308,7 @@ rb_str_concat_literals(size_t num, const VALUE *strary) * s.concat('bar', 'baz') # => "foobarbaz" * s # => "foobarbaz" * - * For each given object +object+ that is an \Integer, + * For each given object +object+ that is an Integer, * the value is considered a codepoint and converted to a character before concatenation: * * s = 'foo' @@ -3347,7 +3347,7 @@ rb_str_concat_multi(int argc, VALUE *argv, VALUE str) * s << 'bar' # => "foobar" * s # => "foobar" * - * If +object+ is an \Integer, + * If +object+ is an Integer, * the value is considered a codepoint and converted to a character before concatenation: * * s = 'foo' @@ -3939,7 +3939,7 @@ str_ensure_byte_pos(VALUE str, long pos) * byteindex(substring, offset = 0) -> integer or nil * byteindex(regexp, offset = 0) -> integer or nil * - * Returns the \Integer byte-based index of the first occurrence of the given +substring+, + * Returns the Integer byte-based index of the first occurrence of the given +substring+, * or +nil+ if none found: * * 'foo'.byteindex('f') # => 0 @@ -3947,7 +3947,7 @@ str_ensure_byte_pos(VALUE str, long pos) * 'foo'.byteindex('oo') # => 1 * 'foo'.byteindex('ooo') # => nil * - * Returns the \Integer byte-based index of the first match for the given \Regexp +regexp+, + * Returns the Integer byte-based index of the first match for the given Regexp +regexp+, * or +nil+ if none found: * * 'foo'.byteindex(/f/) # => 0 @@ -3955,7 +3955,7 @@ str_ensure_byte_pos(VALUE str, long pos) * 'foo'.byteindex(/oo/) # => 1 * 'foo'.byteindex(/ooo/) # => nil * - * \Integer argument +offset+, if given, specifies the byte-based position in the + * Integer argument +offset+, if given, specifies the byte-based position in the * string to begin the search: * * 'foo'.byteindex('o', 1) # => 1 @@ -4108,7 +4108,7 @@ rb_str_rindex(VALUE str, VALUE sub, long pos) * rindex(substring, offset = self.length) -> integer or nil * rindex(regexp, offset = self.length) -> integer or nil * - * Returns the \Integer index of the _last_ occurrence of the given +substring+, + * Returns the Integer index of the _last_ occurrence of the given +substring+, * or +nil+ if none found: * * 'foo'.rindex('f') # => 0 @@ -4116,7 +4116,7 @@ rb_str_rindex(VALUE str, VALUE sub, long pos) * 'foo'.rindex('oo') # => 1 * 'foo'.rindex('ooo') # => nil * - * Returns the \Integer index of the _last_ match for the given \Regexp +regexp+, + * Returns the Integer index of the _last_ match for the given Regexp +regexp+, * or +nil+ if none found: * * 'foo'.rindex(/f/) # => 0 @@ -4141,7 +4141,7 @@ rb_str_rindex(VALUE str, VALUE sub, long pos) * 'foo'.index(/o+(?!.*o)/) # => 1 * $~ #=> # * - * \Integer argument +offset+, if given and non-negative, specifies the maximum starting position in the + * Integer argument +offset+, if given and non-negative, specifies the maximum starting position in the * string to _end_ the search: * * 'foo'.rindex('o', 0) # => nil @@ -4149,7 +4149,7 @@ rb_str_rindex(VALUE str, VALUE sub, long pos) * 'foo'.rindex('o', 2) # => 2 * 'foo'.rindex('o', 3) # => 2 * - * If +offset+ is a negative \Integer, the maximum starting position in the + * If +offset+ is a negative Integer, the maximum starting position in the * string to _end_ the search is the sum of the string's length and +offset+: * * 'foo'.rindex('o', -1) # => 2 @@ -4241,7 +4241,7 @@ rb_str_byterindex(VALUE str, VALUE sub, long pos) * byterindex(substring, offset = self.bytesize) -> integer or nil * byterindex(regexp, offset = self.bytesize) -> integer or nil * - * Returns the \Integer byte-based index of the _last_ occurrence of the given +substring+, + * Returns the Integer byte-based index of the _last_ occurrence of the given +substring+, * or +nil+ if none found: * * 'foo'.byterindex('f') # => 0 @@ -4249,7 +4249,7 @@ rb_str_byterindex(VALUE str, VALUE sub, long pos) * 'foo'.byterindex('oo') # => 1 * 'foo'.byterindex('ooo') # => nil * - * Returns the \Integer byte-based index of the _last_ match for the given \Regexp +regexp+, + * Returns the Integer byte-based index of the _last_ match for the given Regexp +regexp+, * or +nil+ if none found: * * 'foo'.byterindex(/f/) # => 0 @@ -4274,7 +4274,7 @@ rb_str_byterindex(VALUE str, VALUE sub, long pos) * 'foo'.byteindex(/o+(?!.*o)/) # => 1 * $~ #=> # * - * \Integer argument +offset+, if given and non-negative, specifies the maximum starting byte-based position in the + * Integer argument +offset+, if given and non-negative, specifies the maximum starting byte-based position in the * string to _end_ the search: * * 'foo'.byterindex('o', 0) # => nil @@ -4282,7 +4282,7 @@ rb_str_byterindex(VALUE str, VALUE sub, long pos) * 'foo'.byterindex('o', 2) # => 2 * 'foo'.byterindex('o', 3) # => 2 * - * If +offset+ is a negative \Integer, the maximum starting position in the + * If +offset+ is a negative Integer, the maximum starting position in the * string to _end_ the search is the sum of the string's length and +offset+: * * 'foo'.byterindex('o', -1) # => 2 @@ -4340,7 +4340,7 @@ rb_str_byterindex_m(int argc, VALUE *argv, VALUE str) * string =~ regexp -> integer or nil * string =~ object -> integer or nil * - * Returns the \Integer index of the first substring that matches + * Returns the Integer index of the first substring that matches * the given +regexp+, or +nil+ if no match found: * * 'foo' =~ /f/ # => 0 @@ -4349,7 +4349,7 @@ rb_str_byterindex_m(int argc, VALUE *argv, VALUE str) * * Note: also updates Regexp@Global+Variables. * - * If the given +object+ is not a \Regexp, returns the value + * If the given +object+ is not a Regexp, returns the value * returned by object =~ self. * * Note that string =~ regexp is different from regexp =~ string @@ -4387,13 +4387,13 @@ static VALUE get_pat(VALUE); * match(pattern, offset = 0) -> matchdata or nil * match(pattern, offset = 0) {|matchdata| ... } -> object * - * Returns a \MatchData object (or +nil+) based on +self+ and the given +pattern+. + * Returns a MatchData object (or +nil+) based on +self+ and the given +pattern+. * * Note: also updates Regexp@Global+Variables. * - * - Computes +regexp+ by converting +pattern+ (if not already a \Regexp). + * - Computes +regexp+ by converting +pattern+ (if not already a Regexp). * regexp = Regexp.new(pattern) - * - Computes +matchdata+, which will be either a \MatchData object or +nil+ + * - Computes +matchdata+, which will be either a MatchData object or +nil+ * (see Regexp#match): * matchdata = regexp.match(self) * @@ -4403,7 +4403,7 @@ static VALUE get_pat(VALUE); * 'foo'.match('o') # => # * 'foo'.match('x') # => nil * - * If \Integer argument +offset+ is given, the search begins at index +offset+: + * If Integer argument +offset+ is given, the search begins at index +offset+: * * 'foo'.match('f', 1) # => nil * 'foo'.match('o', 1) # => # @@ -4440,17 +4440,17 @@ rb_str_match_m(int argc, VALUE *argv, VALUE str) * * Note: does not update Regexp@Global+Variables. * - * Computes +regexp+ by converting +pattern+ (if not already a \Regexp). + * Computes +regexp+ by converting +pattern+ (if not already a Regexp). * regexp = Regexp.new(pattern) * - * Returns +true+ if self+.match(regexp) returns a \MatchData object, + * Returns +true+ if self+.match(regexp) returns a MatchData object, * +false+ otherwise: * * 'foo'.match?(/o/) # => true * 'foo'.match?('o') # => true * 'foo'.match?(/x/) # => false * - * If \Integer argument +offset+ is given, the search begins at index +offset+: + * If Integer argument +offset+ is given, the search begins at index +offset+: * 'foo'.match?('f', 1) # => false * 'foo'.match?('o', 1) # => true * @@ -4866,7 +4866,7 @@ str_upto_i(VALUE str, VALUE arg) * '25'.upto('5') {|s| fail s } * 'aa'.upto('a') {|s| fail s } * - * With no block given, returns a new \Enumerator: + * With no block given, returns a new Enumerator: * * 'a8'.upto('b6') # => # * @@ -5378,11 +5378,11 @@ rb_str_aset_m(int argc, VALUE *argv, VALUE str) * * Inserts the given +other_string+ into +self+; returns +self+. * - * If the \Integer +index+ is positive, inserts +other_string+ at offset +index+: + * If the Integer +index+ is positive, inserts +other_string+ at offset +index+: * * 'foo'.insert(1, 'bar') # => "fbaroo" * - * If the \Integer +index+ is negative, counts backward from the end of +self+ + * If the Integer +index+ is negative, counts backward from the end of +self+ * and inserts +other_string+ at offset index+1 * (that is, _after_ self[index]): * @@ -11236,17 +11236,17 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str) /********************************************************************** * Document-class: Symbol * - * Symbol objects represent named identifiers inside the Ruby interpreter. + * \Symbol objects represent named identifiers inside the Ruby interpreter. * * You can create a \Symbol object explicitly with: * * - A {symbol literal}[rdoc-ref:syntax/literals.rdoc@Symbol+Literals]. * - * The same Symbol object will be + * The same \Symbol object will be * created for a given name or string for the duration of a program's * execution, regardless of the context or meaning of that name. Thus * if Fred is a constant in one context, a method in - * another, and a class in a third, the Symbol :Fred + * another, and a class in a third, the \Symbol :Fred * will be the same object in all three contexts. * * module One @@ -11289,8 +11289,8 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str) * local_variables * # => [:seven] * - * Symbol objects are different from String objects in that - * Symbol objects represent identifiers, while String objects + * \Symbol objects are different from String objects in that + * \Symbol objects represent identifiers, while String objects * represent text or data. * * == What's Here From 7740526b1ccf62a027984e35375bb30ccbc0a000 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 11 Aug 2023 17:50:53 -0700 Subject: [PATCH 002/158] Reorder bp_check and jit_return in cfp It's the actual cfp[6] in the default build, so it's confusing to say otherwise in the comment. --- vm_core.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/vm_core.h b/vm_core.h index d9d926d2ad5ba0..a2c7edf206273c 100644 --- a/vm_core.h +++ b/vm_core.h @@ -813,18 +813,16 @@ struct rb_block { }; typedef struct rb_control_frame_struct { - const VALUE *pc; /* cfp[0] */ - VALUE *sp; /* cfp[1] */ - const rb_iseq_t *iseq; /* cfp[2] */ - VALUE self; /* cfp[3] / block[0] */ - const VALUE *ep; /* cfp[4] / block[1] */ - const void *block_code; /* cfp[5] / block[2] */ /* iseq or ifunc or forwarded block handler */ - + const VALUE *pc; // cfp[0] + VALUE *sp; // cfp[1] + const rb_iseq_t *iseq; // cfp[2] + VALUE self; // cfp[3] / block[0] + const VALUE *ep; // cfp[4] / block[1] + const void *block_code; // cfp[5] / block[2] -- iseq, ifunc, or forwarded block handler + void *jit_return; // cfp[6] -- return address for JIT code #if VM_DEBUG_BP_CHECK - VALUE *bp_check; /* cfp[6] */ + VALUE *bp_check; // cfp[7] #endif - // Return address for YJIT code - void *jit_return; } rb_control_frame_t; extern const rb_data_type_t ruby_threadptr_data_type; From b377793b6e445ab007e14b51e38260e8613ce843 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 26 Nov 2021 22:31:38 +0900 Subject: [PATCH 003/158] Fold dotted outputs from test-spec --- spec/default.mspec | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/spec/default.mspec b/spec/default.mspec index b928a2c9aa2e82..f97bcc690e0a0b 100644 --- a/spec/default.mspec +++ b/spec/default.mspec @@ -70,3 +70,51 @@ end class MSpecScript prepend JobServer end + + +require 'mspec/runner/formatters/dotted' + +class DottedFormatter + prepend Module.new { + BASE = __dir__ + "/ruby/" + + def initialize(out = nil) + super + if out + @columns = nil + else + columns = ENV["COLUMNS"] + @columns = columns ? columns.to_i : 80 + end + @dotted = 0 + @loaded = false + end + + def register + super + MSpec.register :load, self + MSpec.register :unload, self + end + + def after(*) + super + if !@loaded and @columns and (@dotted += 1) >= @columns + print "\n" + @dotted = 0 + end + end + + def load(*) + print "#{MSpec.file.delete_prefix(BASE)}: " + @loaded = true + end + + def unload + super + if @loaded + print "\n" + @dotted = 0 + end + end + } +end From 2373feade50c5d32dad253ad0651a6a8c7c2a8ac Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 27 Nov 2021 18:57:29 +0900 Subject: [PATCH 004/158] For parallel test --- spec/default.mspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/default.mspec b/spec/default.mspec index f97bcc690e0a0b..4cdd63167598a5 100644 --- a/spec/default.mspec +++ b/spec/default.mspec @@ -105,7 +105,8 @@ class DottedFormatter end def load(*) - print "#{MSpec.file.delete_prefix(BASE)}: " + file = MSpec.file || MSpec.files_array.first + print "#{file.delete_prefix(BASE)}: " @loaded = true end From 2c9fbc51005c15600c03b4dc2f545eabd67734b9 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 11 Aug 2023 20:17:33 +0900 Subject: [PATCH 005/158] Add dotted counts --- spec/default.mspec | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/spec/default.mspec b/spec/default.mspec index 4cdd63167598a5..e2ad19e1173ade 100644 --- a/spec/default.mspec +++ b/spec/default.mspec @@ -71,7 +71,6 @@ class MSpecScript prepend JobServer end - require 'mspec/runner/formatters/dotted' class DottedFormatter @@ -83,11 +82,12 @@ class DottedFormatter if out @columns = nil else - columns = ENV["COLUMNS"] - @columns = columns ? columns.to_i : 80 + columns = ENV["COLUMNS"]&.to_i + @columns = columns&.nonzero? || 80 end @dotted = 0 @loaded = false + @count = 0 end def register @@ -97,8 +97,16 @@ class DottedFormatter end def after(*) + if @columns + if @dotted == 0 + s = sprintf("%6d ", @count) + print(s) + @dotted += s.size + end + @count +=1 + end super - if !@loaded and @columns and (@dotted += 1) >= @columns + if @columns and (@dotted += 1) >= @columns print "\n" @dotted = 0 end @@ -106,15 +114,27 @@ class DottedFormatter def load(*) file = MSpec.file || MSpec.files_array.first - print "#{file.delete_prefix(BASE)}: " @loaded = true + s = "#{file.delete_prefix(BASE)}:" + print s + if @columns + if (@dotted += s.size) >= @columns + print "\n" + @dotted = 0 + else + print " " + @dotted += 1 + end + end + @count = 0 end def unload super if @loaded - print "\n" + print "\n" if @dotted > 0 @dotted = 0 + @loaded = nil end end } From 46c428a926b00f09b8e50dcd0366422d695e15c8 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 11 Aug 2023 21:52:38 +0900 Subject: [PATCH 006/158] Make test-spec on Windows silent a little --- .appveyor.yml | 4 ++-- .github/workflows/windows.yml | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2762a5759cfd88..fdab2008e8b767 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -103,7 +103,7 @@ for: # separately execute tests without -j which may crash worker with -j. - >- nmake -l - "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor" + "TESTOPTS=--timeout-scale=3.0 --excludes=../test/excludes/_appveyor" TESTS=" ../test/win32ole ../test/ruby/test_bignum.rb @@ -111,7 +111,7 @@ for: ../test/open-uri/test_open-uri.rb ../test/rubygems/test_bundled_ca.rb " test-all - - nmake -l test-spec MSPECOPT=-fs # not using `-j` because sometimes `mspec -j` silently dies on Windows + - nmake -l test-spec # not using `-j` because sometimes `mspec -j` silently dies on Windows notifications: - provider: Webhook method: POST diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 74975ca694865f..49e2ce5738439e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -129,8 +129,10 @@ jobs: :vcset set | C:\msys64\usr\bin\sort > old.env call %VCVARS% + nmake -f nul set TMP=%USERPROFILE%\AppData\Local\Temp set TEMP=%USERPROFILE%\AppData\Local\Temp + set MAKEFLAGS=l set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul set | C:\msys64\usr\bin\sort > new.env C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV% @@ -162,7 +164,7 @@ jobs: - run: nmake test timeout-minutes: 5 - - run: nmake test-spec MSPECOPT="-V -fspec" + - run: nmake test-spec timeout-minutes: 10 - run: nmake test-all From 0eb21082146f4a95fa8645fe6ffe1e6929e61e55 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 12 Aug 2023 12:32:31 +0900 Subject: [PATCH 007/158] Use the default test-spec formatter on Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3626a4c1c4fd14..c6054ae6723a46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -209,7 +209,7 @@ script: if [ -n "${TEST_ALL_OPTS_SEPARATED}" ]; then $SETARCH make -s test-all -o exts TESTOPTS="$JOBS -v --tty=no ${TEST_ALL_OPTS_SEPARATED}" RUBYOPT="-w" || : fi - - $SETARCH make -s test-spec MSPECOPT=-ff # not using `-j` because sometimes `mspec -j` silently dies + - $SETARCH make -s test-spec # not using `-j` because sometimes `mspec -j` silently dies - $SETARCH make -s -o showflags leaked-globals # We enable Travis on the specific branches or forked repositories here. From 6ebde0420224b73977a35877eb65f0d3700513d5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 12 Aug 2023 12:33:05 +0900 Subject: [PATCH 008/158] [DOC] Update to use `SPECOPTS` instead of `MSPECOPT` --- doc/contributing/testing_ruby.md | 12 ++++++------ spec/README.md | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/contributing/testing_ruby.md b/doc/contributing/testing_ruby.md index 167ab55c55848c..8decc24083538b 100644 --- a/doc/contributing/testing_ruby.md +++ b/doc/contributing/testing_ruby.md @@ -99,28 +99,28 @@ We can run any of the make scripts [in parallel](building_ruby.md#label-Running+ make test-spec ``` - To run a specific directory, we can use `MSPECOPT` to specify the directory: + To run a specific directory, we can use `SPECOPTS` to specify the directory: ``` - make test-spec MSPECOPT=spec/ruby/core/array + make test-spec SPECOPTS=spec/ruby/core/array ``` - To run a specific file, we can also use `MSPECOPT` to specify the file: + To run a specific file, we can also use `SPECOPTS` to specify the file: ``` - make test-spec MSPECOPT=spec/ruby/core/array/any_spec.rb + make test-spec SPECOPTS=spec/ruby/core/array/any_spec.rb ``` To run a specific test, we can use the `--example` flag to match against the test name: ``` - make test-spec MSPECOPT="../spec/ruby/core/array/any_spec.rb --example='is false if the array is empty'" + make test-spec SPECOPTS="../spec/ruby/core/array/any_spec.rb --example='is false if the array is empty'" ``` To run these specs with logs, we can use: ``` - make test-spec MSPECOPT=-Vfs + make test-spec SPECOPTS=-Vfs ``` To run a ruby-spec file or directory with GNU make, we can use diff --git a/spec/README.md b/spec/README.md index 4fcf090759d740..6a88c06e094e38 100644 --- a/spec/README.md +++ b/spec/README.md @@ -91,24 +91,24 @@ To run all specs: make test-spec ``` -Extra arguments can be added via `MSPECOPT`. +Extra arguments can be added via `SPECOPTS`. For instance, to show the help: ```bash -make test-spec MSPECOPT=-h +make test-spec SPECOPTS=-h ``` You can also run the specs in parallel, which is currently experimental. It takes around 10s instead of 60s on a quad-core laptop. ```bash -make test-spec MSPECOPT=-j +make test-spec SPECOPTS=-j ``` To run a specific test, add its path to the command: ```bash -make test-spec MSPECOPT=spec/ruby/language/for_spec.rb +make test-spec SPECOPTS=spec/ruby/language/for_spec.rb ``` If ruby trunk is your current `ruby` in `$PATH`, you can also run `mspec` directly: From d1b1e4a3ffc294b52c3934fdbce60807b9b708e7 Mon Sep 17 00:00:00 2001 From: git Date: Sat, 12 Aug 2023 07:00:20 +0000 Subject: [PATCH 009/158] Update bundled gems list at 2023-08-12 --- NEWS.md | 1 + gems/bundled_gems | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 9e1f3527a170d3..cdd3e38a69b7eb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -89,6 +89,7 @@ The following bundled gems are updated. * minitest 5.19.0 * test-unit 3.6.1 * rexml 3.2.6 +* rss 0.3.0 * net-imap 0.3.7 * rbs 3.1.3 * typeprof 0.21.7 diff --git a/gems/bundled_gems b/gems/bundled_gems index 68bcaa6d19dc8e..af08c6c82d1c3e 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -10,7 +10,7 @@ power_assert 2.0.3 https://github.com/ruby/power_assert rake 13.0.6 https://github.com/ruby/rake test-unit 3.6.1 https://github.com/test-unit/test-unit rexml 3.2.6 https://github.com/ruby/rexml -rss 0.2.9 https://github.com/ruby/rss +rss 0.3.0 https://github.com/ruby/rss net-ftp 0.2.0 https://github.com/ruby/net-ftp net-imap 0.3.7 https://github.com/ruby/net-imap net-pop 0.1.2 https://github.com/ruby/net-pop From 680835085df7695b18af40c7a8554f2d314b5de5 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sat, 12 Aug 2023 11:17:48 +0100 Subject: [PATCH 010/158] [ruby/irb] Reline/ReadlineInputMethod should inherit StdioInputMethod (https://github.com/ruby/irb/pull/671) They are both built on top of stdio and are basically extended version of StdioInputMethod. They also share several attributes and methods with StdioInputMethod. https://github.com/ruby/irb/commit/c5f5abdbde --- lib/irb/input-method.rb | 62 ++++------------------------------------- 1 file changed, 6 insertions(+), 56 deletions(-) diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index 245b935668b3af..b574a3fe1fd557 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -160,7 +160,7 @@ def close end begin - class ReadlineInputMethod < InputMethod + class ReadlineInputMethod < StdioInputMethod def self.initialize_readline require "readline" rescue LoadError @@ -177,12 +177,9 @@ def initialize IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false) end - @line_no = 0 - @line = [] - @eof = false + super - @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") - @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + @eof = false if Readline.respond_to?("basic_word_break_characters=") Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS @@ -214,28 +211,6 @@ def eof? @eof end - # Whether this input method is still readable when there is no more data to - # read. - # - # See IO#eof for more information. - def readable_after_eof? - true - end - - # Returns the current line number for #io. - # - # #line counts the number of times #gets is called. - # - # See IO#lineno for more information. - def line(line_no) - @line[line_no] - end - - # The external encoding for standard input. - def encoding - @stdin.external_encoding - end - # For debug message def inspect readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline' @@ -247,19 +222,16 @@ def inspect end end - class RelineInputMethod < InputMethod + class RelineInputMethod < StdioInputMethod HISTORY = Reline::HISTORY include HistorySavingAbility # Creates a new input method object using Reline def initialize IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false) - @line_no = 0 - @line = [] - @eof = false + super - @stdin = ::IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") - @stdout = ::IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + @eof = false Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS Reline.completion_append_character = nil @@ -421,28 +393,6 @@ def eof? @eof end - # Whether this input method is still readable when there is no more data to - # read. - # - # See IO#eof for more information. - def readable_after_eof? - true - end - - # Returns the current line number for #io. - # - # #line counts the number of times #gets is called. - # - # See IO#lineno for more information. - def line(line_no) - @line[line_no] - end - - # The external encoding for standard input. - def encoding - @stdin.external_encoding - end - # For debug message def inspect config = Reline::Config.new From e1683b4958b217d246ff737bdd1b046554c73e18 Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Sat, 12 Aug 2023 19:19:20 +0900 Subject: [PATCH 011/158] [ruby/irb] Drop showing indent level number in DEFAULT prompt and INF_RUBY prompt (https://github.com/ruby/irb/pull/679) * Drop showing indent level number in DEFAULT prompt and INF_RUBY prompt * Update prompt part of test_rendering's expected result https://github.com/ruby/irb/commit/3847532e54 --- lib/irb.rb | 18 ++--- lib/irb/init.rb | 10 +-- test/irb/yamatanooroti/test_rendering.rb | 88 ++++++++++++------------ 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/lib/irb.rb b/lib/irb.rb index 8f2934a7e443f7..e0025ab3e8778c 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -194,10 +194,10 @@ # For instance, the default prompt mode is defined as follows: # # IRB.conf[:PROMPT_MODE][:DEFAULT] = { -# :PROMPT_I => "%N(%m):%03n:%i> ", -# :PROMPT_N => "%N(%m):%03n:%i> ", -# :PROMPT_S => "%N(%m):%03n:%i%l ", -# :PROMPT_C => "%N(%m):%03n:%i* ", +# :PROMPT_I => "%N(%m):%03n> ", +# :PROMPT_N => "%N(%m):%03n> ", +# :PROMPT_S => "%N(%m):%03n%l ", +# :PROMPT_C => "%N(%m):%03n* ", # :RETURN => "%s\n" # used to printf # } # @@ -211,10 +211,10 @@ # # :RETURN: | # # %s # # :DEFAULT: -# # :PROMPT_I: ! '%N(%m):%03n:%i> ' -# # :PROMPT_N: ! '%N(%m):%03n:%i> ' -# # :PROMPT_S: ! '%N(%m):%03n:%i%l ' -# # :PROMPT_C: ! '%N(%m):%03n:%i* ' +# # :PROMPT_I: ! '%N(%m):%03n> ' +# # :PROMPT_N: ! '%N(%m):%03n> ' +# # :PROMPT_S: ! '%N(%m):%03n%l ' +# # :PROMPT_C: ! '%N(%m):%03n* ' # # :RETURN: | # # => %s # # :CLASSIC: @@ -232,7 +232,7 @@ # # :RETURN: | # # => %s # # :INF_RUBY: -# # :PROMPT_I: ! '%N(%m):%03n:%i> ' +# # :PROMPT_I: ! '%N(%m):%03n> ' # # :PROMPT_N: # # :PROMPT_S: # # :PROMPT_C: diff --git a/lib/irb/init.rb b/lib/irb/init.rb index 75a7f8d74c0812..ef07a5f1e6b3f9 100644 --- a/lib/irb/init.rb +++ b/lib/irb/init.rb @@ -64,10 +64,10 @@ def IRB.init_config(ap_path) :RETURN => "%s\n" }, :DEFAULT => { - :PROMPT_I => "%N(%m):%03n:%i> ", - :PROMPT_N => "%N(%m):%03n:%i> ", - :PROMPT_S => "%N(%m):%03n:%i%l ", - :PROMPT_C => "%N(%m):%03n:%i* ", + :PROMPT_I => "%N(%m):%03n> ", + :PROMPT_N => "%N(%m):%03n> ", + :PROMPT_S => "%N(%m):%03n%l ", + :PROMPT_C => "%N(%m):%03n* ", :RETURN => "=> %s\n" }, :CLASSIC => { @@ -85,7 +85,7 @@ def IRB.init_config(ap_path) :RETURN => "=> %s\n" }, :INF_RUBY => { - :PROMPT_I => "%N(%m):%03n:%i> ", + :PROMPT_I => "%N(%m):%03n> ", :PROMPT_N => nil, :PROMPT_S => nil, :PROMPT_C => nil, diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb index e146ee490aceb9..6da7fded2b64ad 100644 --- a/test/irb/yamatanooroti/test_rendering.rb +++ b/test/irb/yamatanooroti/test_rendering.rb @@ -41,9 +41,9 @@ def test_launch close assert_screen(<<~EOC) start IRB - irb(main):001:0> 'Hello, World!' + irb(main):001> 'Hello, World!' => "Hello, World!" - irb(main):002:0> + irb(main):002> EOC end @@ -68,21 +68,21 @@ def b; true; end close assert_screen(<<~EOC) start IRB - irb(main):001:1* class A - irb(main):002:1* def inspect; '#'; end - irb(main):003:1* def a; self; end - irb(main):004:1* def b; true; end - irb(main):005:0> end + irb(main):001* class A + irb(main):002* def inspect; '#'; end + irb(main):003* def a; self; end + irb(main):004* def b; true; end + irb(main):005> end => :b - irb(main):006:0> - irb(main):007:0> a = A.new + irb(main):006> + irb(main):007> a = A.new => # - irb(main):008:0> - irb(main):009:0> a - irb(main):010:0> .a - irb(main):011:0> .b + irb(main):008> + irb(main):009> a + irb(main):010> .a + irb(main):011> .b => true - irb(main):012:0> + irb(main):012> EOC end @@ -121,39 +121,39 @@ class A def b; self; end; def c; true; end; end; close assert_screen(<<~EOC) start IRB - irb(main):001:1* class A - irb(main):002:1* def inspect; '#'; end - irb(main):003:1* def b; self; end - irb(main):004:1* def c; true; end - irb(main):005:0> end + irb(main):001* class A + irb(main):002* def inspect; '#'; end + irb(main):003* def b; self; end + irb(main):004* def c; true; end + irb(main):005> end => :c - irb(main):006:0> - irb(main):007:0> a = A.new + irb(main):006> + irb(main):007> a = A.new => # - irb(main):008:0> - irb(main):009:0> a - irb(main):010:0> .b - irb(main):011:0> # aaa - irb(main):012:0> .c + irb(main):008> + irb(main):009> a + irb(main):010> .b + irb(main):011> # aaa + irb(main):012> .c => true - irb(main):013:0> - irb(main):014:0> (a) - irb(main):015:0> &.b() + irb(main):013> + irb(main):014> (a) + irb(main):015> &.b() => # - irb(main):016:0> - irb(main):017:0> - irb(main):018:0> class A def b; self; end; def c; true; end; end; - irb(main):019:0> a = A.new + irb(main):016> + irb(main):017> + irb(main):018> class A def b; self; end; def c; true; end; end; + irb(main):019> a = A.new => # - irb(main):020:0> a - irb(main):021:0> .b - irb(main):022:0> # aaa - irb(main):023:0> .c + irb(main):020> a + irb(main):021> .b + irb(main):022> # aaa + irb(main):023> .c => true - irb(main):024:0> (a) - irb(main):025:0> &.b() + irb(main):024> (a) + irb(main):025> &.b() => # - irb(main):026:0> + irb(main):026> EOC end @@ -168,9 +168,9 @@ def test_symbol_with_backtick close assert_screen(<<~EOC) start IRB - irb(main):001:0> :` + irb(main):001> :` => :` - irb(main):002:0> + irb(main):002> EOC end @@ -243,11 +243,11 @@ def test_assignment_expression_truncate close assert_screen(<<~EOC) start IRB - irb(main):001:0> #{code} + irb(main):001> #{code} => [0, ... - irb(main):002:0> + irb(main):002> EOC end From b18462c14be62f7572ed03dee470ffb99ae74521 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Sat, 12 Aug 2023 14:54:39 +0100 Subject: [PATCH 012/158] [DOC] Don't suppress autolinks --- hash.c | 122 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/hash.c b/hash.c index 6a4c9633e67128..c445ca55664e78 100644 --- a/hash.c +++ b/hash.c @@ -1765,7 +1765,7 @@ static VALUE rb_hash_to_a(VALUE hash); * h = {foo: 0, bar: 1, baz: 2} * Hash[h] # => {:foo=>0, :bar=>1, :baz=>2} * - * When the single given argument is an \Array of 2-element Arrays, + * When the single given argument is an Array of 2-element Arrays, * returns a new \Hash object wherein each 2-element array forms a * key-value entry: * @@ -2419,7 +2419,7 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) * * Removes the first hash entry * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]); - * returns a 2-element \Array containing the removed key and value: + * returns a 2-element Array containing the removed key and value: * h = {foo: 0, bar: 1, baz: 2} * h.shift # => [:foo, 0] * h # => {:bar=>1, :baz=>2} @@ -2493,7 +2493,7 @@ hash_enum_size(VALUE hash, VALUE args, VALUE eobj) * h = {foo: 0, bar: 1, baz: 2} * h.delete_if {|key, value| value > 0 } # => {:foo=>0} * - * If no block given, returns a new \Enumerator: + * If no block given, returns a new Enumerator: * h = {foo: 0, bar: 1, baz: 2} * e = h.delete_if # => #0, :bar=>1, :baz=>2}:delete_if> * e.each { |key, value| value > 0 } # => {:foo=>0} @@ -2522,7 +2522,7 @@ rb_hash_delete_if(VALUE hash) * * Returns +nil+ if no entries are removed. * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.reject! # => #0, :bar=>1, :baz=>2}:reject!> * e.each {|key, value| key.start_with?('b') } # => {:foo=>0} @@ -2553,7 +2553,7 @@ rb_hash_reject_bang(VALUE hash) * h1 = h.reject {|key, value| key.start_with?('b') } * h1 # => {:foo=>0} * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.reject # => #0, :bar=>1, :baz=>2}:reject> * h1 = e.each {|key, value| key.start_with?('b') } @@ -2636,7 +2636,7 @@ rb_hash_except(int argc, VALUE *argv, VALUE hash) * call-seq: * hash.values_at(*keys) -> new_array * - * Returns a new \Array containing values for the given +keys+: + * Returns a new Array containing values for the given +keys+: * h = {foo: 0, bar: 1, baz: 2} * h.values_at(:baz, :foo) # => [2, 0] * @@ -2662,11 +2662,11 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) * hash.fetch_values(*keys) -> new_array * hash.fetch_values(*keys) {|key| ... } -> new_array * - * Returns a new \Array containing the values associated with the given keys *keys: + * Returns a new Array containing the values associated with the given keys *keys: * h = {foo: 0, bar: 1, baz: 2} * h.fetch_values(:baz, :foo) # => [2, 0] * - * Returns a new empty \Array if no arguments given. + * Returns a new empty Array if no arguments given. * * When a block is given, calls the block with each missing key, * treating the block's return value as the value for that key: @@ -2708,7 +2708,7 @@ keep_if_i(VALUE key, VALUE value, VALUE hash) * h = {foo: 0, bar: 1, baz: 2} * h.select {|key, value| value < 2 } # => {:foo=>0, :bar=>1} * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.select # => #0, :bar=>1, :baz=>2}:select> * e.each {|key, value| value < 2 } # => {:foo=>0, :bar=>1} @@ -2738,7 +2738,7 @@ rb_hash_select(VALUE hash) * * Returns +nil+ if no entries were removed. * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.select! # => #0, :bar=>1, :baz=>2}:select!> * e.each { |key, value| value < 2 } # => {:foo=>0, :bar=>1} @@ -2769,7 +2769,7 @@ rb_hash_select_bang(VALUE hash) * h = {foo: 0, bar: 1, baz: 2} * h.keep_if { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2} * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.keep_if # => #0, :bar=>1, :baz=>2}:keep_if> * e.each { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2} @@ -2979,7 +2979,7 @@ each_value_i(VALUE key, VALUE value, VALUE _) * 1 * 2 * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.each_value # => #0, :bar=>1, :baz=>2}:each_value> * h1 = e.each {|value| puts value } @@ -3018,7 +3018,7 @@ each_key_i(VALUE key, VALUE value, VALUE _) * bar * baz * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.each_key # => #0, :bar=>1, :baz=>2}:each_key> * h1 = e.each {|key| puts key } @@ -3068,7 +3068,7 @@ each_pair_i_fast(VALUE key, VALUE value, VALUE _) * bar: 1 * baz: 2 * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.each_pair # => #0, :bar=>1, :baz=>2}:each_pair> * h1 = e.each {|key, value| puts "#{key}: #{value}"} @@ -3151,7 +3151,7 @@ transform_keys_i(VALUE key, VALUE value, VALUE result) * h1 = h.transform_keys {|key| :bat } * h1 # => {:bat=>2} * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.transform_keys # => #0, :bar=>1, :baz=>2}:transform_keys> * h1 = e.each { |key| key.to_s } @@ -3275,7 +3275,7 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg * h1 = h.transform_values {|value| value * 100} * h1 # => {:foo=>0, :bar=>100, :baz=>200} * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.transform_values # => #0, :bar=>1, :baz=>2}:transform_values> * h1 = e.each { |value| value * 100} @@ -3306,7 +3306,7 @@ rb_hash_transform_values(VALUE hash) * h = {foo: 0, bar: 1, baz: 2} * h.transform_values! {|value| value * 100} # => {:foo=>0, :bar=>100, :baz=>200} * - * Returns a new \Enumerator if no block given: + * Returns a new Enumerator if no block given: * h = {foo: 0, bar: 1, baz: 2} * e = h.transform_values! # => #0, :bar=>100, :baz=>200}:transform_values!> * h1 = e.each {|value| value * 100} @@ -3336,8 +3336,8 @@ to_a_i(VALUE key, VALUE value, VALUE ary) * call-seq: * hash.to_a -> new_array * - * Returns a new \Array of 2-element \Array objects; - * each nested \Array contains a key-value pair from +self+: + * Returns a new Array of 2-element Array objects; + * each nested Array contains a key-value pair from +self+: * h = {foo: 0, bar: 1, baz: 2} * h.to_a # => [[:foo, 0], [:bar, 1], [:baz, 2]] */ @@ -3390,7 +3390,7 @@ inspect_hash(VALUE hash, VALUE dummy, int recur) * call-seq: * hash.inspect -> new_string * - * Returns a new \String containing the hash entries: + * Returns a new String containing the hash entries: * h = {foo: 0, bar: 1, baz: 2} * h.inspect # => "{:foo=>0, :bar=>1, :baz=>2}" @@ -3462,8 +3462,8 @@ rb_hash_to_h_block(VALUE hash) * * When a block is given, returns a new \Hash object * whose content is based on the block; - * the block should return a 2-element \Array object - * specifying the key-value pair to be included in the returned \Array: + * the block should return a 2-element Array object + * specifying the key-value pair to be included in the returned Array: * h = {foo: 0, bar: 1, baz: 2} * h1 = h.to_h {|key, value| [value, key] } * h1 # => {0=>:foo, 1=>:bar, 2=>:baz} @@ -3493,7 +3493,7 @@ keys_i(VALUE key, VALUE value, VALUE ary) * call-seq: * hash.keys -> new_array * - * Returns a new \Array containing all keys in +self+: + * Returns a new Array containing all keys in +self+: * h = {foo: 0, bar: 1, baz: 2} * h.keys # => [:foo, :bar, :baz] */ @@ -3537,7 +3537,7 @@ values_i(VALUE key, VALUE value, VALUE ary) * call-seq: * hash.values -> new_array * - * Returns a new \Array containing all values in +self+: + * Returns a new Array containing all values in +self+: * h = {foo: 0, bar: 1, baz: 2} * h.values # => [0, 1, 2] */ @@ -3769,7 +3769,7 @@ hash_i(VALUE key, VALUE val, VALUE arg) * call-seq: * hash.hash -> an_integer * - * Returns the \Integer hash-code for the hash. + * Returns the Integer hash-code for the hash. * * Two \Hash objects have the same hash-code if their content is the same * (regardless or order): @@ -4076,7 +4076,7 @@ assoc_i(VALUE key, VALUE val, VALUE arg) * call-seq: * hash.assoc(key) -> new_array or nil * - * If the given +key+ is found, returns a 2-element \Array containing that key and its value: + * If the given +key+ is found, returns a 2-element Array containing that key and its value: * h = {foo: 0, bar: 1, baz: 2} * h.assoc(:bar) # => [:bar, 1] * @@ -4135,7 +4135,7 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) * call-seq: * hash.rassoc(value) -> new_array or nil * - * Returns a new 2-element \Array consisting of the key and value + * Returns a new 2-element Array consisting of the key and value * of the first-found entry whose value is == to value * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]): * h = {foo: 0, bar: 1, baz: 1} @@ -4172,7 +4172,7 @@ flatten_i(VALUE key, VALUE val, VALUE ary) * hash.flatten -> new_array * hash.flatten(level) -> new_array * - * Returns a new \Array object that is a 1-dimensional flattening of +self+. + * Returns a new Array object that is a 1-dimensional flattening of +self+. * * --- * @@ -4180,7 +4180,7 @@ flatten_i(VALUE key, VALUE val, VALUE ary) * h = {foo: 0, bar: [:bat, 3], baz: 2} * h.flatten # => [:foo, 0, :bar, [:bat, 3], :baz, 2] * - * Takes the depth of recursive flattening from \Integer argument +level+: + * Takes the depth of recursive flattening from Integer argument +level+: * h = {foo: 0, bar: [:bat, [:baz, [:bat, ]]]} * h.flatten(1) # => [:foo, 0, :bar, [:bat, [:baz, [:bat]]]] * h.flatten(2) # => [:foo, 0, :bar, :bat, [:baz, [:bat]]] @@ -4617,7 +4617,7 @@ hash_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(key, hash)) * call-seq: * hash.to_proc -> proc * - * Returns a \Proc object that maps a key to its value: + * Returns a Proc object that maps a key to its value: * h = {foo: 0, bar: 1, baz: 2} * proc = h.to_proc * proc.class # => Proc @@ -5488,7 +5488,7 @@ env_each_value(VALUE ehash) * ENV.each_pair { |name, value| block } -> ENV * ENV.each_pair -> an_enumerator * - * Yields each environment variable name and its value as a 2-element \Array: + * Yields each environment variable name and its value as a 2-element Array: * h = {} * ENV.each_pair { |name, value| h[name] = value } # => ENV * h # => {"bar"=>"1", "foo"=>"0"} @@ -5624,7 +5624,7 @@ env_delete_if(VALUE ehash) * Returns +nil+ in the Array for each name that is not an ENV name: * ENV.values_at('foo', 'bat', 'bar', 'bam') # => ["0", nil, "1", nil] * - * Returns an empty \Array if no names given. + * Returns an empty Array if no names given. * * Raises an exception if any name is invalid. * See {Invalid Names and Values}[rdoc-ref:ENV@Invalid+Names+and+Values]. @@ -6573,8 +6573,8 @@ static const rb_data_type_t env_data_type = { /* * A \Hash maps each of its unique keys to a specific value. * - * A \Hash has certain similarities to an \Array, but: - * - An \Array index is always an \Integer. + * A \Hash has certain similarities to an Array, but: + * - An Array index is always an Integer. * - A \Hash key can be (almost) any object. * * === \Hash \Data Syntax @@ -6584,14 +6584,14 @@ static const rb_data_type_t env_data_type = { * h = {:foo => 0, :bar => 1, :baz => 2} * h # => {:foo=>0, :bar=>1, :baz=>2} * - * Alternatively, but only for a \Hash key that's a \Symbol, + * Alternatively, but only for a \Hash key that's a Symbol, * you can use a newer JSON-style syntax, - * where each bareword becomes a \Symbol: + * where each bareword becomes a Symbol: * * h = {foo: 0, bar: 1, baz: 2} * h # => {:foo=>0, :bar=>1, :baz=>2} * - * You can also use a \String in place of a bareword: + * You can also use a String in place of a bareword: * * h = {'foo': 0, 'bar': 1, 'baz': 2} * h # => {:foo=>0, :bar=>1, :baz=>2} @@ -6716,7 +6716,7 @@ static const rb_data_type_t env_data_type = { * * - Iterative methods such as each, each_key, each_pair, each_value. * - Other order-sensitive methods such as shift, keys, values. - * - The \String returned by method inspect. + * - The String returned by method inspect. * * A new \Hash has its initial ordering per the given entries: * @@ -6775,9 +6775,9 @@ static const rb_data_type_t env_data_type = { * h.include?(a0) # => true * h[a0] # => 0 * - * A \String key is always safe. - * That's because an unfrozen \String - * passed as a key will be replaced by a duplicated and frozen \String: + * A String key is always safe. + * That's because an unfrozen String + * passed as a key will be replaced by a duplicated and frozen String: * * s = 'foo' * s.frozen? # => false @@ -6791,9 +6791,9 @@ static const rb_data_type_t env_data_type = { * Note: this requirement does not apply if the \Hash uses #compare_by_identity since comparison will then * rely on the keys' object id instead of hash and eql?. * - * \Object defines basic implementation for hash and eq? that makes each object + * Object defines basic implementation for hash and eq? that makes each object * a distinct key. Typically, user-defined classes will want to override these methods to provide meaningful - * behavior, or for example inherit \Struct that has useful definitions for these. + * behavior, or for example inherit Struct that has useful definitions for these. * * A typical implementation of hash is based on the * object's data while eql? is usually aliased to the overridden @@ -6874,7 +6874,7 @@ static const rb_data_type_t env_data_type = { * * To use a mutable object as default, it is recommended to use a default proc * - * ==== Default \Proc + * ==== Default Proc * * When the default proc for a \Hash is set (i.e., not +nil+), * the default value returned by method #[] is determined by the default proc alone. @@ -7153,15 +7153,15 @@ Init_Hash(void) /* Document-class: ENV * - * ENV is a hash-like accessor for environment variables. + * \ENV is a hash-like accessor for environment variables. * * === Interaction with the Operating System * - * The ENV object interacts with the operating system's environment variables: + * The \ENV object interacts with the operating system's environment variables: * - * - When you get the value for a name in ENV, the value is retrieved from among the current environment variables. - * - When you create or set a name-value pair in ENV, the name and value are immediately set in the environment variables. - * - When you delete a name-value pair in ENV, it is immediately deleted from the environment variables. + * - When you get the value for a name in \ENV, the value is retrieved from among the current environment variables. + * - When you create or set a name-value pair in \ENV, the name and value are immediately set in the environment variables. + * - When you delete a name-value pair in \ENV, it is immediately deleted from the environment variables. * * === Names and Values * @@ -7211,24 +7211,24 @@ Init_Hash(void) * * === About Ordering * - * ENV enumerates its name/value pairs in the order found + * \ENV enumerates its name/value pairs in the order found * in the operating system's environment variables. - * Therefore the ordering of ENV content is OS-dependent, and may be indeterminate. + * Therefore the ordering of \ENV content is OS-dependent, and may be indeterminate. * * This will be seen in: - * - A Hash returned by an ENV method. - * - An Enumerator returned by an ENV method. + * - A Hash returned by an \ENV method. + * - An Enumerator returned by an \ENV method. * - An Array returned by ENV.keys, ENV.values, or ENV.to_a. * - The String returned by ENV.inspect. * - The Array returned by ENV.shift. * - The name returned by ENV.key. * * === About the Examples - * Some methods in ENV return ENV itself. Typically, there are many environment variables. - * It's not useful to display a large ENV in the examples here, - * so most example snippets begin by resetting the contents of ENV: - * - ENV.replace replaces ENV with a new collection of entries. - * - ENV.clear empties ENV. + * Some methods in \ENV return \ENV itself. Typically, there are many environment variables. + * It's not useful to display a large \ENV in the examples here, + * so most example snippets begin by resetting the contents of \ENV: + * - ENV.replace replaces \ENV with a new collection of entries. + * - ENV.clear empties \ENV. * * == What's Here * @@ -7288,8 +7288,8 @@ Init_Hash(void) * - ::except: Returns a hash of all name/value pairs except those given. * - ::fetch: Returns the value for the given name. * - ::inspect: Returns the contents of \ENV as a string. - * - ::invert: Returns a hash whose keys are the ENV values, - and whose values are the corresponding ENV names. + * - ::invert: Returns a hash whose keys are the \ENV values, + and whose values are the corresponding \ENV names. * - ::keys: Returns an array of all names. * - ::rassoc: Returns the name and value of the first found entry * that has the given value. @@ -7378,7 +7378,7 @@ Init_Hash(void) rb_undef_method(envtbl_class, "initialize_dup"); /* - * ENV is a Hash-like accessor for environment variables. + * \ENV is a Hash-like accessor for environment variables. * * See ENV (the class) for more details. */ From 546c5cfe4ce1335cb45f8e7b6d6da317c61509e7 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Sat, 12 Aug 2023 17:44:38 +0100 Subject: [PATCH 013/158] [DOC] Don't suppress autolinks --- file.c | 22 +++++++++++----------- io.c | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/file.c b/file.c index 89afe7a0d07a1f..e753e116de68f7 100644 --- a/file.c +++ b/file.c @@ -6539,11 +6539,11 @@ const char ruby_null_device[] = * * == Access Modes * - * \Methods File.new and File.open each create a \File object for a given file path. + * Methods File.new and File.open each create a \File object for a given file path. * * === \String Access Modes * - * \Methods File.new and File.open each may take string argument +mode+, which: + * Methods File.new and File.open each may take string argument +mode+, which: * * - Begins with a 1- or 2-character * {read/write mode}[rdoc-ref:File@Read-2FWrite+Mode]. @@ -7179,7 +7179,7 @@ const char ruby_null_device[] = * * == \File \Constants * - * Various constants for use in \File and \IO methods + * Various constants for use in \File and IO methods * may be found in module File::Constants; * an array of their names is returned by File::Constants.constants. * @@ -7234,15 +7234,15 @@ const char ruby_null_device[] = * * _Times_ * - * - ::atime: Returns a \Time for the most recent access to the given file. - * - ::birthtime: Returns a \Time for the creation of the given file. - * - ::ctime: Returns a \Time for the metadata change of the given file. - * - ::mtime: Returns a \Time for the most recent data modification to + * - ::atime: Returns a Time for the most recent access to the given file. + * - ::birthtime: Returns a Time for the creation of the given file. + * - ::ctime: Returns a Time for the metadata change of the given file. + * - ::mtime: Returns a Time for the most recent data modification to * the content of the given file. - * - #atime: Returns a \Time for the most recent access to +self+. - * - #birthtime: Returns a \Time the creation for +self+. - * - #ctime: Returns a \Time for the metadata change of +self+. - * - #mtime: Returns a \Time for the most recent data modification + * - #atime: Returns a Time for the most recent access to +self+. + * - #birthtime: Returns a Time the creation for +self+. + * - #ctime: Returns a Time for the metadata change of +self+. + * - #mtime: Returns a Time for the most recent data modification * to the content of +self+. * * _Types_ diff --git a/io.c b/io.c index d0cc6f2d90e86d..f54f01963fe3b2 100644 --- a/io.c +++ b/io.c @@ -846,7 +846,7 @@ rb_io_timeout(VALUE self) * timeout = duration -> duration * timeout = nil -> nil * - * \Set the internal timeout to the specified duration or nil. The timeout + * Sets the internal timeout to the specified duration or nil. The timeout * applies to all blocking operations where possible. * * When the operation performs longer than the timeout set, IO::TimeoutError @@ -8007,11 +8007,11 @@ rb_open_file(int argc, const VALUE *argv, VALUE io) * File.open(path, mode = 'r', perm = 0666, **opts) -> file * File.open(path, mode = 'r', perm = 0666, **opts) {|f| ... } -> object * - * Creates a new \File object, via File.new with the given arguments. + * Creates a new File object, via File.new with the given arguments. * - * With no block given, returns the \File object. + * With no block given, returns the File object. * - * With a block given, calls the block with the \File object + * With a block given, calls the block with the File object * and returns the block's value. * */ @@ -8799,9 +8799,9 @@ io_puts_ary(VALUE ary, VALUE out, int recur) * * Treatment for each object: * - * - \String: writes the string. + * - String: writes the string. * - Neither string nor array: writes object.to_s. - * - \Array: writes each element of the array; arrays may be nested. + * - Array: writes each element of the array; arrays may be nested. * * To keep these examples brief, we define this helper method: * @@ -9460,9 +9460,9 @@ rb_io_set_encoding_by_bom(VALUE io) * File.new(path, mode = 'r', perm = 0666, **opts) -> file * * Opens the file at the given +path+ according to the given +mode+; - * creates and returns a new \File object for that file. + * creates and returns a new File object for that file. * - * The new \File object is buffered mode (or non-sync mode), unless + * The new File object is buffered mode (or non-sync mode), unless * +filename+ is a tty. * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync=. * @@ -14656,7 +14656,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y) * ARGF is not itself a subclass of \IO. * * \Class StringIO provides an IO-like stream that handles a String. - * \StringIO is not itself a subclass of \IO. + * StringIO is not itself a subclass of \IO. * * Important objects based on \IO include: * @@ -14674,7 +14674,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y) * - Kernel#open: Returns a new \IO object connected to a given source: * stream, file, or subprocess. * - * Like a \File stream, an \IO stream has: + * Like a File stream, an \IO stream has: * * - A read/write mode, which may be read-only, write-only, or read/write; * see {Read/Write Mode}[rdoc-ref:File@Read-2FWrite+Mode]. @@ -14710,7 +14710,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y) * that determine how a new stream is to be opened: * * - +:mode+: Stream mode. - * - +:flags+: \Integer file open flags; + * - +:flags+: Integer file open flags; * If +mode+ is also given, the two are bitwise-ORed. * - +:external_encoding+: External encoding for the stream. * - +:internal_encoding+: Internal encoding for the stream. From b56e5c6b9425a19c04d4e59410463155ea9db30c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 13 Aug 2023 01:00:16 +0900 Subject: [PATCH 014/158] Fix the precedence of `--backtrace-limit` option In general, if the same option specifying a single value is given multiple times at the same level, the last one overrides the earlier ones, unless prohibited. --- ruby.c | 6 +++++- test/ruby/test_rubyoptions.rb | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ruby.c b/ruby.c index e96d5df99e3668..5a339fac0d16a4 100644 --- a/ruby.c +++ b/ruby.c @@ -897,6 +897,7 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) VALUE int_enc_name = opt->intern.enc.name; ruby_features_t feat = opt->features; ruby_features_t warn = opt->warn; + long backtrace_length_limit = opt->backtrace_length_limit; while (ISSPACE(*s)) s++; if (!*s) return; @@ -947,6 +948,9 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) } FEATURE_SET_RESTORE(opt->features, feat); FEATURE_SET_RESTORE(opt->warn, warn); + if (BACKTRACE_LENGTH_LIMIT_VALID_P(backtrace_length_limit)) { + opt->backtrace_length_limit = backtrace_length_limit; + } ruby_xfree(ptr); /* get rid of GC */ @@ -1453,7 +1457,7 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char ** if (errno == ERANGE || !BACKTRACE_LENGTH_LIMIT_VALID_P(n) || *e) { rb_raise(rb_eRuntimeError, "wrong limit for backtrace length"); } - else if (!OPT_BACKTRACE_LENGTH_LIMIT_VALID_P(opt)) { + else { opt->backtrace_length_limit = n; } } diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 7510505062b572..3d98cd6f4e2526 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -89,6 +89,10 @@ def test_backtrace_limit assert_in_out_err([env], "p Thread::Backtrace.limit", ['5'], []) assert_in_out_err([env, "--backtrace-limit=1"], "p Thread::Backtrace.limit", ['1'], []) assert_in_out_err([env, "--backtrace-limit=-1"], "p Thread::Backtrace.limit", ['-1'], []) + assert_in_out_err([env, "--backtrace-limit=3", "--backtrace-limit=1"], + "p Thread::Backtrace.limit", ['1'], []) + assert_in_out_err([{"RUBYOPT" => "--backtrace-limit=5 --backtrace-limit=3"}], + "p Thread::Backtrace.limit", ['3'], []) long_max = RbConfig::LIMITS["LONG_MAX"] assert_in_out_err(%W(--backtrace-limit=#{long_max}), "p Thread::Backtrace.limit", ["#{long_max}"], []) From efc9127790e2e725541de2c36780a852e6c1382c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 13 Aug 2023 15:23:54 +0900 Subject: [PATCH 015/158] Prefix `excludes` with a dot to prevent chkbuild from firing wrongly Chkbuild runs for each directories just under `test` directory when `test-all` failed. `test/excludes` itself should not be a target. --- .appveyor.yml | 4 ++-- common.mk | 2 +- test/{excludes => .excludes}/TestArray.rb | 0 test/{excludes => .excludes}/TestArraySubclass.rb | 0 test/{excludes => .excludes}/TestException.rb | 0 test/{excludes => .excludes}/TestGem.rb | 0 test/{excludes => .excludes}/TestIO_Console.rb | 0 test/{excludes => .excludes}/TestISeq.rb | 0 test/{excludes => .excludes}/TestThread.rb | 0 test/{excludes => .excludes}/TestThreadQueue.rb | 0 test/{excludes => .excludes}/_appveyor/TestArray.rb | 0 11 files changed, 3 insertions(+), 3 deletions(-) rename test/{excludes => .excludes}/TestArray.rb (100%) rename test/{excludes => .excludes}/TestArraySubclass.rb (100%) rename test/{excludes => .excludes}/TestException.rb (100%) rename test/{excludes => .excludes}/TestGem.rb (100%) rename test/{excludes => .excludes}/TestIO_Console.rb (100%) rename test/{excludes => .excludes}/TestISeq.rb (100%) rename test/{excludes => .excludes}/TestThread.rb (100%) rename test/{excludes => .excludes}/TestThreadQueue.rb (100%) rename test/{excludes => .excludes}/_appveyor/TestArray.rb (100%) diff --git a/.appveyor.yml b/.appveyor.yml index fdab2008e8b767..ab8ac580ec301e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -93,7 +93,7 @@ for: - nmake -l "TESTOPTS=-v -q" test-basic - >- nmake -l "TESTOPTS=-v --timeout-scale=3.0 - --excludes=../test/excludes/_appveyor -j%JOBS% + --excludes=../test/.excludes/_appveyor -j%JOBS% --exclude win32ole --exclude test_bignum --exclude test_syntax @@ -103,7 +103,7 @@ for: # separately execute tests without -j which may crash worker with -j. - >- nmake -l - "TESTOPTS=--timeout-scale=3.0 --excludes=../test/excludes/_appveyor" + "TESTOPTS=--timeout-scale=3.0 --excludes=../test/.excludes/_appveyor" TESTS=" ../test/win32ole ../test/ruby/test_bignum.rb diff --git a/common.mk b/common.mk index b1746879034bb2..d031ab28867a6a 100644 --- a/common.mk +++ b/common.mk @@ -259,7 +259,7 @@ INSTALL_DATA_MODE = 0644 BOOTSTRAPRUBY_COMMAND = $(BOOTSTRAPRUBY) $(BOOTSTRAPRUBY_OPT) TESTSDIR = $(srcdir)/test TOOL_TESTSDIR = $(tooldir)/test -TEST_EXCLUDES = --excludes-dir=$(TESTSDIR)/excludes --name=!/memory_leak/ +TEST_EXCLUDES = --excludes-dir=$(TESTSDIR)/.excludes --name=!/memory_leak/ TESTWORKDIR = testwork TESTOPTS = $(RUBY_TESTOPTS) diff --git a/test/excludes/TestArray.rb b/test/.excludes/TestArray.rb similarity index 100% rename from test/excludes/TestArray.rb rename to test/.excludes/TestArray.rb diff --git a/test/excludes/TestArraySubclass.rb b/test/.excludes/TestArraySubclass.rb similarity index 100% rename from test/excludes/TestArraySubclass.rb rename to test/.excludes/TestArraySubclass.rb diff --git a/test/excludes/TestException.rb b/test/.excludes/TestException.rb similarity index 100% rename from test/excludes/TestException.rb rename to test/.excludes/TestException.rb diff --git a/test/excludes/TestGem.rb b/test/.excludes/TestGem.rb similarity index 100% rename from test/excludes/TestGem.rb rename to test/.excludes/TestGem.rb diff --git a/test/excludes/TestIO_Console.rb b/test/.excludes/TestIO_Console.rb similarity index 100% rename from test/excludes/TestIO_Console.rb rename to test/.excludes/TestIO_Console.rb diff --git a/test/excludes/TestISeq.rb b/test/.excludes/TestISeq.rb similarity index 100% rename from test/excludes/TestISeq.rb rename to test/.excludes/TestISeq.rb diff --git a/test/excludes/TestThread.rb b/test/.excludes/TestThread.rb similarity index 100% rename from test/excludes/TestThread.rb rename to test/.excludes/TestThread.rb diff --git a/test/excludes/TestThreadQueue.rb b/test/.excludes/TestThreadQueue.rb similarity index 100% rename from test/excludes/TestThreadQueue.rb rename to test/.excludes/TestThreadQueue.rb diff --git a/test/excludes/_appveyor/TestArray.rb b/test/.excludes/_appveyor/TestArray.rb similarity index 100% rename from test/excludes/_appveyor/TestArray.rb rename to test/.excludes/_appveyor/TestArray.rb From 83718b6bb299c483e60a638ccce98bc8ae1665a1 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 13 Aug 2023 15:24:58 +0900 Subject: [PATCH 016/158] Move test files of ruby/set under `test/set` Chkbuild fires accidentally on `test/fixtures` directory. --- test/{ => set}/fixtures/fake_sorted_set_gem/sorted_set.rb | 0 test/{ => set}/test_set.rb | 0 test/{ => set}/test_sorted_set.rb | 0 tool/sync_default_gems.rb | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename test/{ => set}/fixtures/fake_sorted_set_gem/sorted_set.rb (100%) rename test/{ => set}/test_set.rb (100%) rename test/{ => set}/test_sorted_set.rb (100%) diff --git a/test/fixtures/fake_sorted_set_gem/sorted_set.rb b/test/set/fixtures/fake_sorted_set_gem/sorted_set.rb similarity index 100% rename from test/fixtures/fake_sorted_set_gem/sorted_set.rb rename to test/set/fixtures/fake_sorted_set_gem/sorted_set.rb diff --git a/test/test_set.rb b/test/set/test_set.rb similarity index 100% rename from test/test_set.rb rename to test/set/test_set.rb diff --git a/test/test_sorted_set.rb b/test/set/test_sorted_set.rb similarity index 100% rename from test/test_sorted_set.rb rename to test/set/test_sorted_set.rb diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 2b73af87a2fbc8..a7785a989c48b8 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -371,7 +371,7 @@ def sync_default_gems(gem) `git checkout ext/digest/depend ext/digest/*/depend` when "set" sync_lib gem, upstream - cp_r("#{upstream}/test", ".") + cp_r(Dir.glob("#{upstream}/test/*"), "test/set") when "optparse" sync_lib gem, upstream rm_rf(%w[doc/optparse]) From eb221a37349806bc202dbea2c088754c674605fc Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 13 Aug 2023 15:30:58 +0900 Subject: [PATCH 017/158] Prohibit copying to `fixtures` and dot-direcotry just under `test` Do not add directories which would let chkbuild fires accidentally, to just under `test`. The "fixtures" directory is often used to place test stuffs. --- tool/sync_default_gems.rb | 2 +- tool/test/test_sync_default_gems.rb | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index a7785a989c48b8..d2c17f35af3814 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -600,7 +600,7 @@ def sync_default_gems_with_commits(gem, ranges, edit: nil) puts "Remove files added to toplevel: #{toplevels.join(', ')}" system(*%w"git rm -r --", *toplevels) end - tools = changed.select {|f|f.start_with?("test/lib/", "tool/")} + tools = changed.select {|f|f.start_with?("test/fixtures/", "test/lib/", "tool/")} unless tools.empty? system(*%W"git rm -r --", *tools) system(*%W"git checkout HEAD~ --", *tools) diff --git a/tool/test/test_sync_default_gems.rb b/tool/test/test_sync_default_gems.rb index aa72dcfb205f88..e6c654ed55d914 100755 --- a/tool/test/test_sync_default_gems.rb +++ b/tool/test/test_sync_default_gems.rb @@ -96,7 +96,9 @@ def setup if dir == "src" Dir.mkdir("#{dir}/lib") File.write("#{dir}/lib/fine.rb", "return\n") - system(*%W"git add lib/fine.rb", exception: true, chdir: dir) + Dir.mkdir("#{dir}/test") + File.write("#{dir}/test/test_fine.rb", "return\n") + system(*%W"git add lib/fine.rb test/test_fine.rb", exception: true, chdir: dir) system(*%W"git commit -q -m", "Looks fine", exception: true, chdir: dir) end Dir.mkdir("#{dir}/tool") @@ -154,6 +156,20 @@ def test_skip_tool assert_equal(@sha["src"], IO.popen(%W[git log --format=%H -1], chdir: "src", &:read).chomp, out) end + def test_skip_test_fixtures + Dir.mkdir("#@target/test") + Dir.mkdir("#@target/test/fixtures") + File.write("#@target/test/fixtures/fixme.rb", "") + system(*%W"git add test/fixtures/fixme.rb", exception: true, chdir: @target) + system(*%W"git commit -q -m", "Add fitures", exception: true, chdir: @target) + out = capture_process_output_to([STDOUT, STDERR]) do + Dir.chdir("src") do + SyncDefaultGems.sync_default_gems_with_commits(@target, ["#{@sha[@target]}..#{@target}/default"]) + end + end + assert_equal(@sha["src"], IO.popen(%W[git log --format=%H -1], chdir: "src", &:read).chomp, out) + end + def test_skip_toplevel Dir.mkdir("#@target/docs") File.write("#@target/docs/NEWS.md", "= NEWS!!!\n") From 3af5badae85851ba50e497c297b478cf88a6061a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 14 Aug 2023 00:02:25 +0900 Subject: [PATCH 018/158] [ruby/irb] Remove useless `begin`/`end` [ci skip] (https://github.com/ruby/irb/pull/680) The `rescue` was removed at https://github.com/ruby/irb/commit/420e7d227011. https://github.com/ruby/irb/commit/8fa688e9c0 --- lib/irb/input-method.rb | 98 ++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index b574a3fe1fd557..bd7d4fede4334d 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -159,66 +159,64 @@ def close end end - begin - class ReadlineInputMethod < StdioInputMethod - def self.initialize_readline - require "readline" - rescue LoadError - else - include ::Readline - end + class ReadlineInputMethod < StdioInputMethod + def self.initialize_readline + require "readline" + rescue LoadError + else + include ::Readline + end - include HistorySavingAbility + include HistorySavingAbility - # Creates a new input method object using Readline - def initialize - self.class.initialize_readline - if Readline.respond_to?(:encoding_system_needs) - IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false) - end + # Creates a new input method object using Readline + def initialize + self.class.initialize_readline + if Readline.respond_to?(:encoding_system_needs) + IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false) + end - super + super - @eof = false + @eof = false - if Readline.respond_to?("basic_word_break_characters=") - Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS - end - Readline.completion_append_character = nil - Readline.completion_proc = IRB::InputCompletor::CompletionProc + if Readline.respond_to?("basic_word_break_characters=") + Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS end + Readline.completion_append_character = nil + Readline.completion_proc = IRB::InputCompletor::CompletionProc + end - # Reads the next line from this input method. - # - # See IO#gets for more information. - def gets - Readline.input = @stdin - Readline.output = @stdout - if l = readline(@prompt, false) - HISTORY.push(l) if !l.empty? - @line[@line_no += 1] = l + "\n" - else - @eof = true - l - end + # Reads the next line from this input method. + # + # See IO#gets for more information. + def gets + Readline.input = @stdin + Readline.output = @stdout + if l = readline(@prompt, false) + HISTORY.push(l) if !l.empty? + @line[@line_no += 1] = l + "\n" + else + @eof = true + l end + end - # Whether the end of this input method has been reached, returns +true+ - # if there is no more data to read. - # - # See IO#eof? for more information. - def eof? - @eof - end + # Whether the end of this input method has been reached, returns +true+ + # if there is no more data to read. + # + # See IO#eof? for more information. + def eof? + @eof + end - # For debug message - def inspect - readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline' - str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}" - inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc') - str += " and #{inputrc_path}" if File.exist?(inputrc_path) - str - end + # For debug message + def inspect + readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline' + str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}" + inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc') + str += " and #{inputrc_path}" if File.exist?(inputrc_path) + str end end From 9099d62ac77cdca548bc4110e2cb03057ef0ac8f Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sun, 13 Aug 2023 16:23:00 +0100 Subject: [PATCH 019/158] [ruby/irb] Move IO configuration to IRB::Irb (https://github.com/ruby/irb/pull/681) It shouldn't be `RubyLex`'s responsibility to handle IO. So this moves the configuration to `IRB::Irb`. https://github.com/ruby/irb/commit/daff750076 --- lib/irb.rb | 54 ++- lib/irb/ruby-lex.rb | 57 +-- test/irb/test_irb.rb | 681 ++++++++++++++++++++++++++++++++++++ test/irb/test_ruby_lex.rb | 705 ++------------------------------------ 4 files changed, 766 insertions(+), 731 deletions(-) create mode 100644 test/irb/test_irb.rb diff --git a/lib/irb.rb b/lib/irb.rb index e0025ab3e8778c..c3631715da1d81 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -537,7 +537,7 @@ def eval_input end end - @scanner.configure_io(@context.io) + configure_io @scanner.each_top_level_statement do |line, line_no, is_assignment| signal_status(:IN_EVAL) do @@ -564,6 +564,58 @@ def eval_input end end + def configure_io + if @context.io.respond_to?(:check_termination) + @context.io.check_termination do |code| + if Reline::IOGate.in_pasting? + rest = @scanner.check_termination_in_prev_line(code) + if rest + Reline.delete_text + rest.bytes.reverse_each do |c| + Reline.ungetc(c) + end + true + else + false + end + else + # Accept any single-line input for symbol aliases or commands that transform args + next true if @scanner.single_line_command?(code) + + _tokens, _opens, terminated = @scanner.check_code_state(code) + terminated + end + end + end + if @context.io.respond_to?(:dynamic_prompt) + @context.io.dynamic_prompt do |lines| + lines << '' if lines.empty? + tokens = RubyLex.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context) + line_results = IRB::NestingParser.parse_by_line(tokens) + tokens_until_line = [] + line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset| + line_tokens.each do |token, _s| + # Avoid appending duplicated token. Tokens that include "\n" like multiline tstring_content can exist in multiple lines. + tokens_until_line << token if token != tokens_until_line.last + end + continue = @scanner.should_continue?(tokens_until_line) + @scanner.prompt(next_opens, continue, line_num_offset) + end + end + end + + if @context.io.respond_to?(:auto_indent) and @context.auto_indent_mode + @context.io.auto_indent do |lines, line_index, byte_pointer, is_newline| + next nil if lines == [nil] # Workaround for exit IRB with CTRL+d + next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/) + + code = lines[0..line_index].map { |l| "#{l}\n" }.join + tokens = RubyLex.ripper_lex_without_warning(code, context: @context) + @scanner.process_indent_level(tokens, lines, line_index, is_newline) + end + end + end + def evaluate_line(line, line_no) # Transform a non-identifier alias (@, $) or keywords (next, break) command, args = line.split(/\s/, 2) diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index 92e993ecef5406..7d4f8a514c78d5 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -74,59 +74,6 @@ def set_input(&block) @input = block end - def configure_io(io) - @io = io - if @io.respond_to?(:check_termination) - @io.check_termination do |code| - if Reline::IOGate.in_pasting? - rest = check_termination_in_prev_line(code) - if rest - Reline.delete_text - rest.bytes.reverse_each do |c| - Reline.ungetc(c) - end - true - else - false - end - else - # Accept any single-line input for symbol aliases or commands that transform args - next true if single_line_command?(code) - - _tokens, _opens, terminated = check_code_state(code) - terminated - end - end - end - if @io.respond_to?(:dynamic_prompt) - @io.dynamic_prompt do |lines| - lines << '' if lines.empty? - tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context) - line_results = IRB::NestingParser.parse_by_line(tokens) - tokens_until_line = [] - line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset| - line_tokens.each do |token, _s| - # Avoid appending duplicated token. Tokens that include "\n" like multiline tstring_content can exist in multiple lines. - tokens_until_line << token if token != tokens_until_line.last - end - continue = should_continue?(tokens_until_line) - prompt(next_opens, continue, line_num_offset) - end - end - end - - if @io.respond_to?(:auto_indent) and @context.auto_indent_mode - @io.auto_indent do |lines, line_index, byte_pointer, is_newline| - next nil if lines == [nil] # Workaround for exit IRB with CTRL+d - next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/) - - code = lines[0..line_index].map { |l| "#{l}\n" }.join - tokens = self.class.ripper_lex_without_warning(code, context: @context) - process_indent_level(tokens, lines, line_index, is_newline) - end - end - end - def set_prompt(&block) @prompt = block end @@ -240,7 +187,7 @@ def readmultiline save_prompt_to_context_io([], false, 0) # multiline - return @input.call if @io.respond_to?(:check_termination) + return @input.call if @context.io.respond_to?(:check_termination) # nomultiline code = '' @@ -270,7 +217,7 @@ def each_top_level_statement break unless code if code != "\n" - code.force_encoding(@io.encoding) + code.force_encoding(@context.io.encoding) yield code, @line_no, assignment_expression?(code) end @line_no += code.count("\n") diff --git a/test/irb/test_irb.rb b/test/irb/test_irb.rb new file mode 100644 index 00000000000000..b613cc8a9ad5a3 --- /dev/null +++ b/test/irb/test_irb.rb @@ -0,0 +1,681 @@ +# frozen_string_literal: true +require "irb" + +require_relative "helper" + +module TestIRB + class IrbIOConfigurationTest < TestCase + Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :indent_level) + + class MockIO_AutoIndent + attr_reader :calculated_indent + + def initialize(*params) + @params = params + @calculated_indent + end + + def auto_indent(&block) + @calculated_indent = block.call(*@params) + end + end + + class MockIO_DynamicPrompt + def initialize(params, &assertion) + @params = params + @assertion = assertion + end + + def dynamic_prompt(&block) + result = block.call(@params) + @assertion.call(result) + end + end + + def setup + @irb = build_irb + save_encodings + end + + def teardown + restore_encodings + end + + class AutoIndentationTest < IrbIOConfigurationTest + def test_auto_indent + input_with_correct_indents = [ + [%q(def each_top_level_statement), 0, 2], + [%q( initialize_input), 2, 2], + [%q( catch(:TERM_INPUT) do), 2, 4], + [%q( loop do), 4, 6], + [%q( begin), 6, 8], + [%q( prompt), 8, 8], + [%q( unless l = lex), 8, 10], + [%q( throw :TERM_INPUT if @line == ''), 10, 10], + [%q( else), 8, 10], + [%q( @line_no += l.count("\n")), 10, 10], + [%q( next if l == "\n"), 10, 10], + [%q( @line.concat l), 10, 10], + [%q( if @code_block_open or @ltype or @continue or @indent > 0), 10, 12], + [%q( next), 12, 12], + [%q( end), 10, 10], + [%q( end), 8, 8], + [%q( if @line != "\n"), 8, 10], + [%q( @line.force_encoding(@io.encoding)), 10, 10], + [%q( yield @line, @exp_line_no), 10, 10], + [%q( end), 8, 8], + [%q( break if @io.eof?), 8, 8], + [%q( @line = ''), 8, 8], + [%q( @exp_line_no = @line_no), 8, 8], + [%q( ), nil, 8], + [%q( @indent = 0), 8, 8], + [%q( rescue TerminateLineInput), 6, 8], + [%q( initialize_input), 8, 8], + [%q( prompt), 8, 8], + [%q( end), 6, 6], + [%q( end), 4, 4], + [%q( end), 2, 2], + [%q(end), 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents) + end + + def test_braces_on_their_own_line + input_with_correct_indents = [ + [%q(if true), 0, 2], + [%q( [), 2, 4], + [%q( ]), 2, 2], + [%q(end), 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents) + end + + def test_multiple_braces_in_a_line + input_with_correct_indents = [ + [%q([[[), 0, 6], + [%q( ]), 4, 4], + [%q( ]), 2, 2], + [%q(]), 0, 0], + [%q([< e), 4, 6], + [%q( raise e rescue 8), 6, 6], + [%q( end), 4, 4], + [%q( rescue), 2, 4], + [%q( raise rescue 11), 4, 4], + [%q( end), 2, 2], + [%q(rescue => e), 0, 2], + [%q( raise e rescue 14), 2, 2], + [%q(end), 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents) + end + + def test_oneliner_method_definition + input_with_correct_indents = [ + [%q(class A), 0, 2], + [%q( def foo0), 2, 4], + [%q( 3), 4, 4], + [%q( end), 2, 2], + [%q( def foo1()), 2, 4], + [%q( 3), 4, 4], + [%q( end), 2, 2], + [%q( def foo2(a, b)), 2, 4], + [%q( a + b), 4, 4], + [%q( end), 2, 2], + [%q( def foo3 a, b), 2, 4], + [%q( a + b), 4, 4], + [%q( end), 2, 2], + [%q( def bar0() = 3), 2, 2], + [%q( def bar1(a) = a), 2, 2], + [%q( def bar2(a, b) = a + b), 2, 2], + [%q( def bar3() = :s), 2, 2], + [%q( def bar4() = Time.now), 2, 2], + [%q(end), 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents) + end + + def test_tlambda + input_with_correct_indents = [ + [%q(if true), 0, 2, 1], + [%q( -> {), 2, 4, 2], + [%q( }), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_corresponding_syntax_to_keyword_do_in_class + input_with_correct_indents = [ + [%q(class C), 0, 2, 1], + [%q( while method_name do), 2, 4, 2], + [%q( 3), 4, 4, 2], + [%q( end), 2, 2, 1], + [%q( foo do), 2, 4, 2], + [%q( 3), 4, 4, 2], + [%q( end), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_corresponding_syntax_to_keyword_do + input_with_correct_indents = [ + [%q(while i > 0), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(while true), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(while ->{i > 0}.call), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(while ->{true}.call), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(while i > 0 do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(while true do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(while ->{i > 0}.call do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(while ->{true}.call do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(foo do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(foo true do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(foo ->{true} do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + [%q(foo ->{i > 0} do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_corresponding_syntax_to_keyword_for + input_with_correct_indents = [ + [%q(for i in [1]), 0, 2, 1], + [%q( puts i), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_corresponding_syntax_to_keyword_for_with_do + input_with_correct_indents = [ + [%q(for i in [1] do), 0, 2, 1], + [%q( puts i), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_typing_incomplete_include_interpreted_as_keyword_in + input_with_correct_indents = [ + [%q(module E), 0, 2, 1], + [%q(end), 0, 0, 0], + [%q(class A), 0, 2, 1], + [%q( in), 2, 2, 1] # scenario typing `include E` + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + + end + + def test_bracket_corresponding_to_times + input_with_correct_indents = [ + [%q(3.times { |i|), 0, 2, 1], + [%q( puts i), 2, 2, 1], + [%q(}), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_do_corresponding_to_times + input_with_correct_indents = [ + [%q(3.times do |i|), 0, 2, 1], + [%q( puts i), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_bracket_corresponding_to_loop + input_with_correct_indents = [ + ['loop {', 0, 2, 1], + [' 3', 2, 2, 1], + ['}', 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_do_corresponding_to_loop + input_with_correct_indents = [ + [%q(loop do), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_embdoc_indent + input_with_correct_indents = [ + [%q(=begin), 0, 0, 0], + [%q(a), 0, 0, 0], + [%q( b), 1, 1, 0], + [%q(=end), 0, 0, 0], + [%q(if 1), 0, 2, 1], + [%q( 2), 2, 2, 1], + [%q(=begin), 0, 0, 0], + [%q(a), 0, 0, 0], + [%q( b), 1, 1, 0], + [%q(=end), 0, 2, 1], + [%q( 3), 2, 2, 1], + [%q(end), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_heredoc_with_indent + if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') + pend 'This test needs Ripper::Lexer#scan to take broken tokens' + end + input_with_correct_indents = [ + [%q(<<~Q+<<~R), 0, 2, 1], + [%q(a), 2, 2, 1], + [%q(a), 2, 2, 1], + [%q( b), 2, 2, 1], + [%q( b), 2, 2, 1], + [%q( Q), 0, 2, 1], + [%q( c), 4, 4, 1], + [%q( c), 4, 4, 1], + [%q( R), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_oneliner_def_in_multiple_lines + input_with_correct_indents = [ + [%q(def a()=[), 0, 2, 1], + [%q( 1,), 2, 2, 1], + [%q(].), 0, 0, 0], + [%q(to_s), 0, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_broken_heredoc + input_with_correct_indents = [ + [%q(def foo), 0, 2, 1], + [%q( <<~Q), 2, 4, 2], + [%q( Qend), 4, 4, 2], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_pasted_code_keep_base_indent_spaces + input_with_correct_indents = [ + [%q( def foo), 0, 6, 1], + [%q( if bar), 6, 10, 2], + [%q( [1), 10, 12, 3], + [%q( ]+[["a), 10, 14, 4], + [%q(b" + `c), 0, 14, 4], + [%q(d` + /e), 0, 14, 4], + [%q(f/ + :"g), 0, 14, 4], + [%q(h".tap do), 0, 16, 5], + [%q( 1), 16, 16, 5], + [%q( end), 14, 14, 4], + [%q( ]), 12, 12, 3], + [%q( ]), 10, 10, 2], + [%q( end), 8, 6, 1], + [%q( end), 4, 0, 0], + ] + + assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) + end + + def test_pasted_code_keep_base_indent_spaces_with_heredoc + input_with_correct_indents = [ + [%q( def foo), 0, 6, 1], + [%q( if bar), 6, 10, 2], + [%q( [1), 10, 12, 3], + [%q( ]+[["a), 10, 14, 4], + [%q(b" + <<~A + <<-B + < #{lines.last} + ``` + + All lines: + + ``` + #{lines.join("\n")} + ``` + MSG + assert_equal(row.current_line_spaces, actual_current_line_spaces, error_message) + + error_message = <<~MSG + Incorrect spaces calculation for line after the current line: + + ``` + #{lines.last} + > + ``` + + All lines: + + ``` + #{lines.join("\n")} + ``` + MSG + actual_next_line_spaces = calculate_indenting(lines, true) + assert_equal(row.new_line_spaces, actual_next_line_spaces, error_message) + end + + def assert_rows_with_correct_indents(rows_with_spaces, assert_indent_level: false) + lines = [] + rows_with_spaces.map do |row| + row = Row.new(*row) + lines << row.content + assert_row_indenting(lines, row) + + if assert_indent_level + assert_indent_level(lines, row.indent_level) + end + end + end + + def assert_indent_level(lines, expected) + code = lines.map { |l| "#{l}\n" }.join # code should end with "\n" + _tokens, opens, _ = @irb.scanner.check_code_state(code) + indent_level = @irb.scanner.calc_indent_level(opens) + error_message = "Calculated the wrong number of indent level for:\n #{lines.join("\n")}" + assert_equal(expected, indent_level, error_message) + end + + def calculate_indenting(lines, add_new_line) + lines = lines + [""] if add_new_line + last_line_index = lines.length - 1 + byte_pointer = lines.last.length + + mock_io = MockIO_AutoIndent.new(lines, last_line_index, byte_pointer, add_new_line) + @irb.context.auto_indent_mode = true + @irb.context.io = mock_io + @irb.configure_io + + mock_io.calculated_indent + end + end + + class DynamicPromptTest < IrbIOConfigurationTest + def test_endless_range_at_end_of_line + input_with_prompt = [ + ['001:0: :> ', %q(a = 3..)], + ['002:0: :> ', %q()], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def test_heredoc_with_embexpr + input_with_prompt = [ + ['001:0:":* ', %q(< ', %q(])], + ['012:0: :> ', %q()], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def test_heredoc_prompt_with_quotes + input_with_prompt = [ + ["001:1:':* ", %q(<<~'A')], + ["002:1:':* ", %q(#{foobar})], + ["003:0: :> ", %q(A)], + ["004:1:`:* ", %q(<<~`A`)], + ["005:1:`:* ", %q(whoami)], + ["006:0: :> ", %q(A)], + ['007:1:":* ', %q(<<~"A")], + ['008:1:":* ', %q(foobar)], + ['009:0: :> ', %q(A)], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def test_backtick_method + input_with_prompt = [ + ['001:0: :> ', %q(self.`(arg))], + ['002:0: :> ', %q()], + ['003:0: :> ', %q(def `(); end)], + ['004:0: :> ', %q()], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def test_dynamic_prompt + input_with_prompt = [ + ['001:1: :* ', %q(def hoge)], + ['002:1: :* ', %q( 3)], + ['003:0: :> ', %q(end)], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def test_dynamic_prompt_with_double_newline_breaking_code + input_with_prompt = [ + ['001:1: :* ', %q(if true)], + ['002:2: :* ', %q(%)], + ['003:1: :* ', %q(;end)], + ['004:1: :* ', %q(;hello)], + ['005:0: :> ', %q(end)], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def test_dynamic_prompt_with_multiline_literal + input_with_prompt = [ + ['001:1: :* ', %q(if true)], + ['002:2:]:* ', %q( %w[)], + ['003:2:]:* ', %q( a)], + ['004:1: :* ', %q( ])], + ['005:1: :* ', %q( b)], + ['006:2:]:* ', %q( %w[)], + ['007:2:]:* ', %q( c)], + ['008:1: :* ', %q( ])], + ['009:0: :> ', %q(end)], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def test_dynamic_prompt_with_blank_line + input_with_prompt = [ + ['001:1:]:* ', %q(%w[)], + ['002:1:]:* ', %q()], + ['003:0: :> ', %q(])], + ] + + assert_dynamic_prompt(input_with_prompt) + end + + def assert_dynamic_prompt(input_with_prompt) + expected_prompt_list, lines = input_with_prompt.transpose + dynamic_prompt_executed = false + io = MockIO_DynamicPrompt.new(lines) do |prompt_list| + error_message = <<~EOM + Expected dynamic prompt: + #{expected_prompt_list.join("\n")} + + Actual dynamic prompt: + #{prompt_list.join("\n")} + EOM + dynamic_prompt_executed = true + assert_equal(expected_prompt_list, prompt_list, error_message) + end + @irb.context.io = io + @irb.scanner.set_prompt do |ltype, indent, continue, line_no| + '%03d:%01d:%1s:%s ' % [line_no, indent, ltype, continue ? '*' : '>'] + end + @irb.configure_io + assert dynamic_prompt_executed, "dynamic_prompt's assertions were not executed." + end + end + + private + + def build_irb + IRB.init_config(nil) + workspace = IRB::WorkSpace.new(TOPLEVEL_BINDING.dup) + + IRB.conf[:VERBOSE] = false + IRB::Irb.new(workspace) + end + end +end diff --git a/test/irb/test_ruby_lex.rb b/test/irb/test_ruby_lex.rb index e7122668ea81a7..338ff387512c73 100644 --- a/test/irb/test_ruby_lex.rb +++ b/test/irb/test_ruby_lex.rb @@ -1,27 +1,10 @@ -$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) -require 'irb' -require 'rubygems' -require 'ostruct' +# frozen_string_literal: true +require "irb" require_relative "helper" module TestIRB class RubyLexTest < TestCase - Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :indent_level) - - class MockIO_AutoIndent - attr_reader :calculated_indent - - def initialize(*params) - @params = params - @calculated_indent - end - - def auto_indent(&block) - @calculated_indent = block.call(*@params) - end - end - def setup save_encodings end @@ -30,98 +13,6 @@ def teardown restore_encodings end - def calculate_indenting(lines, add_new_line) - lines = lines + [""] if add_new_line - last_line_index = lines.length - 1 - byte_pointer = lines.last.length - - context = build_context - context.auto_indent_mode = true - - ruby_lex = RubyLex.new(context) - mock_io = MockIO_AutoIndent.new(lines, last_line_index, byte_pointer, add_new_line) - - ruby_lex.configure_io(mock_io) - mock_io.calculated_indent - end - - def assert_row_indenting(lines, row) - actual_current_line_spaces = calculate_indenting(lines, false) - - error_message = <<~MSG - Incorrect spaces calculation for line: - - ``` - > #{lines.last} - ``` - - All lines: - - ``` - #{lines.join("\n")} - ``` - MSG - assert_equal(row.current_line_spaces, actual_current_line_spaces, error_message) - - error_message = <<~MSG - Incorrect spaces calculation for line after the current line: - - ``` - #{lines.last} - > - ``` - - All lines: - - ``` - #{lines.join("\n")} - ``` - MSG - actual_next_line_spaces = calculate_indenting(lines, true) - assert_equal(row.new_line_spaces, actual_next_line_spaces, error_message) - end - - def assert_rows_with_correct_indents(rows_with_spaces, assert_indent_level: false) - lines = [] - rows_with_spaces.map do |row| - row = Row.new(*row) - lines << row.content - assert_row_indenting(lines, row) - - if assert_indent_level - assert_indent_level(lines, row.indent_level) - end - end - end - - def assert_indent_level(lines, expected, local_variables: []) - indent_level, _continue, _code_block_open = check_state(lines, local_variables: local_variables) - error_message = "Calculated the wrong number of indent level for:\n #{lines.join("\n")}" - assert_equal(expected, indent_level, error_message) - end - - def assert_should_continue(lines, expected, local_variables: []) - _indent_level, continue, _code_block_open = check_state(lines, local_variables: local_variables) - error_message = "Wrong result of should_continue for:\n #{lines.join("\n")}" - assert_equal(expected, continue, error_message) - end - - def assert_code_block_open(lines, expected, local_variables: []) - _indent_level, _continue, code_block_open = check_state(lines, local_variables: local_variables) - error_message = "Wrong result of code_block_open for:\n #{lines.join("\n")}" - assert_equal(expected, code_block_open, error_message) - end - - def check_state(lines, local_variables: []) - context = build_context(local_variables) - code = lines.map { |l| "#{l}\n" }.join # code should end with "\n" - ruby_lex = RubyLex.new(context) - tokens, opens, terminated = ruby_lex.check_code_state(code) - indent_level = ruby_lex.calc_indent_level(opens) - continue = ruby_lex.should_continue?(tokens) - [indent_level, continue, !terminated] - end - def test_interpolate_token_with_heredoc_and_unclosed_embexpr code = <<~'EOC' ①+< 0), 10, 12], - [%q( next), 12, 12], - [%q( end), 10, 10], - [%q( end), 8, 8], - [%q( if @line != "\n"), 8, 10], - [%q( @line.force_encoding(@io.encoding)), 10, 10], - [%q( yield @line, @exp_line_no), 10, 10], - [%q( end), 8, 8], - [%q( break if @io.eof?), 8, 8], - [%q( @line = ''), 8, 8], - [%q( @exp_line_no = @line_no), 8, 8], - [%q( ), nil, 8], - [%q( @indent = 0), 8, 8], - [%q( rescue TerminateLineInput), 6, 8], - [%q( initialize_input), 8, 8], - [%q( prompt), 8, 8], - [%q( end), 6, 6], - [%q( end), 4, 4], - [%q( end), 2, 2], - [%q(end), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_braces_on_their_own_line - input_with_correct_indents = [ - [%q(if true), 0, 2], - [%q( [), 2, 4], - [%q( ]), 2, 2], - [%q(end), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_multiple_braces_in_a_line - input_with_correct_indents = [ - [%q([[[), 0, 6], - [%q( ]), 4, 4], - [%q( ]), 2, 2], - [%q(]), 0, 0], - [%q([< ', %q(a = 3..)], - ['002:0: :> ', %q()], - ] - - assert_dynamic_prompt(input_with_prompt) - end - - def test_heredoc_with_embexpr - input_with_prompt = [ - ['001:0:":* ', %q(< ', %q(])], - ['012:0: :> ', %q()], - ] - - assert_dynamic_prompt(input_with_prompt) - end - - def test_heredoc_prompt_with_quotes - input_with_prompt = [ - ["001:1:':* ", %q(<<~'A')], - ["002:1:':* ", %q(#{foobar})], - ["003:0: :> ", %q(A)], - ["004:1:`:* ", %q(<<~`A`)], - ["005:1:`:* ", %q(whoami)], - ["006:0: :> ", %q(A)], - ['007:1:":* ', %q(<<~"A")], - ['008:1:":* ', %q(foobar)], - ['009:0: :> ', %q(A)], - ] - - assert_dynamic_prompt(input_with_prompt) - end - - def test_backtick_method - input_with_prompt = [ - ['001:0: :> ', %q(self.`(arg))], - ['002:0: :> ', %q()], - ['003:0: :> ', %q(def `(); end)], - ['004:0: :> ', %q()], - ] - - assert_dynamic_prompt(input_with_prompt) - end - - def test_incomplete_coding_magic_comment - input_with_correct_indents = [ - [%q(#coding:u), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_incomplete_encoding_magic_comment - input_with_correct_indents = [ - [%q(#encoding:u), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_incomplete_emacs_coding_magic_comment - input_with_correct_indents = [ - [%q(# -*- coding: u), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_incomplete_vim_coding_magic_comment - input_with_correct_indents = [ - [%q(# vim:set fileencoding=u), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_mixed_rescue - input_with_correct_indents = [ - [%q(def m), 0, 2], - [%q( begin), 2, 4], - [%q( begin), 4, 6], - [%q( x = a rescue 4), 6, 6], - [%q( y = [(a rescue 5)]), 6, 6], - [%q( [x, y]), 6, 6], - [%q( rescue => e), 4, 6], - [%q( raise e rescue 8), 6, 6], - [%q( end), 4, 4], - [%q( rescue), 2, 4], - [%q( raise rescue 11), 4, 4], - [%q( end), 2, 2], - [%q(rescue => e), 0, 2], - [%q( raise e rescue 14), 2, 2], - [%q(end), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_oneliner_method_definition - input_with_correct_indents = [ - [%q(class A), 0, 2], - [%q( def foo0), 2, 4], - [%q( 3), 4, 4], - [%q( end), 2, 2], - [%q( def foo1()), 2, 4], - [%q( 3), 4, 4], - [%q( end), 2, 2], - [%q( def foo2(a, b)), 2, 4], - [%q( a + b), 4, 4], - [%q( end), 2, 2], - [%q( def foo3 a, b), 2, 4], - [%q( a + b), 4, 4], - [%q( end), 2, 2], - [%q( def bar0() = 3), 2, 2], - [%q( def bar1(a) = a), 2, 2], - [%q( def bar2(a, b) = a + b), 2, 2], - [%q( def bar3() = :s), 2, 2], - [%q( def bar4() = Time.now), 2, 2], - [%q(end), 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents) - end - - def test_tlambda - input_with_correct_indents = [ - [%q(if true), 0, 2, 1], - [%q( -> {), 2, 4, 2], - [%q( }), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_corresponding_syntax_to_keyword_do_in_class - input_with_correct_indents = [ - [%q(class C), 0, 2, 1], - [%q( while method_name do), 2, 4, 2], - [%q( 3), 4, 4, 2], - [%q( end), 2, 2, 1], - [%q( foo do), 2, 4, 2], - [%q( 3), 4, 4, 2], - [%q( end), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_corresponding_syntax_to_keyword_do - input_with_correct_indents = [ - [%q(while i > 0), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(while true), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(while ->{i > 0}.call), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(while ->{true}.call), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(while i > 0 do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(while true do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(while ->{i > 0}.call do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(while ->{true}.call do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(foo do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(foo true do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(foo ->{true} do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - [%q(foo ->{i > 0} do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_corresponding_syntax_to_keyword_for - input_with_correct_indents = [ - [%q(for i in [1]), 0, 2, 1], - [%q( puts i), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_corresponding_syntax_to_keyword_for_with_do - input_with_correct_indents = [ - [%q(for i in [1] do), 0, 2, 1], - [%q( puts i), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_typing_incomplete_include_interpreted_as_keyword_in - input_with_correct_indents = [ - [%q(module E), 0, 2, 1], - [%q(end), 0, 0, 0], - [%q(class A), 0, 2, 1], - [%q( in), 2, 2, 1] # scenario typing `include E` - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - - end - - def test_bracket_corresponding_to_times - input_with_correct_indents = [ - [%q(3.times { |i|), 0, 2, 1], - [%q( puts i), 2, 2, 1], - [%q(}), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_do_corresponding_to_times - input_with_correct_indents = [ - [%q(3.times do |i|), 0, 2, 1], - [%q( puts i), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_bracket_corresponding_to_loop - input_with_correct_indents = [ - ['loop {', 0, 2, 1], - [' 3', 2, 2, 1], - ['}', 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_do_corresponding_to_loop - input_with_correct_indents = [ - [%q(loop do), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - def test_local_variables_dependent_code lines = ["a /1#/ do", "2"] assert_indent_level(lines, 1) @@ -515,206 +42,6 @@ def test_local_variables_dependent_code assert_code_block_open(lines, false, local_variables: ['a']) end - def test_embdoc_indent - input_with_correct_indents = [ - [%q(=begin), 0, 0, 0], - [%q(a), 0, 0, 0], - [%q( b), 1, 1, 0], - [%q(=end), 0, 0, 0], - [%q(if 1), 0, 2, 1], - [%q( 2), 2, 2, 1], - [%q(=begin), 0, 0, 0], - [%q(a), 0, 0, 0], - [%q( b), 1, 1, 0], - [%q(=end), 0, 2, 1], - [%q( 3), 2, 2, 1], - [%q(end), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_heredoc_with_indent - if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0') - pend 'This test needs Ripper::Lexer#scan to take broken tokens' - end - input_with_correct_indents = [ - [%q(<<~Q+<<~R), 0, 2, 1], - [%q(a), 2, 2, 1], - [%q(a), 2, 2, 1], - [%q( b), 2, 2, 1], - [%q( b), 2, 2, 1], - [%q( Q), 0, 2, 1], - [%q( c), 4, 4, 1], - [%q( c), 4, 4, 1], - [%q( R), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_oneliner_def_in_multiple_lines - input_with_correct_indents = [ - [%q(def a()=[), 0, 2, 1], - [%q( 1,), 2, 2, 1], - [%q(].), 0, 0, 0], - [%q(to_s), 0, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_broken_heredoc - input_with_correct_indents = [ - [%q(def foo), 0, 2, 1], - [%q( <<~Q), 2, 4, 2], - [%q( Qend), 4, 4, 2], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_heredoc_keep_indent_spaces - (1..4).each do |indent| - row = Row.new(' ' * indent, nil, [4, indent].max, 2) - lines = ['def foo', ' <<~Q', row.content] - assert_row_indenting(lines, row) - assert_indent_level(lines, row.indent_level) - end - end - - class MockIO_DynamicPrompt - def initialize(params, &assertion) - @params = params - @assertion = assertion - end - - def dynamic_prompt(&block) - result = block.call(@params) - @assertion.call(result) - end - end - - def test_pasted_code_keep_base_indent_spaces - input_with_correct_indents = [ - [%q( def foo), 0, 6, 1], - [%q( if bar), 6, 10, 2], - [%q( [1), 10, 12, 3], - [%q( ]+[["a), 10, 14, 4], - [%q(b" + `c), 0, 14, 4], - [%q(d` + /e), 0, 14, 4], - [%q(f/ + :"g), 0, 14, 4], - [%q(h".tap do), 0, 16, 5], - [%q( 1), 16, 16, 5], - [%q( end), 14, 14, 4], - [%q( ]), 12, 12, 3], - [%q( ]), 10, 10, 2], - [%q( end), 8, 6, 1], - [%q( end), 4, 0, 0], - ] - - assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true) - end - - def test_pasted_code_keep_base_indent_spaces_with_heredoc - input_with_correct_indents = [ - [%q( def foo), 0, 6, 1], - [%q( if bar), 6, 10, 2], - [%q( [1), 10, 12, 3], - [%q( ]+[["a), 10, 14, 4], - [%q(b" + <<~A + <<-B + <'] - end - ruby_lex.configure_io(io) - assert dynamic_prompt_executed, "dynamic_prompt's assertions were not executed." - end - - def test_dynamic_prompt - input_with_prompt = [ - ['001:1: :* ', %q(def hoge)], - ['002:1: :* ', %q( 3)], - ['003:0: :> ', %q(end)], - ] - - assert_dynamic_prompt(input_with_prompt) - end - - def test_dynamic_prompt_with_double_newline_breaking_code - input_with_prompt = [ - ['001:1: :* ', %q(if true)], - ['002:2: :* ', %q(%)], - ['003:1: :* ', %q(;end)], - ['004:1: :* ', %q(;hello)], - ['005:0: :> ', %q(end)], - ] - - assert_dynamic_prompt(input_with_prompt) - end - - def test_dynamic_prompt_with_multiline_literal - input_with_prompt = [ - ['001:1: :* ', %q(if true)], - ['002:2:]:* ', %q( %w[)], - ['003:2:]:* ', %q( a)], - ['004:1: :* ', %q( ])], - ['005:1: :* ', %q( b)], - ['006:2:]:* ', %q( %w[)], - ['007:2:]:* ', %q( c)], - ['008:1: :* ', %q( ])], - ['009:0: :> ', %q(end)], - ] - - assert_dynamic_prompt(input_with_prompt) - end - - def test_dynamic_prompt_with_blank_line - input_with_prompt = [ - ['001:1:]:* ', %q(%w[)], - ['002:1:]:* ', %q()], - ['003:0: :> ', %q(])], - ] - - assert_dynamic_prompt(input_with_prompt) - end - def test_literal_ends_with_space assert_code_block_open(['% a'], true) assert_code_block_open(['% a '], false) @@ -890,5 +217,33 @@ def build_context(local_variables = nil) IRB.conf[:VERBOSE] = false IRB::Context.new(nil, workspace) end + + def assert_indent_level(lines, expected, local_variables: []) + indent_level, _continue, _code_block_open = check_state(lines, local_variables: local_variables) + error_message = "Calculated the wrong number of indent level for:\n #{lines.join("\n")}" + assert_equal(expected, indent_level, error_message) + end + + def assert_should_continue(lines, expected, local_variables: []) + _indent_level, continue, _code_block_open = check_state(lines, local_variables: local_variables) + error_message = "Wrong result of should_continue for:\n #{lines.join("\n")}" + assert_equal(expected, continue, error_message) + end + + def assert_code_block_open(lines, expected, local_variables: []) + _indent_level, _continue, code_block_open = check_state(lines, local_variables: local_variables) + error_message = "Wrong result of code_block_open for:\n #{lines.join("\n")}" + assert_equal(expected, code_block_open, error_message) + end + + def check_state(lines, local_variables: []) + context = build_context(local_variables) + code = lines.map { |l| "#{l}\n" }.join # code should end with "\n" + ruby_lex = RubyLex.new(context) + tokens, opens, terminated = ruby_lex.check_code_state(code) + indent_level = ruby_lex.calc_indent_level(opens) + continue = ruby_lex.should_continue?(tokens) + [indent_level, continue, !terminated] + end end end From 7f8f62c93bf3d11a0321fa91823065a2ff36f6d0 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sun, 13 Aug 2023 19:30:30 +0100 Subject: [PATCH 020/158] [ruby/irb] Support seamless integration with ruby/debug (https://github.com/ruby/irb/pull/575) * Support native integration with ruby/debug * Prevent using multi-irb and activating debugger at the same time Multi-irb makes a few assumptions: - IRB will manage all threads that host sub-irb sessions - All IRB sessions will be run on the threads created by IRB itself However, when using the debugger these assumptions are broken: - `debug` will freeze ALL threads when it suspends the session (e.g. when hitting a breakpoint, or performing step-debugging). - Since the irb-debug integration runs IRB as the debugger's interface, it will be run on the debugger's thread, which is not managed by IRB. So we should prevent the 2 features from being used at the same time. To do that, we check if the other feature is already activated when executing the commands that would activate the other feature. https://github.com/ruby/irb/commit/d8fb3246be --- lib/irb.rb | 83 ++++++++++++-- lib/irb/cmd/debug.rb | 128 ++++++---------------- lib/irb/cmd/subirb.rb | 36 +++++- lib/irb/context.rb | 2 + lib/irb/debug.rb | 127 ++++++++++++++++++++++ lib/irb/debug/ui.rb | 104 ++++++++++++++++++ lib/irb/history.rb | 4 + lib/irb/ruby-lex.rb | 6 +- lib/irb/workspace.rb | 4 + test/irb/test_debug_cmd.rb | 217 +++++++++++++++++++++++++++++++++++-- test/irb/test_history.rb | 45 +++++++- 11 files changed, 642 insertions(+), 114 deletions(-) create mode 100644 lib/irb/debug.rb create mode 100644 lib/irb/debug/ui.rb diff --git a/lib/irb.rb b/lib/irb.rb index c3631715da1d81..c884d70a67b7e2 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -18,6 +18,7 @@ require_relative "irb/version" require_relative "irb/easter-egg" +require_relative "irb/debug" # IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby # expressions read from the standard input. @@ -373,8 +374,6 @@ module IRB class Abort < Exception;end @CONF = {} - - # Displays current configuration. # # Modifying the configuration is achieved by sending a message to IRB.conf. @@ -441,7 +440,7 @@ class Irb # Creates a new irb session def initialize(workspace = nil, input_method = nil) @context = Context.new(self, workspace, input_method) - @context.main.extend ExtendCommandBundle + @context.workspace.load_commands_to_main @signal_status = :IN_IRB @scanner = RubyLex.new(@context) end @@ -457,6 +456,38 @@ def debug_break end end + def debug_readline(binding) + workspace = IRB::WorkSpace.new(binding) + context.workspace = workspace + context.workspace.load_commands_to_main + scanner.increase_line_no(1) + + # When users run: + # 1. Debugging commands, like `step 2` + # 2. Any input that's not irb-command, like `foo = 123` + # + # Irb#eval_input will simply return the input, and we need to pass it to the debugger. + input = if IRB.conf[:SAVE_HISTORY] && context.io.support_history_saving? + # Previous IRB session's history has been saved when `Irb#run` is exited + # We need to make sure the saved history is not saved again by reseting the counter + context.io.reset_history_counter + + begin + eval_input + ensure + context.io.save_history + end + else + eval_input + end + + if input&.include?("\n") + scanner.increase_line_no(input.count("\n") - 1) + end + + input + end + def run(conf = IRB.conf) in_nested_session = !!conf[:MAIN_CONTEXT] conf[:IRB_RC].call(context) if conf[:IRB_RC] @@ -542,6 +573,18 @@ def eval_input @scanner.each_top_level_statement do |line, line_no, is_assignment| signal_status(:IN_EVAL) do begin + # If the integration with debugger is activated, we need to handle certain input differently + if @context.with_debugger + command_class = load_command_class(line) + # First, let's pass debugging command's input to debugger + # Secondly, we need to let debugger evaluate non-command input + # Otherwise, the expression will be evaluated in the debugger's main session thread + # This is the only way to run the user's program in the expected thread + if !command_class || ExtendCommand::DebugCommand > command_class + return line + end + end + evaluate_line(line, line_no) # Don't echo if the line ends with a semicolon @@ -633,6 +676,12 @@ def evaluate_line(line, line_no) @context.evaluate(line, line_no) end + def load_command_class(line) + command, _ = line.split(/\s/, 2) + command_name = @context.command_aliases[command.to_sym] + ExtendCommandBundle.load_command(command_name || command) + end + def convert_invalid_byte_sequence(str, enc) str.force_encoding(enc) str.scrub { |c| @@ -986,12 +1035,32 @@ class Binding # # See IRB@Usage for more information. def irb(show_code: true) + # Setup IRB with the current file's path and no command line arguments IRB.setup(source_location[0], argv: []) + # Create a new workspace using the current binding workspace = IRB::WorkSpace.new(self) + # Print the code around the binding if show_code is true STDOUT.print(workspace.code_around_binding) if show_code - binding_irb = IRB::Irb.new(workspace) - binding_irb.context.irb_path = File.expand_path(source_location[0]) - binding_irb.run(IRB.conf) - binding_irb.debug_break + # Get the original IRB instance + debugger_irb = IRB.instance_variable_get(:@debugger_irb) + + irb_path = File.expand_path(source_location[0]) + + if debugger_irb + # If we're already in a debugger session, set the workspace and irb_path for the original IRB instance + debugger_irb.context.workspace = workspace + debugger_irb.context.irb_path = irb_path + # If we've started a debugger session and hit another binding.irb, we don't want to start an IRB session + # instead, we want to resume the irb:rdbg session. + IRB::Debug.setup(debugger_irb) + IRB::Debug.insert_debug_break + debugger_irb.debug_break + else + # If we're not in a debugger session, create a new IRB instance with the current workspace + binding_irb = IRB::Irb.new(workspace) + binding_irb.context.irb_path = irb_path + binding_irb.run(IRB.conf) + binding_irb.debug_break + end end end diff --git a/lib/irb/cmd/debug.rb b/lib/irb/cmd/debug.rb index 7d39b9fa2772f3..9eca964218a116 100644 --- a/lib/irb/cmd/debug.rb +++ b/lib/irb/cmd/debug.rb @@ -1,4 +1,5 @@ require_relative "nop" +require_relative "../debug" module IRB # :stopdoc: @@ -12,37 +13,46 @@ class Debug < Nop '', binding.method(:irb).source_location.first, ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ } - IRB_DIR = File.expand_path('..', __dir__) def execute(pre_cmds: nil, do_cmds: nil) - unless binding_irb? - puts "`debug` command is only available when IRB is started with binding.irb" - return - end + if irb_context.with_debugger + # If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger. + if cmd = pre_cmds || do_cmds + throw :IRB_EXIT, cmd + else + puts "IRB is already running with a debug session." + return + end + else + # If IRB is not running with a debug session yet, then: + # 1. Check if the debugging command is run from a `binding.irb` call. + # 2. If so, try setting up the debug gem. + # 3. Insert a debug breakpoint at `Irb#debug_break` with the intended command. + # 4. Exit the current Irb#run call via `throw :IRB_EXIT`. + # 5. `Irb#debug_break` will be called and trigger the breakpoint, which will run the intended command. + unless binding_irb? + puts "`debug` command is only available when IRB is started with binding.irb" + return + end - unless setup_debugger - puts <<~MSG - You need to install the debug gem before using this command. - If you use `bundle exec`, please add `gem "debug"` into your Gemfile. - MSG - return - end + if IRB.respond_to?(:JobManager) + warn "Can't start the debugger when IRB is running in a multi-IRB session." + return + end - options = { oneshot: true, hook_call: false } - if pre_cmds || do_cmds - options[:command] = ['irb', pre_cmds, do_cmds] - end - if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src]) - options[:skip_src] = true - end + unless IRB::Debug.setup(irb_context.irb) + puts <<~MSG + You need to install the debug gem before using this command. + If you use `bundle exec`, please add `gem "debug"` into your Gemfile. + MSG + return + end - # To make debugger commands like `next` or `continue` work without asking - # the user to quit IRB after that, we need to exit IRB first and then hit - # a TracePoint on #debug_break. - file, lineno = IRB::Irb.instance_method(:debug_break).source_location - DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options) - # exit current Irb#run call - throw :IRB_EXIT + IRB::Debug.insert_debug_break(pre_cmds: pre_cmds, do_cmds: do_cmds) + + # exit current Irb#run call + throw :IRB_EXIT + end end private @@ -54,72 +64,6 @@ def binding_irb? end end end - - module SkipPathHelperForIRB - def skip_internal_path?(path) - # The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved - super || path.match?(IRB_DIR) || path.match?('') - end - end - - def setup_debugger - unless defined?(DEBUGGER__::SESSION) - begin - require "debug/session" - rescue LoadError # debug.gem is not written in Gemfile - return false unless load_bundled_debug_gem - end - DEBUGGER__.start(nonstop: true) - end - - unless DEBUGGER__.respond_to?(:capture_frames_without_irb) - DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames) - - def DEBUGGER__.capture_frames(*args) - frames = capture_frames_without_irb(*args) - frames.reject! do |frame| - frame.realpath&.start_with?(IRB_DIR) || frame.path == "" - end - frames - end - - DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB) - end - - true - end - - # This is used when debug.gem is not written in Gemfile. Even if it's not - # installed by `bundle install`, debug.gem is installed by default because - # it's a bundled gem. This method tries to activate and load that. - def load_bundled_debug_gem - # Discover latest debug.gem under GEM_PATH - debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path| - File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+(\w+)?\z/) - end.sort_by do |path| - Gem::Version.new(File.basename(path).delete_prefix('debug-')) - end.last - return false unless debug_gem - - # Discover debug/debug.so under extensions for Ruby 3.2+ - ext_name = "/debug/debug.#{RbConfig::CONFIG['DLEXT']}" - ext_path = Gem.paths.path.flat_map do |path| - Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}#{ext_name}") - end.first - - # Attempt to forcibly load the bundled gem - if ext_path - $LOAD_PATH << ext_path.delete_suffix(ext_name) - end - $LOAD_PATH << "#{debug_gem}/lib" - begin - require "debug/session" - puts "Loaded #{File.basename(debug_gem)}" - true - rescue LoadError - false - end - end end class DebugCommand < Debug diff --git a/lib/irb/cmd/subirb.rb b/lib/irb/cmd/subirb.rb index 3018ab277b42e9..5ffd646416707f 100644 --- a/lib/irb/cmd/subirb.rb +++ b/lib/irb/cmd/subirb.rb @@ -11,8 +11,7 @@ module IRB module ExtendCommand class MultiIRBCommand < Nop - def initialize(conf) - super + def execute(*args) extend_irb_context end @@ -29,6 +28,10 @@ def extend_irb_context # this extension patches IRB context like IRB.CurrentContext require_relative "../ext/multi-irb" end + + def print_debugger_warning + warn "Multi-IRB commands are not available when the debugger is enabled." + end end class IrbCommand < MultiIRBCommand @@ -37,6 +40,13 @@ class IrbCommand < MultiIRBCommand def execute(*obj) print_deprecated_warning + + if irb_context.with_debugger + print_debugger_warning + return + end + + super IRB.irb(nil, *obj) end end @@ -47,6 +57,13 @@ class Jobs < MultiIRBCommand def execute print_deprecated_warning + + if irb_context.with_debugger + print_debugger_warning + return + end + + super IRB.JobManager end end @@ -57,6 +74,14 @@ class Foreground < MultiIRBCommand def execute(key = nil) print_deprecated_warning + + if irb_context.with_debugger + print_debugger_warning + return + end + + super + raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key IRB.JobManager.switch(key) end @@ -68,6 +93,13 @@ class Kill < MultiIRBCommand def execute(*keys) print_deprecated_warning + + if irb_context.with_debugger + print_debugger_warning + return + end + + super IRB.JobManager.kill(*keys) end end diff --git a/lib/irb/context.rb b/lib/irb/context.rb index 18125ff6fb0851..43d9b53435df98 100644 --- a/lib/irb/context.rb +++ b/lib/irb/context.rb @@ -345,6 +345,8 @@ def main # User-defined IRB command aliases attr_accessor :command_aliases + attr_accessor :with_debugger + # Alias for #use_multiline alias use_multiline? use_multiline # Alias for #use_singleline diff --git a/lib/irb/debug.rb b/lib/irb/debug.rb new file mode 100644 index 00000000000000..dab9d1846a0514 --- /dev/null +++ b/lib/irb/debug.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +module IRB + module Debug + BINDING_IRB_FRAME_REGEXPS = [ + '', + binding.method(:irb).source_location.first, + ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ } + IRB_DIR = File.expand_path('..', __dir__) + + class << self + def insert_debug_break(pre_cmds: nil, do_cmds: nil) + options = { oneshot: true, hook_call: false } + + if pre_cmds || do_cmds + options[:command] = ['irb', pre_cmds, do_cmds] + end + if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src]) + options[:skip_src] = true + end + + # To make debugger commands like `next` or `continue` work without asking + # the user to quit IRB after that, we need to exit IRB first and then hit + # a TracePoint on #debug_break. + file, lineno = IRB::Irb.instance_method(:debug_break).source_location + DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options) + end + + def setup(irb) + # When debug session is not started at all + unless defined?(DEBUGGER__::SESSION) + begin + require "debug/session" + rescue LoadError # debug.gem is not written in Gemfile + return false unless load_bundled_debug_gem + end + DEBUGGER__::CONFIG.set_config + configure_irb_for_debugger(irb) + thread = Thread.current + + DEBUGGER__.initialize_session{ IRB::Debug::UI.new(thread, irb) } + end + + # When debug session was previously started but not by IRB + if defined?(DEBUGGER__::SESSION) && !irb.context.with_debugger + configure_irb_for_debugger(irb) + thread = Thread.current + + DEBUGGER__::SESSION.reset_ui(IRB::Debug::UI.new(thread, irb)) + end + + # Apply patches to debug gem so it skips IRB frames + unless DEBUGGER__.respond_to?(:capture_frames_without_irb) + DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames) + + def DEBUGGER__.capture_frames(*args) + frames = capture_frames_without_irb(*args) + frames.reject! do |frame| + frame.realpath&.start_with?(IRB_DIR) || frame.path == "" + end + frames + end + + DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB) + end + + true + end + + private + + def configure_irb_for_debugger(irb) + require 'irb/debug/ui' + IRB.instance_variable_set(:@debugger_irb, irb) + irb.context.with_debugger = true + irb.context.irb_name = "irb:rdbg" + end + + def binding_irb? + caller.any? do |frame| + BINDING_IRB_FRAME_REGEXPS.any? do |regexp| + frame.match?(regexp) + end + end + end + + module SkipPathHelperForIRB + def skip_internal_path?(path) + # The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved + super || path.match?(IRB_DIR) || path.match?('') + end + end + + # This is used when debug.gem is not written in Gemfile. Even if it's not + # installed by `bundle install`, debug.gem is installed by default because + # it's a bundled gem. This method tries to activate and load that. + def load_bundled_debug_gem + # Discover latest debug.gem under GEM_PATH + debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path| + File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+(\w+)?\z/) + end.sort_by do |path| + Gem::Version.new(File.basename(path).delete_prefix('debug-')) + end.last + return false unless debug_gem + + # Discover debug/debug.so under extensions for Ruby 3.2+ + ext_name = "/debug/debug.#{RbConfig::CONFIG['DLEXT']}" + ext_path = Gem.paths.path.flat_map do |path| + Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}#{ext_name}") + end.first + + # Attempt to forcibly load the bundled gem + if ext_path + $LOAD_PATH << ext_path.delete_suffix(ext_name) + end + $LOAD_PATH << "#{debug_gem}/lib" + begin + require "debug/session" + puts "Loaded #{File.basename(debug_gem)}" + true + rescue LoadError + false + end + end + end + end +end diff --git a/lib/irb/debug/ui.rb b/lib/irb/debug/ui.rb new file mode 100644 index 00000000000000..a4ca4fdf0f2df0 --- /dev/null +++ b/lib/irb/debug/ui.rb @@ -0,0 +1,104 @@ +require 'io/console/size' +require 'debug/console' + +module IRB + module Debug + class UI < DEBUGGER__::UI_Base + def initialize(thread, irb) + @thread = thread + @irb = irb + end + + def remote? + false + end + + def activate session, on_fork: false + end + + def deactivate + end + + def width + if (w = IO.console_size[1]) == 0 # for tests PTY + 80 + else + w + end + end + + def quit n + yield + exit n + end + + def ask prompt + setup_interrupt do + print prompt + ($stdin.gets || '').strip + end + end + + def puts str = nil + case str + when Array + str.each{|line| + $stdout.puts line.chomp + } + when String + str.each_line{|line| + $stdout.puts line.chomp + } + when nil + $stdout.puts + end + end + + def readline _ + setup_interrupt do + tc = DEBUGGER__::SESSION.get_thread_client(@thread) + cmd = @irb.debug_readline(tc.current_frame.binding || TOPLEVEL_BINDING) + + case cmd + when nil # when user types C-d + "continue" + else + cmd + end + end + end + + def setup_interrupt + DEBUGGER__::SESSION.intercept_trap_sigint false do + current_thread = Thread.current # should be session_server thread + + prev_handler = trap(:INT){ + current_thread.raise Interrupt + } + + yield + ensure + trap(:INT, prev_handler) + end + end + + def after_fork_parent + parent_pid = Process.pid + + at_exit{ + DEBUGGER__::SESSION.intercept_trap_sigint_end + trap(:SIGINT, :IGNORE) + + if Process.pid == parent_pid + # only check child process from its parent + begin + # wait for all child processes to keep terminal + Process.waitpid + rescue Errno::ESRCH, Errno::ECHILD + end + end + } + end + end + end +end diff --git a/lib/irb/history.rb b/lib/irb/history.rb index 516890ac058b0b..ae924d152b096e 100644 --- a/lib/irb/history.rb +++ b/lib/irb/history.rb @@ -4,6 +4,10 @@ def support_history_saving? true end + def reset_history_counter + @loaded_history_lines = self.class::HISTORY.size if defined? @loaded_history_lines + end + def load_history history = self.class::HISTORY if history_file = IRB.conf[:HISTORY_FILE] diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index 7d4f8a514c78d5..282e6ef05f225f 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -183,6 +183,10 @@ def save_prompt_to_context_io(opens, continue, line_num_offset) prompt(opens, continue, line_num_offset) end + def increase_line_no(addition) + @line_no += addition + end + def readmultiline save_prompt_to_context_io([], false, 0) @@ -220,7 +224,7 @@ def each_top_level_statement code.force_encoding(@context.io.encoding) yield code, @line_no, assignment_expression?(code) end - @line_no += code.count("\n") + increase_line_no(code.count("\n")) rescue TerminateLineInput end end diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb index d6fa67053d6f83..2bf3d5e0f11f1a 100644 --- a/lib/irb/workspace.rb +++ b/lib/irb/workspace.rb @@ -108,6 +108,10 @@ def initialize(*main) # IRB.conf[:__MAIN__] attr_reader :main + def load_commands_to_main + main.extend ExtendCommandBundle + end + # Evaluate the given +statements+ within the context of this workspace. def evaluate(statements, file = __FILE__, line = __LINE__) eval(statements, @binding, file, line) diff --git a/test/irb/test_debug_cmd.rb b/test/irb/test_debug_cmd.rb index 35239364bae51b..c4e4a04fdd64d4 100644 --- a/test/irb/test_debug_cmd.rb +++ b/test/irb/test_debug_cmd.rb @@ -27,10 +27,10 @@ def foo output = run_ruby_file do type "backtrace" - type "q!" + type "exit!" end - assert_match(/\(rdbg:irb\) backtrace/, output) + assert_match(/irb\(main\):001> backtrace/, output) assert_match(/Object#foo at #{@ruby_file.to_path}/, output) end @@ -46,10 +46,27 @@ def test_debug type "continue" end - assert_match(/\(rdbg\) next/, output) + assert_match(/irb\(main\):001> debug/, output) + assert_match(/irb:rdbg\(main\):002> next/, output) assert_match(/=> 2\| puts "hello"/, output) end + def test_debug_command_only_runs_once + write_ruby <<~'ruby' + binding.irb + ruby + + output = run_ruby_file do + type "debug" + type "debug" + type "continue" + end + + assert_match(/irb\(main\):001> debug/, output) + assert_match(/irb:rdbg\(main\):002> debug/, output) + assert_match(/IRB is already running with a debug session/, output) + end + def test_next write_ruby <<~'ruby' binding.irb @@ -61,7 +78,7 @@ def test_next type "continue" end - assert_match(/\(rdbg:irb\) next/, output) + assert_match(/irb\(main\):001> next/, output) assert_match(/=> 2\| puts "hello"/, output) end @@ -77,7 +94,7 @@ def test_break type "continue" end - assert_match(/\(rdbg:irb\) break/, output) + assert_match(/irb\(main\):001> break/, output) assert_match(/=> 2\| puts "Hello"/, output) end @@ -96,7 +113,7 @@ def test_delete type "continue" end - assert_match(/\(rdbg:irb\) delete/, output) + assert_match(/irb:rdbg\(main\):003> delete/, output) assert_match(/deleted: #0 BP - Line/, output) end @@ -115,11 +132,44 @@ def foo type "continue" end - assert_match(/\(rdbg:irb\) step/, output) + assert_match(/irb\(main\):001> step/, output) assert_match(/=> 5\| foo/, output) assert_match(/=> 2\| puts "Hello"/, output) end + def test_long_stepping + write_ruby <<~'RUBY' + class Foo + def foo(num) + bar(num + 10) + end + + def bar(num) + num + end + end + + binding.irb + Foo.new.foo(100) + RUBY + + output = run_ruby_file do + type "step" + type "step" + type "step" + type "step" + type "num" + type "continue" + end + + assert_match(/irb\(main\):001> step/, output) + assert_match(/irb:rdbg\(main\):002> step/, output) + assert_match(/irb:rdbg\(#\):003> step/, output) + assert_match(/irb:rdbg\(#\):004> step/, output) + assert_match(/irb:rdbg\(#\):005> num/, output) + assert_match(/=> 110/, output) + end + def test_continue write_ruby <<~'RUBY' binding.irb @@ -133,8 +183,9 @@ def test_continue type "continue" end - assert_match(/\(rdbg:irb\) continue/, output) + assert_match(/irb\(main\):001> continue/, output) assert_match(/=> 3: binding.irb/, output) + assert_match(/irb:rdbg\(main\):002> continue/, output) end def test_finish @@ -151,7 +202,7 @@ def foo type "continue" end - assert_match(/\(rdbg:irb\) finish/, output) + assert_match(/irb\(main\):001> finish/, output) assert_match(/=> 4\| end/, output) end @@ -169,7 +220,7 @@ def foo type "continue" end - assert_match(/\(rdbg:irb\) info/, output) + assert_match(/irb\(main\):001> info/, output) assert_match(/%self = main/, output) assert_match(/a = "Hello"/, output) end @@ -186,8 +237,152 @@ def test_catch type "continue" end - assert_match(/\(rdbg:irb\) catch/, output) + assert_match(/irb\(main\):001> catch/, output) assert_match(/Stop by #0 BP - Catch "ZeroDivisionError"/, output) end + + def test_exit + write_ruby <<~'RUBY' + binding.irb + puts "hello" + RUBY + + output = run_ruby_file do + type "next" + type "exit" + end + + assert_match(/irb\(main\):001> next/, output) + end + + def test_quit + write_ruby <<~'RUBY' + binding.irb + RUBY + + output = run_ruby_file do + type "next" + type "quit!" + end + + assert_match(/irb\(main\):001> next/, output) + end + + def test_prompt_line_number_continues + write_ruby <<~'ruby' + binding.irb + puts "Hello" + puts "World" + ruby + + output = run_ruby_file do + type "123" + type "456" + type "next" + type "info" + type "next" + type "continue" + end + + assert_match(/irb\(main\):003> next/, output) + assert_match(/irb:rdbg\(main\):004> info/, output) + assert_match(/irb:rdbg\(main\):005> next/, output) + end + + def test_irb_commands_are_available_after_moving_around_with_the_debugger + write_ruby <<~'ruby' + class Foo + def bar + puts "bar" + end + end + + binding.irb + Foo.new.bar + ruby + + output = run_ruby_file do + # Due to the way IRB defines its commands, moving into the Foo instance from main is necessary for proper testing. + type "next" + type "step" + type "irb_info" + type "continue" + end + + assert_include(output, "InputMethod: RelineInputMethod") + end + + def test_input_is_evaluated_in_the_context_of_the_current_thread + write_ruby <<~'ruby' + current_thread = Thread.current + binding.irb + ruby + + output = run_ruby_file do + type "debug" + type '"Threads match: #{current_thread == Thread.current}"' + type "continue" + end + + assert_match(/irb\(main\):001> debug/, output) + assert_match(/Threads match: true/, output) + end + + def test_irb_switches_debugger_interface_if_debug_was_already_activated + write_ruby <<~'ruby' + require 'debug' + class Foo + def bar + puts "bar" + end + end + + binding.irb + Foo.new.bar + ruby + + output = run_ruby_file do + # Due to the way IRB defines its commands, moving into the Foo instance from main is necessary for proper testing. + type "next" + type "step" + type 'irb_info' + type "continue" + end + + assert_match(/irb\(main\):001> next/, output) + assert_include(output, "InputMethod: RelineInputMethod") + end + + def test_debugger_cant_be_activated_while_multi_irb_is_active + write_ruby <<~'ruby' + binding.irb + a = 1 + ruby + + output = run_ruby_file do + type "jobs" + type "next" + type "exit" + end + + assert_match(/irb\(main\):001> jobs/, output) + assert_include(output, "Can't start the debugger when IRB is running in a multi-IRB session.") + end + + def test_multi_irb_commands_are_not_available_after_activating_the_debugger + write_ruby <<~'ruby' + binding.irb + a = 1 + ruby + + output = run_ruby_file do + type "next" + type "jobs" + type "continue" + end + + assert_match(/irb\(main\):001> next/, output) + assert_include(output, "Multi-IRB commands are not available when the debugger is enabled.") + end end end diff --git a/test/irb/test_history.rb b/test/irb/test_history.rb index 39f9e8275034ae..9bf146609c2ab2 100644 --- a/test/irb/test_history.rb +++ b/test/irb/test_history.rb @@ -209,7 +209,50 @@ def with_temp_stdio end end - class NestedIRBHistoryTest < IntegrationTestCase + class IRBHistoryIntegrationTest < IntegrationTestCase + def test_history_saving_with_debug + if ruby_core? + omit "This test works only under ruby/irb" + end + + write_history "" + + write_ruby <<~'RUBY' + def foo + end + + binding.irb + + foo + RUBY + + output = run_ruby_file do + type "'irb session'" + type "next" + type "'irb:debug session'" + type "step" + type "irb_info" + type "puts Reline::HISTORY.to_a.to_s" + type "q!" + end + + assert_include(output, "InputMethod: RelineInputMethod") + # check that in-memory history is preserved across sessions + assert_include output, %q( + ["'irb session'", "next", "'irb:debug session'", "step", "irb_info", "puts Reline::HISTORY.to_a.to_s"] + ).strip + + assert_equal <<~HISTORY, @history_file.open.read + 'irb session' + next + 'irb:debug session' + step + irb_info + puts Reline::HISTORY.to_a.to_s + q! + HISTORY + end + def test_history_saving_with_nested_sessions write_history "" From 3080cf3decf18c72c1fc608c112048fff0614c9b Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Sun, 13 Aug 2023 20:20:36 +0100 Subject: [PATCH 021/158] [DOC] Don't suppress autolinks --- numeric.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/numeric.c b/numeric.c index 5993d08a657a90..6afb5b50dede91 100644 --- a/numeric.c +++ b/numeric.c @@ -671,7 +671,7 @@ num_div(VALUE x, VALUE y) * Of the Core and Standard Library classes, * only Rational uses this implementation. * - * For \Rational +r+ and real number +n+, these expressions are equivalent: + * For Rational +r+ and real number +n+, these expressions are equivalent: * * r % n * r-n*(r/n).floor @@ -1002,7 +1002,7 @@ num_negative_p(VALUE num) and +self+ * - #divmod: Returns a 2-element array containing the quotient and remainder * results of dividing +self+ by the given value. - * - #fdiv: Returns the Float result of dividing +self+ by the given value. + * - #fdiv: Returns the \Float result of dividing +self+ by the given value. * - #floor: Returns the greatest number smaller than or equal to +self+. * - #next_float: Returns the next-larger representable \Float. * - #prev_float: Returns the next-smaller representable \Float. @@ -2335,7 +2335,7 @@ int_half_p_half_down(VALUE num, VALUE n, VALUE f) } /* - * Assumes num is an Integer, ndigits <= 0 + * Assumes num is an \Integer, ndigits <= 0 */ static VALUE rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode) @@ -5339,7 +5339,7 @@ int_aref(int const argc, VALUE * const argv, VALUE const num) * 1.to_f # => 1.0 * -1.to_f # => -1.0 * - * If the value of +self+ does not fit in a \Float, + * If the value of +self+ does not fit in a Float, * the result is infinity: * * (10**400).to_f # => Infinity @@ -6032,9 +6032,9 @@ int_s_try_convert(VALUE self, VALUE num) /* * Document-class: Numeric * - * Numeric is the class from which all higher-level numeric classes should inherit. + * \Numeric is the class from which all higher-level numeric classes should inherit. * - * Numeric allows instantiation of heap-allocated objects. Other core numeric classes such as + * \Numeric allows instantiation of heap-allocated objects. Other core numeric classes such as * Integer are implemented as immediates, which means that each Integer is a single immutable * object which is always passed by value. * @@ -6048,9 +6048,9 @@ int_s_try_convert(VALUE self, VALUE num) * 1.dup #=> 1 * 1.object_id == 1.dup.object_id #=> true * - * For this reason, Numeric should be used when defining other numeric classes. + * For this reason, \Numeric should be used when defining other numeric classes. * - * Classes which inherit from Numeric must implement +coerce+, which returns a two-member + * Classes which inherit from \Numeric must implement +coerce+, which returns a two-member * Array containing an object that has been coerced into an instance of the new class * and +self+ (see #coerce). * From d33555eeaeac76a76c086c3dd09f53fff88d7f6a Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Sun, 13 Aug 2023 20:23:41 -0500 Subject: [PATCH 022/158] [DOC] RDoc for numeric.rb (#8216) --- numeric.rb | 271 ++++++++++++++++++++++++----------------------------- 1 file changed, 125 insertions(+), 146 deletions(-) diff --git a/numeric.rb b/numeric.rb index 92768200ad16bd..806b65becd035e 100644 --- a/numeric.rb +++ b/numeric.rb @@ -1,62 +1,56 @@ class Numeric - # + # call-seq: - # num.real? -> true or false + # real? -> true or false # - # Returns +true+ if +num+ is a real number (i.e. not Complex). + # Returns +true+ if +self+ is a real number (i.e. not Complex). # def real? true end - # # call-seq: - # num.real -> self + # real -> self # - # Returns self. + # Returns +self+. # def real self end - # # call-seq: - # num.integer? -> true or false + # integer? -> true or false # - # Returns +true+ if +num+ is an Integer. + # Returns +true+ if +self+ is an Integer. # - # 1.0.integer? #=> false - # 1.integer? #=> true + # 1.0.integer? # => false + # 1.integer? # => true # def integer? false end - # # call-seq: - # num.finite? -> true or false + # finite? -> true or false # - # Returns +true+ if +num+ is a finite number, otherwise returns +false+. + # Returns +true+ if +self+ is a finite number, +false+ otherwise. # def finite? true end - # # call-seq: - # num.infinite? -> -1, 1, or nil + # infinite? -> -1, 1, or nil # - # Returns +nil+, -1, or 1 depending on whether the value is - # finite, -Infinity, or +Infinity. + # Returns +nil+, -1, or 1 depending on whether +self+ is + # finite, -Infinity, or +Infinity. # def infinite? nil end - # # call-seq: - # num.imag -> 0 - # num.imaginary -> 0 + # imag -> 0 # # Returns zero. # @@ -66,12 +60,10 @@ def imaginary alias imag imaginary - # # call-seq: - # num.conj -> self - # num.conjugate -> self + # conj -> self # - # Returns self. + # Returns +self+. # def conjugate self @@ -82,39 +74,41 @@ def conjugate class Integer # call-seq: - # -int -> integer + # -int -> integer # - # Returns +int+, negated. + # Returns +self+, negated. def -@ Primitive.attr! :leaf Primitive.cexpr! 'rb_int_uminus(self)' end # call-seq: - # ~int -> integer + # ~int -> integer + # + # One's complement: + # returns the value of +self+ with each bit inverted. # - # One's complement: returns a number where each bit is flipped. + # Because an integer value is conceptually of infinite length, + # the result acts as if it had an infinite number of + # one bits to the left. + # In hex representations, this is displayed + # as two periods to the left of the digits: # - # Inverts the bits in an Integer. As integers are conceptually of - # infinite length, the result acts as if it had an infinite number of - # one bits to the left. In hex representations, this is displayed - # as two periods to the left of the digits. + # sprintf("%X", ~0x1122334455) # => "..FEEDDCCBBAA" # - # sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA" def ~ Primitive.attr! :leaf Primitive.cexpr! 'rb_int_comp(self)' end # call-seq: - # int.abs -> integer - # int.magnitude -> integer + # abs -> integer # - # Returns the absolute value of +int+. + # Returns the absolute value of +self+. # - # (-12345).abs #=> 12345 - # -12345.abs #=> 12345 - # 12345.abs #=> 12345 + # (-12345).abs # => 12345 + # -12345.abs # => 12345 + # 12345.abs # => 12345 # def abs Primitive.attr! :leaf @@ -122,64 +116,65 @@ def abs end # call-seq: - # int.bit_length -> integer + # bit_length -> integer # - # Returns the number of bits of the value of +int+. - # - # "Number of bits" means the bit position of the highest bit - # which is different from the sign bit + # Returns the number of bits of the value of +self+, + # which is the bit position of the highest-order bit + # that is different from the sign bit # (where the least significant bit has bit position 1). - # If there is no such bit (zero or minus one), zero is returned. - # - # I.e. this method returns ceil(log2(int < 0 ? -int : int+1)). - # - # (-2**1000-1).bit_length #=> 1001 - # (-2**1000).bit_length #=> 1000 - # (-2**1000+1).bit_length #=> 1000 - # (-2**12-1).bit_length #=> 13 - # (-2**12).bit_length #=> 12 - # (-2**12+1).bit_length #=> 12 - # -0x101.bit_length #=> 9 - # -0x100.bit_length #=> 8 - # -0xff.bit_length #=> 8 - # -2.bit_length #=> 1 - # -1.bit_length #=> 0 - # 0.bit_length #=> 0 - # 1.bit_length #=> 1 - # 0xff.bit_length #=> 8 - # 0x100.bit_length #=> 9 - # (2**12-1).bit_length #=> 12 - # (2**12).bit_length #=> 13 - # (2**12+1).bit_length #=> 13 - # (2**1000-1).bit_length #=> 1000 - # (2**1000).bit_length #=> 1001 - # (2**1000+1).bit_length #=> 1001 - # - # This method can be used to detect overflow in Array#pack as follows: - # - # if n.bit_length < 32 - # [n].pack("l") # no overflow - # else - # raise "overflow" - # end + # If there is no such bit (zero or minus one), returns zero. + # + # This method returns ceil(log2(self < 0 ? -self : self + 1))>. + # + # (-2**1000-1).bit_length # => 1001 + # (-2**1000).bit_length # => 1000 + # (-2**1000+1).bit_length # => 1000 + # (-2**12-1).bit_length # => 13 + # (-2**12).bit_length # => 12 + # (-2**12+1).bit_length # => 12 + # -0x101.bit_length # => 9 + # -0x100.bit_length # => 8 + # -0xff.bit_length # => 8 + # -2.bit_length # => 1 + # -1.bit_length # => 0 + # 0.bit_length # => 0 + # 1.bit_length # => 1 + # 0xff.bit_length # => 8 + # 0x100.bit_length # => 9 + # (2**12-1).bit_length # => 12 + # (2**12).bit_length # => 13 + # (2**12+1).bit_length # => 13 + # (2**1000-1).bit_length # => 1000 + # (2**1000).bit_length # => 1001 + # (2**1000+1).bit_length # => 1001 + # + # For \Integer _n_, + # this method can be used to detect overflow in Array#pack: + # + # if n.bit_length < 32 + # [n].pack('l') # No overflow. + # else + # raise 'Overflow' + # end + # def bit_length Primitive.attr! :leaf Primitive.cexpr! 'rb_int_bit_length(self)' end # call-seq: - # int.even? -> true or false + # even? -> true or false # - # Returns +true+ if +int+ is an even number. + # Returns +true+ if +self+ is an even number, +false+ otherwise. def even? Primitive.attr! :leaf Primitive.cexpr! 'rb_int_even_p(self)' end # call-seq: - # int.integer? -> true + # integer? -> true # - # Since +int+ is already an Integer, this always returns +true+. + # Since +self+ is already an \Integer, always returns +true+. def integer? true end @@ -187,41 +182,35 @@ def integer? alias magnitude abs # call-seq: - # int.odd? -> true or false + # odd? -> true or false # - # Returns +true+ if +int+ is an odd number. + # Returns +true+ if +self+ is an odd number, +false+ otherwise. def odd? Primitive.attr! :leaf Primitive.cexpr! 'rb_int_odd_p(self)' end # call-seq: - # int.ord -> self - # - # Returns the +int+ itself. - # - # 97.ord #=> 97 - # - # This method is intended for compatibility to character literals - # in Ruby 1.9. + # ord -> self # - # For example, ?a.ord returns 97 both in 1.8 and 1.9. + # Returns +self+; + # intended for compatibility to character literals in Ruby 1.9. def ord self end # call-seq: - # int.size -> int + # size -> integer # - # Returns the number of bytes in the machine representation of +int+ - # (machine dependent). + # Returns the number of bytes in the machine representation of +self+; + # the value is system-dependent: # - # 1.size #=> 8 - # -1.size #=> 8 - # 2147483647.size #=> 8 - # (256**10 - 1).size #=> 10 - # (256**20 - 1).size #=> 20 - # (256**40 - 1).size #=> 40 + # 1.size # => 8 + # -1.size # => 8 + # 2147483647.size # => 8 + # (256**10 - 1).size # => 10 + # (256**20 - 1).size # => 20 + # (256**40 - 1).size # => 40 # def size Primitive.attr! :leaf @@ -229,89 +218,86 @@ def size end # call-seq: - # int.to_i -> integer + # to_i -> self # - # Since +int+ is already an Integer, returns +self+. + # Returns +self+ (which is already an \Integer). def to_i self end # call-seq: - # int.to_int -> integer + # to_int -> self # - # Since +int+ is already an Integer, returns +self+. + # Returns +self+ (which is already an \Integer). def to_int self end # call-seq: - # int.zero? -> true or false + # zero? -> true or false # - # Returns +true+ if +int+ has a zero value. + # Returns +true+ if +self+ has a zero value, +false+ otherwise. def zero? Primitive.attr! :leaf Primitive.cexpr! 'rb_int_zero_p(self)' end # call-seq: - # ceildiv(other) -> integer + # ceildiv(numeric) -> integer # - # Returns the result of division +self+ by +other+. The result is rounded up to the nearest integer. + # Returns the result of division +self+ by +numeric+. + # rounded up to the nearest integer. # - # 3.ceildiv(3) # => 1 - # 4.ceildiv(3) # => 2 + # 3.ceildiv(3) # => 1 + # 4.ceildiv(3) # => 2 # - # 4.ceildiv(-3) # => -1 - # -4.ceildiv(3) # => -1 + # 4.ceildiv(-3) # => -1 + # -4.ceildiv(3) # => -1 # -4.ceildiv(-3) # => 2 # # 3.ceildiv(1.2) # => 3 + # def ceildiv(other) -div(0 - other) end # # call-seq: - # int.numerator -> self + # numerator -> self # - # Returns self. + # Returns +self+. # def numerator self end - # # call-seq: - # int.denominator -> 1 - # - # Returns 1. + # denominator -> 1 # + # Returns +1+. def denominator 1 end end class Float - # + # call-seq: - # float.to_f -> self - # - # Since +float+ is already a Float, returns +self+. + # to_f -> self # + # Returns +self+ (which is already a \Float). def to_f self end - # # call-seq: - # float.abs -> float - # float.magnitude -> float + # float.abs -> float # - # Returns the absolute value of +float+. + # Returns the absolute value of +self+: # - # (-34.56).abs #=> 34.56 - # -34.56.abs #=> 34.56 - # 34.56.abs #=> 34.56 + # (-34.56).abs # => 34.56 + # -34.56.abs # => 34.56 + # 34.56.abs # => 34.56 # def abs Primitive.attr! :leaf @@ -323,45 +309,38 @@ def magnitude Primitive.cexpr! 'rb_float_abs(self)' end - # # call-seq: - # -float -> float + # -float -> float # - # Returns +float+, negated. + # Returns +self+, negated. # def -@ Primitive.attr! :leaf Primitive.cexpr! 'rb_float_uminus(self)' end - # # call-seq: - # float.zero? -> true or false - # - # Returns +true+ if +float+ is 0.0. + # zero? -> true or false # + # Returns +true+ if +self+ is 0.0, +false+ otherwise. def zero? Primitive.attr! :leaf Primitive.cexpr! 'RBOOL(FLOAT_ZERO_P(self))' end - # # call-seq: - # float.positive? -> true or false - # - # Returns +true+ if +float+ is greater than 0. + # positive? -> true or false # + # Returns +true+ if +self+ is greater than 0, +false+ otherwise. def positive? Primitive.attr! :leaf Primitive.cexpr! 'RBOOL(RFLOAT_VALUE(self) > 0.0)' end - # # call-seq: - # float.negative? -> true or false - # - # Returns +true+ if +float+ is less than 0. + # negative? -> true or false # + # Returns +true+ if +self+ is less than 0, +false+ otherwise. def negative? Primitive.attr! :leaf Primitive.cexpr! 'RBOOL(RFLOAT_VALUE(self) < 0.0)' From 2a3acbc420cc94af07a16d45310554f616dc457a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 12 Aug 2023 00:14:08 +0900 Subject: [PATCH 023/158] Fix test and precheck order for old GNU Make --- common.mk | 9 ++++++--- defs/gmake.mk | 22 +++++++++++++++++++--- template/Makefile.in | 7 +++++-- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/common.mk b/common.mk index d031ab28867a6a..6aea69e9e09261 100644 --- a/common.mk +++ b/common.mk @@ -883,10 +883,12 @@ test-sample: test-basic # backward compatibility for mswin-build test-short: btest-ruby $(DOT_WAIT) test-knownbug $(DOT_WAIT) test-basic test: test-short +yes-test-all-precheck: programs encs exts PHONY $(DOT_WAIT) + # $ make test-all TESTOPTS="--help" displays more detail # for example, make test-all TESTOPTS="-j2 -v -n test-name -- test-file-name" test-all: $(TEST_RUNNABLE)-test-all -yes-test-all: programs PHONY +yes-test-all: yes-test-all-precheck $(ACTIONS_GROUP) $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) $(TESTS) $(ACTIONS_ENDGROUP) @@ -928,10 +930,10 @@ $(RBCONFIG): $(tooldir)/mkconfig.rb config.status $(srcdir)/version.h $(srcdir)/ test-rubyspec: test-spec yes-test-rubyspec: yes-test-spec -test-spec-precheck: programs yes-fake +yes-test-spec-precheck: yes-test-all-precheck yes-fake test-spec: $(TEST_RUNNABLE)-test-spec -yes-test-spec: test-spec-precheck +yes-test-spec: yes-test-spec-precheck $(ACTIONS_GROUP) $(gnumake_recursive)$(Q) \ $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/rubyspec_temp \ @@ -1544,6 +1546,7 @@ check: $(DOT_WAIT) $(PREPARE_SYNTAX_SUGGEST) test-syntax-suggest test-bundler-precheck: $(TEST_RUNNABLE)-test-bundler-precheck no-test-bundler-precheck: yes-test-bundler-precheck: main $(arch)-fake.rb +yes-test-bundler-parallel-precheck: yes-test-bundler-precheck test-bundler-prepare: $(TEST_RUNNABLE)-test-bundler-prepare no-test-bundler-prepare: no-test-bundler-precheck diff --git a/defs/gmake.mk b/defs/gmake.mk index db622db257b444..9042b8ad120f3d 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -38,6 +38,7 @@ TEST_DEPENDS := $(filter-out test-all $(TEST_TARGETS),$(TEST_DEPENDS)) TEST_TARGETS := $(patsubst test,test-short,$(TEST_TARGETS)) TEST_DEPENDS := $(filter-out test $(TEST_TARGETS),$(TEST_DEPENDS)) TEST_TARGETS := $(patsubst test-short,btest-ruby test-knownbug test-basic,$(TEST_TARGETS)) +TEST_TARGETS := $(patsubst test-basic,test-basic test-leaked-globals,$(TEST_TARGETS)) TEST_TARGETS := $(patsubst test-bundled-gems,test-bundled-gems-run,$(TEST_TARGETS)) TEST_TARGETS := $(patsubst test-bundled-gems-run,test-bundled-gems-run $(PREPARE_BUNDLED_GEMS),$(TEST_TARGETS)) TEST_TARGETS := $(patsubst test-bundled-gems-prepare,test-bundled-gems-prepare $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch,$(TEST_TARGETS)) @@ -92,16 +93,31 @@ $(addprefix yes-,$(TEST_TARGETS)): $(TEST_DEPENDS) endif ORDERED_TEST_TARGETS := $(filter $(TEST_TARGETS), \ - btest-ruby test-knownbug test-basic \ + btest-ruby test-knownbug test-leaked-globals test-basic \ test-testframework test-tool test-ruby test-all \ test-spec test-syntax-suggest-prepare test-syntax-suggest \ test-bundler-prepare test-bundler test-bundler-parallel \ test-bundled-gems-precheck test-bundled-gems-fetch \ test-bundled-gems-prepare test-bundled-gems-run \ ) -prev_test := $(if $(filter test-spec,$(ORDERED_TEST_TARGETS)),test-spec-precheck) + +# grep ^yes-test-.*-precheck: template/Makefile.in defs/gmake.mk common.mk +test_prechecks := $(filter $(ORDERED_TEST_TARGETS),\ + test-leaked-globals \ + test-all \ + test-spec \ + test-syntax-suggest \ + test-bundler \ + test-bundler-parallel \ + test-bundled-gems\ + ) +prev_test := $(subst test-bundler-parallel,test-bundler,$(test_prechecks)) +prev_test := $(addsuffix -precheck,$(prev_test)) +first_test_prechecks := $(prev_test) + $(foreach test,$(ORDERED_TEST_TARGETS), \ - $(eval yes-$(value test) no-$(value test): $(value prev_test)); \ + $(eval yes-$(value test): $(addprefix yes-,$(value prev_test))); \ + $(eval no-$(value test): $(addprefix no-,$(value prev_test))); \ $(eval prev_test := $(value test))) endif diff --git a/template/Makefile.in b/template/Makefile.in index 5e7edc2f18a358..4a19a3cec6de7d 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -637,8 +637,11 @@ un-runnable: $(Q) exit 1 LIBRUBY_FOR_LEAKED_GLOBALS = $(enable_shared:no=) -yes-test-basic: $(DOT_WAIT) leaked-globals -leaked-globals: $(COMMONOBJS) prog $(tooldir)/leaked-globals +yes-test-basic: $(DOT_WAIT) test-leaked-globals +leaked-globals: test-leaked-globals +yes-test-leaked-globals-precheck: $(COMMONOBJS) prog $(tooldir)/leaked-globals +test-leaked-globals: yes-test-leaked-globals +yes-test-leaked-globals: yes-test-leaked-globals-precheck $(ACTIONS_GROUP) $(Q) $(XRUBY) $(tooldir)/leaked-globals \ SOEXT=$(SOEXT) NM="$(NM) -Pgp" SYMBOL_PREFIX=$(SYMBOL_PREFIX) \ From 75c9487a98ebb27d38387a0c900ff5b1f34c30d2 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 14 Aug 2023 07:18:19 -0700 Subject: [PATCH 024/158] YJIT: Chain guard classes on instance_of (#8209) --- yjit/src/codegen.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index d34a180837b3a4..11d70a3e6b343c 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4264,7 +4264,7 @@ fn jit_rb_kernel_is_a( fn jit_rb_kernel_instance_of( jit: &mut JITState, asm: &mut Assembler, - _ocb: &mut OutlinedCb, + ocb: &mut OutlinedCb, _ci: *const rb_callinfo, _cme: *const rb_callable_method_entry_t, _block: Option, @@ -4305,7 +4305,14 @@ fn jit_rb_kernel_instance_of( asm.comment("Kernel#instance_of?"); asm.cmp(asm.stack_opnd(0), sample_rhs.into()); - asm.jne(Target::side_exit(Counter::guard_send_instance_of_class_mismatch)); + jit_chain_guard( + JCC_JNE, + jit, + asm, + ocb, + SEND_MAX_CHAIN_DEPTH, + Counter::guard_send_instance_of_class_mismatch, + ); asm.stack_pop(2); From 52837fcec2340048f9bdc2169cde17243c5e9d6d Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 14 Aug 2023 11:48:39 -0400 Subject: [PATCH 025/158] [DOC] Remove Document-class from trace_point.rb --- trace_point.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/trace_point.rb b/trace_point.rb index ac4086589c6bbf..dc9c339b6b26ba 100644 --- a/trace_point.rb +++ b/trace_point.rb @@ -1,7 +1,5 @@ # loaded from vm_trace.c -# Document-class: TracePoint -# # A class that provides the functionality of Kernel#set_trace_func in a # nice Object-Oriented API. # From b1f6c4b568597995ea404711440d4cabcfef0236 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 15 Aug 2023 11:07:53 +0900 Subject: [PATCH 026/158] Remove a misplaced and duplicate file [ci skip] --- .../seattlerb/pct_w_heredoc_interp_nested.txt | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 test/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt diff --git a/test/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt b/test/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt deleted file mode 100644 index 89ce74ce19627d..00000000000000 --- a/test/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt +++ /dev/null @@ -1,28 +0,0 @@ -ProgramNode(0...30)( - [], - StatementsNode(0...30)( - [ArrayNode(0...30)( - [StringNode(4...5)(nil, (4...5), nil, "1"), - InterpolatedStringNode(0...12)( - nil, - [EmbeddedStatementsNode(6...12)( - (6...8), - StatementsNode(8...19)( - [InterpolatedStringNode(8...19)( - (8...11), - [StringNode(15...17)(nil, (15...17), nil, "2\n")], - (17...19) - )] - ), - (11...12) - )], - nil - ), - StringNode(13...14)(nil, (13...14), nil, "3"), - StringNode(25...26)(nil, (25...26), nil, "4"), - StringNode(27...28)(nil, (27...28), nil, "5")], - (0...3), - (29...30) - )] - ) -) From 542424fc5693cbd6dd0d0bcbdca06364751f71f9 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 15 Aug 2023 11:19:05 +0900 Subject: [PATCH 027/158] An empty test file for satisfy chkbuild [ci skip] --- test/lib/!Nothing_to_test.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/lib/!Nothing_to_test.rb diff --git a/test/lib/!Nothing_to_test.rb b/test/lib/!Nothing_to_test.rb new file mode 100644 index 00000000000000..e69de29bb2d1d6 From b554198572b6670b4606d479e5510dd1d1d6ce6a Mon Sep 17 00:00:00 2001 From: git Date: Tue, 15 Aug 2023 02:37:12 +0000 Subject: [PATCH 028/158] * append newline at EOF. [ci skip] --- test/lib/!Nothing_to_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lib/!Nothing_to_test.rb b/test/lib/!Nothing_to_test.rb index e69de29bb2d1d6..8b137891791fe9 100644 --- a/test/lib/!Nothing_to_test.rb +++ b/test/lib/!Nothing_to_test.rb @@ -0,0 +1 @@ + From a11b90774592ccac72eda0f2a8f1a1e5cc3e4fc6 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 15 Aug 2023 12:49:05 +0900 Subject: [PATCH 029/158] Add description to the empty test file [ci skip] --- test/lib/!Nothing_to_test.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/lib/!Nothing_to_test.rb b/test/lib/!Nothing_to_test.rb index 8b137891791fe9..c1f4c439d3208c 100644 --- a/test/lib/!Nothing_to_test.rb +++ b/test/lib/!Nothing_to_test.rb @@ -1 +1,5 @@ +### Empty test file for chkbuild ### +# If chkbuild fails with `test-all`, each child file/directory is +# executed individually, but test-unit fails if there are no test +# files in the specified directory. From 300bc145892488b91f10438f06fe75d03809424c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 14 Aug 2023 14:04:39 -0400 Subject: [PATCH 030/158] [DOC] Improve some GC docs --- gc.c | 2 +- gc.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gc.c b/gc.c index 70b9b36d638d38..d2c5c52692fd25 100644 --- a/gc.c +++ b/gc.c @@ -13813,7 +13813,7 @@ Init_GC(void) rb_hash_aset(gc_constants, ID2SYM(rb_intern("RB_BUG_INSTEAD_OF_RB_MEMERROR")), Qtrue); } OBJ_FREEZE(gc_constants); - /* internal constants */ + /* Internal constants in the garbage collector. */ rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants); rb_mProfiler = rb_define_module_under(rb_mGC, "Profiler"); diff --git a/gc.rb b/gc.rb index dd4fb6c274c88a..cbb5daf654e037 100644 --- a/gc.rb +++ b/gc.rb @@ -1,6 +1,6 @@ # for gc.c -# The GC module provides an interface to Ruby's mark and +# The \GC module provides an interface to Ruby's mark and # sweep garbage collection mechanism. # # Some of the underlying methods are also available via the ObjectSpace From 2498140777020808a007691516e7bf8d8d862215 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 14 Aug 2023 14:04:55 -0400 Subject: [PATCH 031/158] [DOC] Improve docs for GC.start --- gc.rb | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/gc.rb b/gc.rb index cbb5daf654e037..215a95b032f148 100644 --- a/gc.rb +++ b/gc.rb @@ -10,26 +10,31 @@ # GC::Profiler. module GC - # call-seq: - # GC.start -> nil - # ObjectSpace.garbage_collect -> nil - # include GC; garbage_collect -> nil - # GC.start(full_mark: true, immediate_sweep: true) -> nil - # ObjectSpace.garbage_collect(full_mark: true, immediate_sweep: true) -> nil - # include GC; garbage_collect(full_mark: true, immediate_sweep: true) -> nil - # - # Initiates garbage collection, even if manually disabled. - # - # This method is defined with keyword arguments that default to true: - # - # def GC.start(full_mark: true, immediate_sweep: true); end - # - # Use full_mark: false to perform a minor \GC. - # Use immediate_sweep: false to defer sweeping (use lazy sweep). - # - # Note: These keyword arguments are implementation and version dependent. They - # are not guaranteed to be future-compatible, and may be ignored if the - # underlying implementation does not support them. + # Initiates garbage collection, even if manually disabled. + # + # The +full_mark+ keyword argument determines whether or not to perform a + # major garbage collection cycle. When set to +true+, a major garbage + # collection cycle is ran, meaning all objects are marked. When set to + # +false+, a minor garbage collection cycle is ran, meaning only young + # objects are marked. + # + # The +immediate_mark+ keyword argument determines whether or not to perform + # incremental marking. When set to +true+, marking is completed during the + # call to this method. When set to +false+, marking is performed in steps + # that is interleaved with future Ruby code execution, so marking might not + # be completed during this method call. Note that if +full_mark+ is +false+ + # then marking will always be immediate, regardless of the value of + # +immediate_mark+. + # + # The +immedate_sweep+ keyword argument determines whether or not to defer + # sweeping (using lazy sweep). When set to +true+, sweeping is performed in + # steps that is interleaved with future Ruby code execution, so sweeping might + # not be completed during this method call. When set to +false+, sweeping is + # completed during the call to this method. + # + # Note: These keyword arguments are implementation and version dependent. They + # are not guaranteed to be future-compatible, and may be ignored if the + # underlying implementation does not support them. def self.start full_mark: true, immediate_mark: true, immediate_sweep: true Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false end From 01f74b28521069e2582fbd751c34b115fe033a2b Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 14 Aug 2023 14:06:03 -0400 Subject: [PATCH 032/158] [DOC] Improve docs about keys in GC.stat_heap --- gc.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/gc.rb b/gc.rb index 215a95b032f148..5f9940b4d61e06 100644 --- a/gc.rb +++ b/gc.rb @@ -219,6 +219,33 @@ def self.stat hash_or_key = nil # If the optional argument, hash, is given, it is overwritten and returned. # # This method is only expected to work on CRuby. + # + # The hash includes the following keys about the internal information in + # the \GC: + # + # [slot_size] + # The slot size of the heap in bytes. + # [heap_allocatable_pages] + # The number of pages that can be allocated without triggering a new + # garbage collection cycle. + # [heap_eden_pages] + # The number of pages in the eden heap. + # [heap_eden_slots] + # The total number of slots in all of the pages in the eden heap. + # [heap_tomb_pages] + # The number of pages in the tomb heap. The tomb heap only contains pages + # that do not have any live objects. + # [heap_tomb_slots] + # The total number of slots in all of the pages in the tomb heap. + # [total_allocated_pages] + # The total number of pages that have been allocated in the heap. + # [total_freed_pages] + # The total number of pages that have been freed and released back to the + # system in the heap. + # [force_major_gc_count] + # The number of times major garbage collection cycles this size pool has + # forced to start due to running out of free slots. + # def self.stat_heap heap_name = nil, hash_or_key = nil Primitive.gc_stat_heap heap_name, hash_or_key end From 2f57db6c778f18a6967b8d7bcca33593fa8f013b Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 14 Aug 2023 14:08:31 -0400 Subject: [PATCH 033/158] [DOC] Rename "memory pool" to "heap" --- gc.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/gc.rb b/gc.rb index 5f9940b4d61e06..4803a844eeb615 100644 --- a/gc.rb +++ b/gc.rb @@ -196,19 +196,18 @@ def self.stat hash_or_key = nil # GC.stat_heap(heap_name, hash) -> Hash # GC.stat_heap(heap_name, :key) -> Numeric # - # Returns information for memory pools in the \GC. + # Returns information for heaps in the \GC. # # If the first optional argument, +heap_name+, is passed in and not +nil+, it - # returns a +Hash+ containing information about the particular memory pool. - # Otherwise, it will return a +Hash+ with memory pool names as keys and - # a +Hash+ containing information about the memory pool as values. + # returns a +Hash+ containing information about the particular heap. + # Otherwise, it will return a +Hash+ with heap names as keys and + # a +Hash+ containing information about the heap as values. # # If the second optional argument, +hash_or_key+, is given as +Hash+, it will # be overwritten and returned. This is intended to avoid the probe effect. # # If both optional arguments are passed in and the second optional argument is - # a symbol, it will return a +Numeric+ of the value for the particular memory - # pool. + # a symbol, it will return a +Numeric+ of the value for the particular heap. # # On CRuby, +heap_name+ is of the type +Integer+ but may be of type +String+ # on other implementations. @@ -243,8 +242,8 @@ def self.stat hash_or_key = nil # The total number of pages that have been freed and released back to the # system in the heap. # [force_major_gc_count] - # The number of times major garbage collection cycles this size pool has - # forced to start due to running out of free slots. + # The number of times major garbage collection cycles this heap has forced + # to start due to running out of free slots. # def self.stat_heap heap_name = nil, hash_or_key = nil Primitive.gc_stat_heap heap_name, hash_or_key From 9acc73d7c583649240906b079c270e6ce1d8c50f Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 15 Aug 2023 10:08:48 -0400 Subject: [PATCH 034/158] YJIT: Optional parameter rework and bugfix (#8220) * YJIT: Fix splatting empty array with rest param * YJIT: Rework optional parameter handling to fix corner case The old code had a few unintuitive parts. The starting PC of the callee was set in different places; `num_param`, which one would assume to be static for a particular callee seemingly tallied to different amounts depending on the what the caller passed; `opts_filled_with_splat` was greater than zero even when the opts were not filled by items in the splat array. Functionally, the bits that lets the callee know which keyword parameters are unspecified were not passed properly when there are optional parameters and a rest parameter, and then optional parameters are all filled. Make `num_param` non-mut and use parameter information in the callee iseq as-is. Move local variable nil fill and placing of the rest array out of `gen_push_frame()` as they are only ever relevant for iseq calls. Always place the rest array at `lead_num + opt_num` to fix the previously buggy situation. * YJIT: Compile splat calls to iseqs with rest params Test interactions with optional parameters. --- bootstraptest/test_yjit.rb | 54 +++++++ yjit/src/codegen.rs | 286 ++++++++++++++++++------------------- 2 files changed, 197 insertions(+), 143 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index d87454c38c5436..196fa454ff437b 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -1,3 +1,57 @@ +# test splat filling required and feeding rest +assert_equal '[0, 1, 2, [3, 4]]', %q{ + public def lead_rest(a, b, *rest) + [self, a, b, rest] + end + + def call(args) = 0.lead_rest(*args) + + call([1, 2, 3, 4]) +} + +# test missing opts are nil initialized +assert_equal '[[0, 1, nil, 3], [0, 1, nil, 3], [0, 1, nil, 3, []], [0, 1, nil, 3, []]]', %q{ + public def lead_opts(a, b=binding.local_variable_get(:c), c=3) + [self, a, b, c] + end + + public def opts_rest(a=raise, b=binding.local_variable_get(:c), c=3, *rest) + [self, a, b, c, rest] + end + + def call(args) + [ + 0.lead_opts(1), + 0.lead_opts(*args), + + 0.opts_rest(1), + 0.opts_rest(*args), + ] + end + + call([1]) +} + +# test filled optionals with unspecified keyword param +assert_equal 'ok', %q{ + def opt_rest_opt_kw(_=1, *, k: :ok) = k + + def call = opt_rest_opt_kw(0) + + call +} + +# test splat empty array with rest param +assert_equal '[0, 1, 2, []]', %q{ + public def foo(a=1, b=2, *rest) + [self, a, b, rest] + end + + def call(args) = 0.foo(*args) + + call([]) +} + # Regression test for yielding with autosplat to block with # optional parameters. https://github.com/Shopify/yjit/issues/313 assert_equal '[:a, :b, :a, :b]', %q{ diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 11d70a3e6b343c..919e1662b820c0 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5011,7 +5011,6 @@ struct ControlFrame { frame_type: u32, specval: SpecVal, cme: *const rb_callable_method_entry_t, - local_size: i32 } // Codegen performing a similar (but not identical) function to vm_push_frame @@ -5034,10 +5033,7 @@ fn gen_push_frame( asm: &mut Assembler, set_sp_cfp: bool, // if true CFP and SP will be switched to the callee frame: ControlFrame, - rest_arg: Option<(i32, Opnd)>, ) { - assert!(frame.local_size >= 0); - let sp = frame.sp; asm.comment("push cme, specval, frame type"); @@ -5127,27 +5123,6 @@ fn gen_push_frame( asm.mov(cfp_opnd(RUBY_OFFSET_CFP_SELF), frame.recv); asm.mov(cfp_opnd(RUBY_OFFSET_CFP_BLOCK_CODE), 0.into()); - // This Qnil fill snippet potentially requires 2 more registers on Arm, one for Qnil and - // another for calculating the address in case there are a lot of local variables. So doing - // this after releasing the register for specval and the receiver to avoid register spill. - let num_locals = frame.local_size; - if num_locals > 0 { - asm.comment("initialize locals"); - - // Initialize local variables to Qnil - for i in 0..num_locals { - let offs = SIZEOF_VALUE_I32 * (i - num_locals - 3); - asm.store(Opnd::mem(64, sp, offs), Qnil.into()); - } - } - - if let Some((opts_missing, rest_arg)) = rest_arg { - // We want to set the rest_param just after the optional arguments - let index = opts_missing - num_locals - 3; - let offset = SIZEOF_VALUE_I32 * index; - asm.store(Opnd::mem(64, sp, offset), rest_arg); - } - // Spill stack temps to let the callee use them (must be done before changing SP) asm.spill_temps(); @@ -5379,8 +5354,7 @@ fn gen_send_cfunc( None // Leave PC uninitialized as cfuncs shouldn't read it }, iseq: None, - local_size: 0, - }, None); + }); if !kw_arg.is_null() { // Build a hash from all kwargs passed @@ -5523,6 +5497,11 @@ fn move_rest_args_to_stack(array: Opnd, num_args: u32, asm: &mut Assembler) { asm.cmp(array_len_opnd, num_args.into()); asm.jl(Target::side_exit(Counter::guard_send_iseq_has_rest_and_splat_not_equal)); + // Unused operands cause the backend to panic + if num_args == 0 { + return; + } + asm.comment("Push arguments from array"); // Load the address of the embedded array @@ -5589,7 +5568,7 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) { ); let array_len_opnd = asm.csel_nz(emb_len_opnd, array_len_opnd); - asm.comment("Side exit if length doesn't not equal remaining args"); + asm.comment("Guard for expected splat length"); asm.cmp(array_len_opnd, required_args.into()); asm.jne(Target::side_exit(Counter::guard_send_splatarray_length_not_equal)); @@ -5693,19 +5672,28 @@ fn gen_send_iseq( argc: i32, captured_opnd: Option, ) -> Option { + // Argument count. We will change this as we gather values from + // sources to satisfy the callee's parameters. To help make sense + // of changes, note that: + // - Parameters syntactically on the left have lower addresses. + // For example, all the lead (required) and optional parameters + // have lower addresses than the rest parameter array. + // - The larger the index one passes to Assembler::stack_opnd(), + // the *lower* the address. let mut argc = argc; - // When you have keyword arguments, there is an extra object that gets - // placed on the stack the represents a bitmap of the keywords that were not - // specified at the call site. We need to keep track of the fact that this - // value is present on the stack in order to properly set up the callee's - // stack pointer. + // Iseqs with keyword parameters have a hidden, unnamed parameter local + // that the callee could use to know which keywords are unspecified + // (see the `checkkeyword` instruction and check `ruby --dump=insn -e 'def foo(k:itself)=k'`). + // We always need to set up this local if the call goes through. let doing_kw_call = unsafe { get_iseq_flags_has_kw(iseq) }; let supplying_kws = unsafe { vm_ci_flag(ci) & VM_CALL_KWARG } != 0; let iseq_has_rest = unsafe { get_iseq_flags_has_rest(iseq) }; + let iseq_has_block_param = unsafe { get_iseq_flags_has_block(iseq) }; - // For computing number of locals to set up for the callee - let mut num_params = unsafe { get_iseq_body_param_size(iseq) }; + // For computing offsets to callee locals + let num_params = unsafe { get_iseq_body_param_size(iseq) }; + let num_locals = unsafe { get_iseq_body_local_table_size(iseq) as i32 }; let mut start_pc_offset: u16 = 0; let required_num = unsafe { get_iseq_body_param_lead_num(iseq) }; @@ -5722,7 +5710,7 @@ fn gen_send_iseq( // Arity handling and optional parameter setup let mut opts_filled = argc - required_num - kw_arg_num; let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) }; - // We have a rest argument so there could be more args + // We have a rest parameter so there could be more args // than are required + optional. Those will go in rest. // So we cap ops_filled at opt_num. if iseq_has_rest { @@ -5744,7 +5732,6 @@ fn gen_send_iseq( exit_if_has_kwrest(asm, iseq)?; exit_if_splat_and_ruby2_keywords(asm, jit, flags)?; exit_if_has_rest_and_captured(asm, iseq_has_rest, captured_opnd)?; - exit_if_has_rest_and_splat(asm, iseq_has_rest, flags)?; exit_if_has_rest_and_supplying_kws(asm, iseq_has_rest, iseq, supplying_kws)?; exit_if_supplying_kw_and_has_no_kw(asm, supplying_kws, iseq)?; exit_if_supplying_kws_and_accept_no_kwargs(asm, supplying_kws, iseq)?; @@ -5756,9 +5743,9 @@ fn gen_send_iseq( exit_if_unsupported_block_arg_type(asm, block_arg_type)?; // Block parameter handling. This mirrors setup_parameters_complex(). - if unsafe { get_iseq_flags_has_block(iseq) } { + if iseq_has_block_param { if unsafe { get_iseq_body_local_iseq(iseq) == iseq } { - num_params -= 1; + // Do nothing } else { // In this case (param.flags.has_block && local_iseq != iseq), // the block argument is setup as a local variable and requires @@ -5768,15 +5755,6 @@ fn gen_send_iseq( } } - // We will handle splat case later - if opt_num > 0 && flags & VM_CALL_ARGS_SPLAT == 0 { - num_params -= opts_missing as u32; - unsafe { - let opt_table = get_iseq_body_param_opt_table(iseq); - start_pc_offset = (*opt_table.offset(opts_filled as isize)).try_into().unwrap(); - } - } - if doing_kw_call { // Here we're calling a method with keyword arguments and specifying // keyword arguments at this call site. @@ -5910,40 +5888,32 @@ fn gen_send_iseq( None }; - // If we have a rest, optional arguments, and a splat - // some of those splatted args will end up filling the - // optional arguments and some will potentially end up - // in the rest. This calculates how many are filled - // by the splat. - let opts_filled_with_splat: Option = { - if iseq_has_rest && opt_num > 0 { - splat_array_length.map(|len| { - let num_args = (argc - 1) + len as i32; - if num_args >= required_num { - min(num_args - required_num, opt_num) - } else { - 0 - } - }) + // Adjust `opts_filled` and `opts_missing` taking + // into account the size of the splat expansion. + if let Some(len) = splat_array_length { + assert_eq!(kw_arg_num, 0); // Due to exit_if_doing_kw_and_splat(). + // Simplifies calculation below. + let num_args = (argc - 1) + len as i32; + + opts_filled = if num_args >= required_num { + min(num_args - required_num, opt_num) } else { - None - } - }; + 0 + }; + opts_missing = opt_num - opts_filled; + } - // If we have optional arguments filled by the splat (see comment above) - // we need to set a few variables concerning optional arguments - // to their correct values, as well as set the pc_offset. - if let Some(filled) = opts_filled_with_splat { - opts_missing = opt_num - filled; - opts_filled = filled; - num_params -= opts_missing as u32; + assert_eq!(opts_missing + opts_filled, opt_num); + assert!(opts_filled >= 0); - // We are going to jump to the correct offset based on how many optional - // params are remaining. + // ISeq with optional paramters start at different + // locations depending on the number of optionals given. + if opt_num > 0 { + assert!(opts_filled >= 0); unsafe { let opt_table = get_iseq_body_param_opt_table(iseq); - start_pc_offset = (*opt_table.offset(filled as isize)).try_into().unwrap(); - }; + start_pc_offset = opt_table.offset(opts_filled as isize).read().try_into().unwrap(); + } } // We will not have None from here. You can use stack_pop / stack_pop. @@ -6004,9 +5974,6 @@ fn gen_send_iseq( } } - // Number of locals that are not parameters - let num_locals = unsafe { get_iseq_body_local_table_size(iseq) as i32 } - (num_params as i32) + if iseq_has_rest && opt_num != 0 { 1 } else { 0 }; - // Stack overflow check // Note that vm_push_frame checks it against a decremented cfp, hence the multiply by 2. // #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) @@ -6020,38 +5987,21 @@ fn gen_send_iseq( // push_splat_args does stack manipulation so we can no longer side exit if let Some(array_length) = splat_array_length { - let remaining_opt = (opt_num as u32 + required_num as u32).saturating_sub(array_length + (argc as u32 - 1)); - if !iseq_has_rest { - if opt_num > 0 { - // We are going to jump to the correct offset based on how many optional - // params are remaining. - unsafe { - let opt_table = get_iseq_body_param_opt_table(iseq); - let offset = (opt_num - remaining_opt as i32) as isize; - start_pc_offset = (*opt_table.offset(offset)).try_into().unwrap(); - }; - } - - // We are going to assume that the splat fills - // all the remaining arguments. In the generated code - // we test if this is true and if not side exit. - argc = argc - 1 + array_length as i32 + remaining_opt as i32; + // Speculate that future splats will be done with + // an array that has the same length. We will insert guards. + argc = argc - 1 + array_length as i32; if argc + asm.ctx.get_stack_size() as i32 > MAX_SPLAT_LENGTH { gen_counter_incr(asm, Counter::send_splat_too_long); return None; } push_splat_args(array_length, asm); - - for _ in 0..remaining_opt { - // We need to push nil for the optional arguments - let stack_ret = asm.stack_push(Type::Unknown); - asm.mov(stack_ret, Qnil.into()); - } } } // This is a .send call and we need to adjust the stack + // TODO: This can be more efficient if we do it before + // extracting from the splat array above. if flags & VM_CALL_OPT_SEND != 0 { handle_opt_send_shift_stack(asm, argc); } @@ -6061,20 +6011,24 @@ fn gen_send_iseq( jit_save_pc(jit, asm); gen_save_sp(asm); - if flags & VM_CALL_ARGS_SPLAT != 0 { + let rest_param_array = if flags & VM_CALL_ARGS_SPLAT != 0 { let non_rest_arg_count = argc - 1; // We start by dupping the array because someone else might have - // a reference to it. + // a reference to it. This also normalizes to an ::Array instance. let array = asm.stack_pop(1); let array = asm.ccall( rb_ary_dup as *const u8, vec![array], ); - if non_rest_arg_count > required_num + opt_num { + // This is the end stack state of all `non_rest_arg_count` situations below + argc = required_num + opts_filled; + + if non_rest_arg_count > required_num + opt_num { // If we have more arguments than required, we need to prepend // the items from the stack onto the array. - let diff = (non_rest_arg_count - (required_num + opts_filled_with_splat.unwrap_or(0))) as u32; + let diff: u32 = (non_rest_arg_count - (required_num + opt_num)) + .try_into().unwrap(); // diff is >0 so no need to worry about null pointer asm.comment("load pointer to array elements"); @@ -6089,37 +6043,35 @@ fn gen_send_iseq( ); asm.stack_pop(diff as usize); - let stack_ret = asm.stack_push(Type::TArray); - asm.mov(stack_ret, array); - // We now should have the required arguments - // and an array of all the rest arguments - argc = required_num + opts_filled_with_splat.unwrap_or(0) + 1; + array } else if non_rest_arg_count < required_num + opt_num { // If we have fewer arguments than required, we need to take some // from the array and move them to the stack. + asm.comment("take items from splat array"); + + let diff: u32 = (required_num - non_rest_arg_count + opts_filled) + .try_into().unwrap(); - let diff = (required_num - non_rest_arg_count + opts_filled_with_splat.unwrap_or(0)) as u32; // This moves the arguments onto the stack. But it doesn't modify the array. move_rest_args_to_stack(array, diff, asm); // We will now slice the array to give us a new array of the correct size - let ret = asm.ccall(rb_yjit_rb_ary_subseq_length as *const u8, vec![array, Opnd::UImm(diff as u64)]); - let stack_ret = asm.stack_push(Type::TArray); - asm.mov(stack_ret, ret); + let sliced = asm.ccall(rb_yjit_rb_ary_subseq_length as *const u8, vec![array, Opnd::UImm(diff as u64)]); - // We now should have the required arguments - // and an array of all the rest arguments - argc = required_num + opts_filled_with_splat.unwrap_or(0) + 1; + sliced } else { // The arguments are equal so we can just push to the stack + asm.comment("same length for splat array and rest param"); assert!(non_rest_arg_count == required_num + opt_num); - let stack_ret = asm.stack_push(Type::TArray); - asm.mov(stack_ret, array); + + array } } else { + asm.comment("rest parameter without splat"); + assert!(argc >= required_num); let n = (argc - required_num - opts_filled) as u32; - argc = required_num + opts_filled + 1; + argc = required_num + opts_filled; // If n is 0, then elts is never going to be read, so we can just pass null let values_ptr = if n == 0 { Opnd::UImm(0) @@ -6139,9 +6091,31 @@ fn gen_send_iseq( ] ); asm.stack_pop(n.as_usize()); - let stack_ret = asm.stack_push(Type::CArray); - asm.mov(stack_ret, new_ary); - } + + new_ary + }; + + // Find where to put the rest parameter array + let rest_param = if opts_missing == 0 { + // All optionals are filled, the rest param goes at the top of the stack + argc += 1; + asm.stack_push(Type::CArray) + } else { + // The top of the stack will be a missing optional, but the rest + // parameter needs to be placed after all the missing optionals. + // Place it using a stack operand with a negative stack index. + // (Higher magnitude negative stack index have higher address.) + assert!(opts_missing > 0); + // The argument deepest in the stack will be the 0th local in the callee. + let callee_locals_base = argc - 1; + let rest_param_stack_idx = callee_locals_base - required_num - opt_num; + assert!(rest_param_stack_idx < 0); + asm.stack_opnd(rest_param_stack_idx) + }; + // Store rest param to memory to avoid register shuffle as + // we won't be reading it for the remainder of the block. + asm.ctx.dealloc_temp_reg(rest_param.stack_idx()); + asm.store(rest_param, rest_param_array); } if doing_kw_call { @@ -6311,16 +6285,47 @@ fn gen_send_iseq( argc = lead_num; } - // If we have a rest param and optional parameters, - // we don't actually pass the rest parameter as an argument, - // instead we set its value in the callee's locals - let rest_param = if iseq_has_rest && opt_num != 0 { - argc -= 1; - let top = asm.stack_pop(1); - Some((opts_missing as i32, asm.load(top))) - } else { - None - }; + fn nil_fill(comment: &'static str, fill_range: std::ops::Range, asm: &mut Assembler) { + if fill_range.is_empty() { + return; + } + + asm.comment(comment); + for i in fill_range { + let value_slot = asm.ctx.sp_opnd(i * SIZEOF_VALUE as isize); + asm.store(value_slot, Qnil.into()); + } + } + + // Nil-initialize missing optional parameters + nil_fill( + "nil-initialize missing optionals", + { + let begin = -(argc as isize) + required_num as isize + opts_filled as isize; + let end = -(argc as isize) + required_num as isize + opt_num as isize; + + begin..end + }, + asm + ); + // Nil-initialize the block parameter. It's the last parameter local + if iseq_has_block_param { + let block_param = asm.ctx.sp_opnd( + SIZEOF_VALUE as isize * (-(argc as isize) + num_params as isize - 1) + ); + asm.store(block_param, Qnil.into()); + } + // Nil-initialize non-parameter locals + nil_fill( + "nil-initialize locals", + { + let begin = -(argc as isize) + num_params as isize; + let end = -(argc as isize) + num_locals as isize; + + begin..end + }, + asm + ); // Points to the receiver operand on the stack unless a captured environment is used let recv = match captured_opnd { @@ -6339,8 +6344,9 @@ fn gen_send_iseq( jit_save_pc(jit, asm); // Adjust the callee's stack pointer - let offs = - (SIZEOF_VALUE as isize) * (3 + (num_locals as isize) + if doing_kw_call { 1 } else { 0 }); + let offs = (SIZEOF_VALUE as isize) * ( + -(argc as isize) + num_locals as isize + VM_ENV_DATA_SIZE as isize + ); let callee_sp = asm.lea(asm.ctx.sp_opnd(offs)); let specval = if let Some(prev_ep) = prev_ep { @@ -6367,8 +6373,7 @@ fn gen_send_iseq( sp: callee_sp, iseq: Some(iseq), pc: None, // We are calling into jitted code, which will set the PC as necessary - local_size: num_locals - }, rest_param); + }); // No need to set cfp->pc since the callee sets it whenever calling into routines // that could look at it through jit_save_pc(). @@ -6487,11 +6492,6 @@ fn exit_if_has_rest_and_captured(asm: &mut Assembler, iseq_has_rest: bool, captu exit_if(asm, iseq_has_rest && captured_opnd.is_some(), Counter::send_iseq_has_rest_and_captured) } -#[must_use] -fn exit_if_has_rest_and_splat( asm: &mut Assembler, iseq_has_rest: bool, flags: u32) -> Option<()> { - exit_if(asm, iseq_has_rest && flags & VM_CALL_ARGS_SPLAT != 0, Counter::send_iseq_has_rest_and_splat) -} - #[must_use] fn exit_if_has_rest_and_supplying_kws(asm: &mut Assembler, iseq_has_rest: bool, iseq: *const rb_iseq_t, supplying_kws: bool) -> Option<()> { exit_if( From b76c2ec0052afc303e254c1e748c2c2a585d6ad5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 14 Aug 2023 22:28:19 +0900 Subject: [PATCH 035/158] Use `::` form workflow commands --- .github/workflows/mingw.yml | 8 ++++---- defs/gmake.mk | 5 +++-- tool/test-bundled-gems.rb | 5 +++-- win32/Makefile.sub | 5 +++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index b7387d0fcf23ce..0136c7bd2d6836 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -78,9 +78,9 @@ jobs: mv /c/Windows/System32/libssl-1_1-x64.dll /c/Windows/System32/libssl-1_1-x64.dll_ result=true for e in gcc.exe ragel.exe make.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do - echo '##['group']'$'\033[93m'$e$'\033[m' + echo ::group::$'\033[93m'$e$'\033[m' where $e || result=false - echo '##['endgroup']' + echo ::endgroup:: done $result working-directory: @@ -91,9 +91,9 @@ jobs: result=true for e in gcc ragel make "openssl version"; do case "$e" in *" "*) ;; *) e="$e --version";; esac - echo '##['group']'$'\033[93m'$e$'\033[m' + echo ::group::$'\033[93m'$e$'\033[m' $e || result=false - echo '##['endgroup']' + echo ::endgroup:: done $result working-directory: diff --git a/defs/gmake.mk b/defs/gmake.mk index 9042b8ad120f3d..bc1ef9b79c2651 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -8,8 +8,9 @@ MSPECOPT += $(if $(filter -j%,$(MFLAGS)),-j) nproc = $(subst -j,,$(filter -j%,$(MFLAGS))) ifeq ($(GITHUB_ACTIONS),true) -override ACTIONS_GROUP = @echo "\#\#[group]$(patsubst yes-%,%,$@)" -override ACTIONS_ENDGROUP = @echo "\#\#[endgroup]" +# 93(bright yellow) is copied from .github/workflows/mingw.yml +override ACTIONS_GROUP = @echo "::group::$(@:yes-%=%)" +override ACTIONS_ENDGROUP = @echo "::endgroup::" endif ifneq ($(filter darwin%,$(target_os)),) diff --git a/tool/test-bundled-gems.rb b/tool/test-bundled-gems.rb index 07b7e310421fe4..9721d2d908ebf3 100644 --- a/tool/test-bundled-gems.rb +++ b/tool/test-bundled-gems.rb @@ -23,7 +23,8 @@ next if /^\s*(?:#|$)/ =~ line gem = line.split.first next if ARGV.any? {|pat| !File.fnmatch?(pat, gem)} - puts "#{github_actions ? "##[group]" : "\n"}Testing the #{gem} gem" + # 93(bright yellow) is copied from .github/workflows/mingw.yml + puts "#{github_actions ? "::group::\e\[93m" : "\n"}Testing the #{gem} gem#{github_actions ? "\e\[m" : ""}" test_command = "#{ruby} -C #{gem_dir}/src/#{gem} #{rake} test" first_timeout = 600 # 10min @@ -88,7 +89,7 @@ break end - print "##[endgroup]\n" if github_actions + print "::endgroup::\n" if github_actions unless $?.success? mesg = "Tests failed " + diff --git a/win32/Makefile.sub b/win32/Makefile.sub index e258e0388b15ea..feb7bfd2b514e3 100644 --- a/win32/Makefile.sub +++ b/win32/Makefile.sub @@ -547,8 +547,9 @@ GOLF_PRELUDE_C = golf_prelude.c RBCONFIG = ./.rbconfig.time !if "$(GITHUB_ACTIONS)" == "true" -ACTIONS_GROUP = @echo ^#^#[group]$(@:yes-=) -ACTIONS_ENDGROUP = @echo ^#^#[endgroup] +# 93(bright yellow) is copied from .github/workflows/mingw.yml +ACTIONS_GROUP = @echo ::group::$(@:yes-=) +ACTIONS_ENDGROUP = @echo ::endgroup:: !else ACTIONS_GROUP = @:: $(empty) ACTIONS_ENDGROUP = @:: From 6066f8d337977add0fae53aeebd14b045be2807f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 15 Aug 2023 20:05:22 +0900 Subject: [PATCH 036/158] Fix a typo to suppress updating rbconfig.rb during `make up` --- .github/actions/setup/directories/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index c4d64ee7eab714..3890c4d9dc1b26 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -93,7 +93,7 @@ runs: working-directory: ${{ inputs.srcdir }} run: | touch config.status - touch rbconfig.time + touch .rbconfig.time sed -f tool/prereq.status template/Makefile.in common.mk > Makefile make up From d9d4ae511a692568af4638e3fb88dbfdcbcba19b Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 15 Aug 2023 18:31:37 +0900 Subject: [PATCH 037/158] Group configure outputs on GitHub Actions --- configure.ac | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 0b01430db17ea7..af3ec862623958 100644 --- a/configure.ac +++ b/configure.ac @@ -47,11 +47,22 @@ m4_include([tool/m4/ruby_universal_arch.m4])dnl m4_include([tool/m4/ruby_wasm_tools.m4])dnl m4_include([tool/m4/ruby_werror_flag.m4])dnl +AS_IF([test "x${GITHUB_ACTIONS}" = xtrue], +[AC_REQUIRE([_COLORIZE_RESULT_PREPARE])dnl +dnl 93(bright yellow) is copied from .github/workflows/mingw.yml + begin_group() { AS_ECHO(["::group::@<:@93m$[]1@<:@m"]);} + end_group() { AS_ECHO(["::endgroup::"]);} +], +[dnl + begin_group() { :;} + end_group() { :;} +]) + AC_ARG_VAR([cflags], [additional CFLAGS (ignored when CFLAGS is given)])dnl AC_ARG_VAR([cppflags], [additional CPPFLAGS (ignored when CPPFLAGS is given)])dnl AC_ARG_VAR([cxxflags], [additional CXXFLAGS (ignored when CXXFLAGS is given)])dnl -: "environment section" && { +[begin]_group "environment section" && { HAVE_BASERUBY=yes BASERUBY_VERSION= AC_ARG_WITH(baseruby, @@ -591,7 +602,7 @@ AC_MSG_RESULT([$CHDIR]) AC_SUBST(CHDIR) } -: "compiler section" && { +[begin]_group "compiler section" && { RUBY_WERROR_FLAG([ AC_MSG_CHECKING([whether CFLAGS is valid]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], @@ -985,7 +996,7 @@ AS_IF([test "$rb_cv_have_stmt_and_decl_in_expr" = yes], [ AC_DEFINE(HAVE_STMT_AND_DECL_IN_EXPR) ]) -: "header and library section" && { +[begin]_group "header and library section" && { AC_ARG_WITH(winnt-ver, AS_HELP_STRING([--with-winnt-ver=0xXXXX], [target Windows NT version (default to 0x0600)]), [with_winnt_ver="$withval"], [with_winnt_ver="0x0600"]) @@ -2913,7 +2924,7 @@ AS_IF([test "x$ac_cv_func_ioctl" = xyes], [ } -: "runtime section" && { +[begin]_group "runtime section" && { dnl wheather use dln_a_out or not AC_ARG_WITH(dln-a-out, AS_HELP_STRING([--with-dln-a-out], [dln_a_out is deprecated]), @@ -3702,7 +3713,7 @@ AS_IF([test x"$gcov" = xyes], [ RUBY_SETJMP_TYPE } -: "build section" && { +[begin]_group "build section" && { dnl build rdoc index if requested RDOCTARGET="" CAPITARGET="" @@ -4110,8 +4121,10 @@ AS_IF([test "${universal_binary-no}" = yes ], [ const char arch[[]] = __ARCHITECTURE__;]], [[puts(arch);]])], [rb_cv_architecture_available=yes], [rb_cv_architecture_available=no])) ]) +} : ${RJIT_LDSHARED=`echo "$LDSHARED" | sed ['s|\$(LD)|'"${LD}"'|g;s|\$(CC)|$(RJIT_CC)|g']`} +[end]_group MAINLIBS="$LIBS" LIBS=$ORIG_LIBS @@ -4550,7 +4563,6 @@ AC_SUBST(DESTDIR) AC_OUTPUT } -} AS_IF([test "$silent" = yes], [], [ AS_IF([${FOLD+:} false], [], [ From 8c5b9ebf7144af73cf52209b73b849c078133dff Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Tue, 15 Aug 2023 13:43:58 -0500 Subject: [PATCH 038/158] [DOC] Improve doc guide compliance (#8221) --- array.rb | 4 ++-- enum.c | 36 ++++++++++++++++++------------------ object.c | 2 +- string.rb | 2 +- struct.c | 2 +- time.c | 2 +- timev.rb | 2 +- weakmap.c | 4 ++-- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/array.rb b/array.rb index 358b6a5d79ab37..d17f3742357613 100644 --- a/array.rb +++ b/array.rb @@ -81,7 +81,7 @@ def sample(n = (ary = false), random: Random) # # If +self+ is empty, returns +nil+. # - # When non-negative \Integer argument +n+ is given, + # When non-negative Integer argument +n+ is given, # returns the first +n+ elements in a new \Array: # # a = [:foo, 'bar', 2] @@ -125,7 +125,7 @@ def first n = unspecified = true # # If +self+ is empty, returns +nil+. # - # When non-negative \Integer argument +n+ is given, + # When non-negative Integer argument +n+ is given, # returns the last +n+ elements in a new \Array: # # a = [:foo, 'bar', 2] diff --git a/enum.c b/enum.c index 46fcb24cfd18ee..355170cc3ecb68 100644 --- a/enum.c +++ b/enum.c @@ -354,7 +354,7 @@ find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) * {foo: 0, bar: 1, baz: 2}.find {|key, value| key.start_with?('b') } # => [:bar, 1] * {foo: 0, bar: 1, baz: 2}.find(proc {[]}) {|key, value| key.start_with?('c') } # => [] * - * With no block given, returns an \Enumerator. + * With no block given, returns an Enumerator. * */ static VALUE @@ -424,7 +424,7 @@ find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) * ['a', 'b', 'c', 'b'].find_index {|element| element.start_with?('b') } # => 1 * {foo: 0, bar: 1, baz: 2}.find_index {|key, value| value > 1 } # => 2 * - * With no argument and no block given, returns an \Enumerator. + * With no argument and no block given, returns an Enumerator. * */ @@ -501,7 +501,7 @@ enum_size_over_p(VALUE obj, long n) * a = {foo: 0, bar: 1, baz: 2}.select {|key, value| key.start_with?('b') } * a # => {:bar=>1, :baz=>2} * - * With no block given, returns an \Enumerator. + * With no block given, returns an Enumerator. * * Related: #reject. */ @@ -543,7 +543,7 @@ filter_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) * (0..9).filter_map {|i| i * 2 if i.even? } # => [0, 4, 8, 12, 16] * {foo: 0, bar: 1, baz: 2}.filter_map {|key, value| key if value.even? } # => [:foo, :baz] * - * When no block given, returns an \Enumerator. + * When no block given, returns an Enumerator. * */ static VALUE @@ -584,7 +584,7 @@ reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) * (0..9).reject {|i| i * 2 if i.even? } # => [1, 3, 5, 7, 9] * {foo: 0, bar: 1, baz: 2}.reject {|key, value| key if value.odd? } # => {:foo=>0, :baz=>2} * - * When no block given, returns an \Enumerator. + * When no block given, returns an Enumerator. * * Related: #select. */ @@ -631,7 +631,7 @@ collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) * (0..4).map {|i| i*i } # => [0, 1, 4, 9, 16] * {foo: 0, bar: 1, baz: 2}.map {|key, value| value*2} # => [0, 2, 4] * - * With no block given, returns an \Enumerator. + * With no block given, returns an Enumerator. * */ static VALUE @@ -681,7 +681,7 @@ flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary)) * [[0, 1], [2, 3]].flat_map {|e| e + [100] } # => [0, 1, 100, 2, 3, 100] * {foo: 0, bar: 1, baz: 2}.flat_map {|key, value| [key, value] } # => [:foo, 0, :bar, 1, :baz, 2] * - * With no block given, returns an \Enumerator. + * With no block given, returns an Enumerator. * * Alias: #collect_concat. */ @@ -4905,7 +4905,7 @@ enum_compact(VALUE obj) * - #one?: Returns +true+ if exactly one element meets a specified criterion; +false+ otherwise. * - #count: Returns the count of elements, * based on an argument or block criterion, if given. - * - #tally: Returns a new \Hash containing the counts of occurrences of each element. + * - #tally: Returns a new Hash containing the counts of occurrences of each element. * * === Methods for Fetching * @@ -4926,20 +4926,20 @@ enum_compact(VALUE obj) * as determined by <=> or a given block. * - #max: Returns the elements whose values are largest among the elements, * as determined by <=> or a given block. - * - #minmax: Returns a 2-element \Array containing the smallest and largest elements. + * - #minmax: Returns a 2-element Array containing the smallest and largest elements. * - #min_by: Returns the smallest element, as determined by the given block. * - #max_by: Returns the largest element, as determined by the given block. * - #minmax_by: Returns the smallest and largest elements, as determined by the given block. * * Groups, slices, and partitions: * - * - #group_by: Returns a \Hash that partitions the elements into groups. + * - #group_by: Returns a Hash that partitions the elements into groups. * - #partition: Returns elements partitioned into two new Arrays, as determined by the given block. - * - #slice_after: Returns a new \Enumerator whose entries are a partition of +self+, + * - #slice_after: Returns a new Enumerator whose entries are a partition of +self+, based either on a given +object+ or a given block. - * - #slice_before: Returns a new \Enumerator whose entries are a partition of +self+, + * - #slice_before: Returns a new Enumerator whose entries are a partition of +self+, based either on a given +object+ or a given block. - * - #slice_when: Returns a new \Enumerator whose entries are a partition of +self+ + * - #slice_when: Returns a new Enumerator whose entries are a partition of +self+ based on the given block. * - #chunk: Returns elements organized into chunks as specified by the given block. * - #chunk_while: Returns elements organized into chunks as specified by the given block. @@ -5040,18 +5040,18 @@ enum_compact(VALUE obj) * * Virtually all methods in \Enumerable call method +#each+ in the including class: * - * - Hash#each yields the next key-value pair as a 2-element \Array. - * - Struct#each yields the next name-value pair as a 2-element \Array. + * - Hash#each yields the next key-value pair as a 2-element Array. + * - Struct#each yields the next name-value pair as a 2-element Array. * - For the other classes above, +#each+ yields the next object from the collection. * * == About the Examples * * The example code snippets for the \Enumerable methods: * - * - Always show the use of one or more \Array-like classes (often \Array itself). - * - Sometimes show the use of a \Hash-like class. + * - Always show the use of one or more Array-like classes (often Array itself). + * - Sometimes show the use of a Hash-like class. * For some methods, though, the usage would not make sense, - * and so it is not shown. Example: #tally would find exactly one of each \Hash entry. + * and so it is not shown. Example: #tally would find exactly one of each Hash entry. * */ diff --git a/object.c b/object.c index 45a571adacea35..70cb64eb850d17 100644 --- a/object.c +++ b/object.c @@ -4244,7 +4244,7 @@ f_sprintf(int c, const VALUE *v, VALUE _) * and frozen state. * - #define_singleton_method: Defines a singleton method in +self+ * for the given symbol method-name and block or proc. - * - #display: Prints +self+ to the given \IO stream or $stdout. + * - #display: Prints +self+ to the given IO stream or $stdout. * - #dup: Returns a shallow unfrozen copy of +self+. * - #enum_for (aliased as #to_enum): Returns an Enumerator for +self+ * using the using the given method, arguments, and block. diff --git a/string.rb b/string.rb index e1f55d17b4a3f7..e4de709dc59e6c 100644 --- a/string.rb +++ b/string.rb @@ -265,7 +265,7 @@ # # string[regexp, capture = 0] # -# When the \Regexp argument +regexp+ is given, +# When the Regexp argument +regexp+ is given, # and the +capture+ argument is 0, # the slice is the first matching substring found in +self+: # diff --git a/struct.c b/struct.c index c47d8d086bf619..b46fd88264e1c1 100644 --- a/struct.c +++ b/struct.c @@ -561,7 +561,7 @@ rb_struct_define_under(VALUE outer, const char *name, ...) * * Member Names * - * \Symbol arguments +member_names+ + * Symbol arguments +member_names+ * determines the members of the new subclass: * * Struct.new(:foo, :bar).members # => [:foo, :bar] diff --git a/time.c b/time.c index f4faaf3fcf11a3..617326f9961647 100644 --- a/time.c +++ b/time.c @@ -3637,7 +3637,7 @@ tmcmp(struct tm *a, struct tm *b) * Time.utc(Float(0.0), Rational(1, 1), 1.0, 0.0, 0.0, 0.0, 0.0) * # => 0000-01-01 00:00:00 UTC * - * - \String integers: + * - String integers: * * a = %w[0 1 1 0 0 0 0 0] * # => ["0", "1", "1", "0", "0", "0", "0", "0"] diff --git a/timev.rb b/timev.rb index 76d3ab70584dd2..e710dc699003e2 100644 --- a/timev.rb +++ b/timev.rb @@ -359,7 +359,7 @@ def self.at(time, subsec = false, unit = :microsecond, in: nil) # Time.new(Float(0.0), Rational(1, 1), 1.0, 0.0, 0.0, 0.0) # # => 0000-01-01 00:00:00 -0600 # - # - \String integers: + # - String integers: # # a = %w[0 1 1 0 0 0] # # => ["0", "1", "1", "0", "0", "0"] diff --git a/weakmap.c b/weakmap.c index 17883f05a44f9c..ef859f89e8350c 100644 --- a/weakmap.c +++ b/weakmap.c @@ -894,8 +894,8 @@ wkmap_clear(VALUE self) * call-seq: * map.inspect -> new_string * - * Returns a new \String containing informations about the map: - + * Returns a new String containing informations about the map: + * * m = ObjectSpace::WeakKeyMap.new * m[key] = value * m.inspect # => "#" From 0f94e653597dc2ae21ae39ac4c85266f3bb36ab6 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 14 Aug 2023 11:24:50 -0400 Subject: [PATCH 039/158] Add stat force_incremental_marking_finish_count This commit adds key force_incremental_marking_finish_count to GC.stat_heap. This statistic returns the number of times the size pool has forced incremental marking to finish due to running out of slots. --- gc.c | 5 +++++ gc.rb | 3 +++ test/ruby/test_gc.rb | 1 + 3 files changed, 9 insertions(+) diff --git a/gc.c b/gc.c index d2c5c52692fd25..0d650dbe68f79b 100644 --- a/gc.c +++ b/gc.c @@ -707,6 +707,7 @@ typedef struct rb_size_pool_struct { size_t total_allocated_pages; size_t total_freed_pages; size_t force_major_gc_count; + size_t force_incremental_marking_finish_count; /* Sweeping statistics */ size_t freed_slots; @@ -8504,6 +8505,7 @@ gc_marks_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t else { gc_report(2, objspace, "gc_marks_continue: no more pooled pages (stack depth: %"PRIdSIZE").\n", mark_stack_size(&objspace->mark_stack)); + size_pool->force_incremental_marking_finish_count++; gc_marks_rest(objspace); } @@ -11182,6 +11184,7 @@ enum gc_stat_heap_sym { gc_stat_heap_sym_total_allocated_pages, gc_stat_heap_sym_total_freed_pages, gc_stat_heap_sym_force_major_gc_count, + gc_stat_heap_sym_force_incremental_marking_finish_count, gc_stat_heap_sym_last }; @@ -11201,6 +11204,7 @@ setup_gc_stat_heap_symbols(void) S(total_allocated_pages); S(total_freed_pages); S(force_major_gc_count); + S(force_incremental_marking_finish_count); #undef S } } @@ -11244,6 +11248,7 @@ gc_stat_heap_internal(int size_pool_idx, VALUE hash_or_sym) SET(total_allocated_pages, size_pool->total_allocated_pages); SET(total_freed_pages, size_pool->total_freed_pages); SET(force_major_gc_count, size_pool->force_major_gc_count); + SET(force_incremental_marking_finish_count, size_pool->force_incremental_marking_finish_count); #undef SET if (!NIL_P(key)) { /* matched key should return above */ diff --git a/gc.rb b/gc.rb index 4803a844eeb615..c3b104454cb715 100644 --- a/gc.rb +++ b/gc.rb @@ -244,6 +244,9 @@ def self.stat hash_or_key = nil # [force_major_gc_count] # The number of times major garbage collection cycles this heap has forced # to start due to running out of free slots. + # [force_incremental_marking_finish_count] + # The number of times this heap has forced incremental marking to complete + # due to running out of pooled slots. # def self.stat_heap heap_name = nil, hash_or_key = nil Primitive.gc_stat_heap heap_name, hash_or_key diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index 0cf57cb088feb8..aabdfc0cf8dc77 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -163,6 +163,7 @@ def test_stat_heap assert_operator stat_heap[:total_allocated_pages], :>=, 0 assert_operator stat_heap[:total_freed_pages], :>=, 0 assert_operator stat_heap[:force_major_gc_count], :>=, 0 + assert_operator stat_heap[:force_incremental_marking_finish_count], :>=, 0 end GC.stat_heap(0, stat_heap) From e6e23b92e3019e27471c9bf7a97db5f95e7a9a29 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 26 Jun 2023 22:04:24 -0700 Subject: [PATCH 040/158] [ruby/yarp] rust: Initial yarp-sys Still need to add more tests Update Cargo.toml; add README Switch yp_string_t_type variants to SNAKE_CASE Add unescape tests Add encoding callback tests Add pack_parse test Add diagnostic test Add comment test Add node tests Add string_list tests Add other string tests Add shared string test Add list tests Fixes for updated branch Run bundle install before running Rust tests Fix version test ci: Add proper config for rust-toolchain step for sanitizers ci: Fix tests, clippy Remove extra `bundle install`; run `bundle exec rake` Didn't realize `setup-ruby`'s `bundle-cache: true` runs `bundle install`. Remove `rake compile` from build.rs This is complicating CI for me; maybe we add it back later. Undo README formatting changes Fix UB in C callbacks Use slice+str instead of String for raw things Move bindings to bindings module Handle non-UTF-8 strings in paths rust ci: test with sanitizers; add -D warnings Update rust-bindings.yml Update Cargo.toml Don't need to compile extra crate_types PR changes Apply patch from @kddnewton Delete unescape_tests.rs Fix things after rebasing https://github.com/ruby/yarp/commit/273790e40b --- .github/workflows/rust-bindings.yml | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 .github/workflows/rust-bindings.yml diff --git a/.github/workflows/rust-bindings.yml b/.github/workflows/rust-bindings.yml new file mode 100644 index 00000000000000..80fa75bce50029 --- /dev/null +++ b/.github/workflows/rust-bindings.yml @@ -0,0 +1,101 @@ +--- +name: Rust Bindings + +on: + push: + paths: + - ".github/workflows/rust-bindings.yml" + - "include/" + - "src/" + - "rust/" + - "*akefile*" + branches: + - main + pull_request: + +env: + RUSTFLAGS: "-D warnings" + +jobs: + cargo-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: head + bundler-cache: true + - uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} + restore-keys: | + ${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }} + ${{ runner.os }}-cargo + - name: rake compile + run: bundle exec rake compile + - name: cargo test + working-directory: rust/yarp-sys + run: cargo test + + cargo-clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: head + bundler-cache: true + - uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} + restore-keys: | + ${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }} + ${{ runner.os }}-cargo + - name: rake compile + run: bundle exec rake compile + - name: cargo clippy + working-directory: rust/yarp-sys + run: cargo clippy --tests -- -W "clippy::pedantic" + + sanitizer-test: + name: Test with -Zsanitizer=${{ matrix.sanitizer }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sanitizer: [address, leak] + steps: + - uses: actions/checkout@v3 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: head + bundler-cache: true + - name: rake compile + run: bundle exec rake compile + - uses: dtolnay/rust-toolchain@nightly + with: + target: "x86_64-unknown-linux-gnu" + components: "rust-src" + - name: Test with sanitizer + env: + RUSTFLAGS: -Zsanitizer=${{ matrix.sanitizer }} + RUSTDOCFLAGS: -Zsanitizer=${{ matrix.sanitizer }} + # only needed by asan + ASAN_OPTIONS: detect_stack_use_after_return=1 + # Asan's leak detection occasionally complains + # about some small leaks if backtraces are captured, + # so ensure they're not + RUST_BACKTRACE: 0 + working-directory: rust/yarp-sys + run: cargo test -Zbuild-std --verbose --target=x86_64-unknown-linux-gnu From efd611ceb661a230f121797079376cdb4e831951 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 15 Aug 2023 13:54:13 -0700 Subject: [PATCH 041/158] Revert "[ruby/yarp] rust: Initial yarp-sys" This reverts commit e6e23b92e3019e27471c9bf7a97db5f95e7a9a29. It seems like it wasn't added for ruby/ruby. We could fix tool/sync_default_gems.rb to deal with this, but we have a pull request that changes that part now, so let me only revert this for now and revisit this after merging that pull request. --- .github/workflows/rust-bindings.yml | 101 ---------------------------- 1 file changed, 101 deletions(-) delete mode 100644 .github/workflows/rust-bindings.yml diff --git a/.github/workflows/rust-bindings.yml b/.github/workflows/rust-bindings.yml deleted file mode 100644 index 80fa75bce50029..00000000000000 --- a/.github/workflows/rust-bindings.yml +++ /dev/null @@ -1,101 +0,0 @@ ---- -name: Rust Bindings - -on: - push: - paths: - - ".github/workflows/rust-bindings.yml" - - "include/" - - "src/" - - "rust/" - - "*akefile*" - branches: - - main - pull_request: - -env: - RUSTFLAGS: "-D warnings" - -jobs: - cargo-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: head - bundler-cache: true - - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - restore-keys: | - ${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }} - ${{ runner.os }}-cargo - - name: rake compile - run: bundle exec rake compile - - name: cargo test - working-directory: rust/yarp-sys - run: cargo test - - cargo-clippy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: head - bundler-cache: true - - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - restore-keys: | - ${{ runner.os }}-cargo-${{ hashFiles('Cargo.toml') }} - ${{ runner.os }}-cargo - - name: rake compile - run: bundle exec rake compile - - name: cargo clippy - working-directory: rust/yarp-sys - run: cargo clippy --tests -- -W "clippy::pedantic" - - sanitizer-test: - name: Test with -Zsanitizer=${{ matrix.sanitizer }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - sanitizer: [address, leak] - steps: - - uses: actions/checkout@v3 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: head - bundler-cache: true - - name: rake compile - run: bundle exec rake compile - - uses: dtolnay/rust-toolchain@nightly - with: - target: "x86_64-unknown-linux-gnu" - components: "rust-src" - - name: Test with sanitizer - env: - RUSTFLAGS: -Zsanitizer=${{ matrix.sanitizer }} - RUSTDOCFLAGS: -Zsanitizer=${{ matrix.sanitizer }} - # only needed by asan - ASAN_OPTIONS: detect_stack_use_after_return=1 - # Asan's leak detection occasionally complains - # about some small leaks if backtraces are captured, - # so ensure they're not - RUST_BACKTRACE: 0 - working-directory: rust/yarp-sys - run: cargo test -Zbuild-std --verbose --target=x86_64-unknown-linux-gnu From 47b1a52826e5690969e26760d9d2536887f41f62 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Aug 2023 00:53:39 +0900 Subject: [PATCH 042/158] Split installation from build section --- configure.ac | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index af3ec862623958..2cc4e6beba4d6e 100644 --- a/configure.ac +++ b/configure.ac @@ -3713,7 +3713,7 @@ AS_IF([test x"$gcov" = xyes], [ RUBY_SETJMP_TYPE } -[begin]_group "build section" && { +[begin]_group "installation section" && { dnl build rdoc index if requested RDOCTARGET="" CAPITARGET="" @@ -3761,6 +3761,19 @@ AC_SUBST(CAPITARGET) AS_CASE(["$RDOCTARGET:$CAPITARGET"],[nodoc:nodoc],[INSTALLDOC=nodoc],[INSTALLDOC=all]) AC_SUBST(INSTALLDOC) +AC_ARG_ENABLE(install-static-library, + AS_HELP_STRING([--disable-install-static-library], [do not install static ruby library]), + [INSTALL_STATIC_LIBRARY=$enableval + AS_IF([test x"$enable_shared" = xno -a x"$INSTALL_STATIC_LIBRARY" = xno], + [AC_MSG_ERROR([must install either static or shared library])], + [])], + AS_IF([test x"$enable_shared" = xyes], + [INSTALL_STATIC_LIBRARY=no], + [INSTALL_STATIC_LIBRARY=yes])) +AC_SUBST(INSTALL_STATIC_LIBRARY) +} + +[begin]_group "JIT section" && { AC_CHECK_PROG(RUSTC, [rustc], [rustc], [no]) dnl no ac_tool_prefix dnl check if rustc is recent enough to build YJIT (rustc >= 1.58.0) @@ -3922,18 +3935,9 @@ AS_CASE(["$RJIT_SUPPORT"], ]) AC_SUBST(RJIT_SUPPORT) +} -AC_ARG_ENABLE(install-static-library, - AS_HELP_STRING([--disable-install-static-library], [do not install static ruby library]), - [INSTALL_STATIC_LIBRARY=$enableval - AS_IF([test x"$enable_shared" = xno -a x"$INSTALL_STATIC_LIBRARY" = xno], - [AC_MSG_ERROR([must install either static or shared library])], - [])], - AS_IF([test x"$enable_shared" = xyes], - [INSTALL_STATIC_LIBRARY=no], - [INSTALL_STATIC_LIBRARY=yes])) -AC_SUBST(INSTALL_STATIC_LIBRARY) - +[begin]_group "build section" && { AC_CACHE_CHECK([for prefix of external symbols], rb_cv_symbol_prefix, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[extern void conftest_external(void) {}]], [[]])],[ rb_cv_symbol_prefix=`$NM conftest.$ac_objext | From 8d985b1855d5d5dca88edce32625440a6c123a16 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 15 Aug 2023 17:07:17 -0700 Subject: [PATCH 043/158] Clarify the actual Visual Studio version [ci skip] --- .appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index ab8ac580ec301e..6865393b1aefb8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -26,8 +26,9 @@ environment: # is limited, and compatibility issues that happen only in newer versions are rare. # You may test some other stuff on GitHub Actions instead. - build: vs - vs: 120 + vs: 120 # Visual Studio 2013 ssl: OpenSSL-v111 + # The worker image name. This is NOT the Visual Studio version we're using here. APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 GEMS_FOR_TEST: "" RELINE_TEST_ENCODING: "UTF-8" From 0300ea5a6c8a7a49feed73318fc8a991aa89fcfc Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Sun, 13 Aug 2023 12:55:29 -0400 Subject: [PATCH 044/158] [ruby/net-http] Improve performance of HTTPHeader#content_type In the existing implementation, `main_type` and `sub_type` would end up being called multiple times potentially. Instead of doing that, save the result so it can be re-used. https://github.com/ruby/net-http/commit/179976f7ea --- lib/net/http/header.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb index b704860c906431..ec5552f04d2bce 100644 --- a/lib/net/http/header.rb +++ b/lib/net/http/header.rb @@ -699,10 +699,14 @@ def range_length # res.content_type # => "application/json" # def content_type - return nil unless main_type() - if sub_type() - then "#{main_type()}/#{sub_type()}" - else main_type() + main = main_type() + return nil unless main + + sub = sub_type() + if sub + "#{main}/#{sub}" + else + main end end From 8d04260acd8b6fba98867acc1a7e786495813fa0 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Fri, 11 Aug 2023 15:57:35 -0400 Subject: [PATCH 045/158] [ruby/net-http] turn on frozen strings for net/http/header https://github.com/ruby/net-http/commit/a5203c9f92 --- lib/net/http/header.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb index ec5552f04d2bce..6660c8075a4230 100644 --- a/lib/net/http/header.rb +++ b/lib/net/http/header.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # The \HTTPHeader module provides access to \HTTP headers. # From 2fbd8dca18a102cb3ffc5e7e6235c09fd0d04ba3 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Fri, 11 Aug 2023 18:02:57 -0400 Subject: [PATCH 046/158] [ruby/net-http] turn on frozen strings for net/http/generic_request https://github.com/ruby/net-http/commit/b92ade088d --- lib/net/http/generic_request.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/http/generic_request.rb b/lib/net/http/generic_request.rb index 8877cd04ae2c07..1f0d2e52c2019a 100644 --- a/lib/net/http/generic_request.rb +++ b/lib/net/http/generic_request.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # \HTTPGenericRequest is the parent of the Net::HTTPRequest class. # @@ -316,7 +316,7 @@ def encode_multipart_form_data(out, params, opt) boundary ||= SecureRandom.urlsafe_base64(40) chunked_p = chunked? - buf = '' + buf = String.new params.each do |key, value, h={}| key = quote_string(key, charset) filename = @@ -401,7 +401,7 @@ def write_header(sock, ver, path) if /[\r\n]/ =~ reqline raise ArgumentError, "A Request-Line must not contain CR or LF" end - buf = "" + buf = String.new buf << reqline << "\r\n" each_capitalized do |k,v| buf << "#{k}: #{v}\r\n" From 4165ec91d87ff1fcb41e312d896bea8a678c9bab Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Fri, 11 Aug 2023 19:04:18 -0400 Subject: [PATCH 047/158] [ruby/net-http] update net/http/response to be frozen string literal https://github.com/ruby/net-http/commit/dc3b4a75ca --- lib/net/http/response.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb index 1d83935c105960..ac465cc64a0457 100644 --- a/lib/net/http/response.rb +++ b/lib/net/http/response.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # This class is the base class for \Net::HTTP response classes. # @@ -273,7 +273,7 @@ def code_type #:nodoc: def error! #:nodoc: message = @code - message += ' ' + @message.dump if @message + message += " #{@message.dump}" if @message raise error_type().new(message, self) end @@ -648,7 +648,7 @@ def procdest(dest, block) if block Net::ReadAdapter.new(block) else - dest || '' + dest || String.new end end From 4d21134f3f1645ae2042d836e750ad267ee1551f Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Sat, 12 Aug 2023 12:19:50 -0400 Subject: [PATCH 048/158] [ruby/net-http] freeze rest of lib https://github.com/ruby/net-http/commit/455a74734a --- lib/net/http.rb | 2 +- lib/net/http/backward.rb | 2 +- lib/net/http/exceptions.rb | 2 +- lib/net/http/proxy_delta.rb | 2 +- lib/net/http/request.rb | 2 +- lib/net/http/requests.rb | 2 +- lib/net/https.rb | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/net/http.rb b/lib/net/http.rb index 89277ca49d86b9..e65a6005251f77 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # = net/http.rb # diff --git a/lib/net/http/backward.rb b/lib/net/http/backward.rb index 691e41e4f10547..b44577edbd2c6b 100644 --- a/lib/net/http/backward.rb +++ b/lib/net/http/backward.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # for backward compatibility # :enddoc: diff --git a/lib/net/http/exceptions.rb b/lib/net/http/exceptions.rb index 9c425cae165d06..ceec8f7b0a3822 100644 --- a/lib/net/http/exceptions.rb +++ b/lib/net/http/exceptions.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true module Net # Net::HTTP exception class. # You cannot use Net::HTTPExceptions directly; instead, you must use diff --git a/lib/net/http/proxy_delta.rb b/lib/net/http/proxy_delta.rb index a2f770ebdb1b09..e7d30def649e82 100644 --- a/lib/net/http/proxy_delta.rb +++ b/lib/net/http/proxy_delta.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true module Net::HTTP::ProxyDelta #:nodoc: internal use only private diff --git a/lib/net/http/request.rb b/lib/net/http/request.rb index e900b8a17ad8f6..4a138572e905f4 100644 --- a/lib/net/http/request.rb +++ b/lib/net/http/request.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # This class is the base class for \Net::HTTP request classes. # The class should not be used directly; diff --git a/lib/net/http/requests.rb b/lib/net/http/requests.rb index 96cedcabcc8ed4..5724164205e61b 100644 --- a/lib/net/http/requests.rb +++ b/lib/net/http/requests.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # HTTP/1.1 methods --- RFC2616 diff --git a/lib/net/https.rb b/lib/net/https.rb index d46721c82a582a..0f23e1fb135d38 100644 --- a/lib/net/https.rb +++ b/lib/net/https.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true =begin = net/https -- SSL/TLS enhancement for Net::HTTP. From 70da92cdf7ac75e071353c4551419ad02c284497 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Mon, 14 Aug 2023 11:17:00 -0400 Subject: [PATCH 049/158] [ruby/net-http] Fix on 2.7 https://github.com/ruby/net-http/commit/5194fd541e --- lib/net/http.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/http.rb b/lib/net/http.rb index e65a6005251f77..c05c5baa6cde45 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -1615,7 +1615,7 @@ def connect write_timeout: @write_timeout, continue_timeout: @continue_timeout, debug_output: @debug_output) - buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n" + buf = +"CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n" buf << "Host: #{@address}:#{@port}\r\n" if proxy_user credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0') From ea321a654d4b4fd6d56a1cdd6e117c62075898ee Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Mon, 14 Aug 2023 11:17:45 -0400 Subject: [PATCH 050/158] [ruby/net-http] use +'' everywhere https://github.com/ruby/net-http/commit/1077427152 --- lib/net/http/generic_request.rb | 4 ++-- lib/net/http/response.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/net/http/generic_request.rb b/lib/net/http/generic_request.rb index 1f0d2e52c2019a..9421535ceb2e45 100644 --- a/lib/net/http/generic_request.rb +++ b/lib/net/http/generic_request.rb @@ -316,7 +316,7 @@ def encode_multipart_form_data(out, params, opt) boundary ||= SecureRandom.urlsafe_base64(40) chunked_p = chunked? - buf = String.new + buf = +'' params.each do |key, value, h={}| key = quote_string(key, charset) filename = @@ -401,7 +401,7 @@ def write_header(sock, ver, path) if /[\r\n]/ =~ reqline raise ArgumentError, "A Request-Line must not contain CR or LF" end - buf = String.new + buf = +'' buf << reqline << "\r\n" each_capitalized do |k,v| buf << "#{k}: #{v}\r\n" diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb index ac465cc64a0457..27cdb5b4f6d284 100644 --- a/lib/net/http/response.rb +++ b/lib/net/http/response.rb @@ -648,7 +648,7 @@ def procdest(dest, block) if block Net::ReadAdapter.new(block) else - dest || String.new + dest || +'' end end From ae68a8df586e9f3b3211e9c174b7001e57ee6aee Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Tue, 15 Aug 2023 13:30:53 -0400 Subject: [PATCH 051/158] [ruby/net-http] Update lib/net/http/response.rb @natematykiewicz's suggestion to avoid a string allocation https://github.com/ruby/net-http/commit/925630f227 Co-authored-by: Nate Matykiewicz --- lib/net/http/response.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb index 27cdb5b4f6d284..192fa2c749c860 100644 --- a/lib/net/http/response.rb +++ b/lib/net/http/response.rb @@ -273,7 +273,7 @@ def code_type #:nodoc: def error! #:nodoc: message = @code - message += " #{@message.dump}" if @message + message = "#{message} #{@message.dump}" if @message raise error_type().new(message, self) end From af67ced3b0945e8ea67434f8e66ef1e602656438 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Tue, 15 Aug 2023 13:31:43 -0400 Subject: [PATCH 052/158] [ruby/net-http] Update lib/net/http.rb @natematykiewicz's suggestion to avoid another string allocation https://github.com/ruby/net-http/commit/4a22c42338 Co-authored-by: Nate Matykiewicz --- lib/net/http.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/net/http.rb b/lib/net/http.rb index c05c5baa6cde45..ff780b45bd3c2a 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -1615,8 +1615,8 @@ def connect write_timeout: @write_timeout, continue_timeout: @continue_timeout, debug_output: @debug_output) - buf = +"CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n" - buf << "Host: #{@address}:#{@port}\r\n" + buf = +"CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n" \ + "Host: #{@address}:#{@port}\r\n" if proxy_user credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0') buf << "Proxy-Authorization: Basic #{credential}\r\n" From 66a70582f4d7fea5dffac5925484640337d15e7f Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 7 Jun 2023 15:52:52 +0900 Subject: [PATCH 053/158] [ruby/openssl] ssl: adjust styles of ossl_start_ssl() Expand tabs, insert some spaces, and adjust indentation of switch-case to match Ruby's style. https://github.com/ruby/openssl/commit/10833aa8f6 --- ext/openssl/ossl_ssl.c | 72 +++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index ce6a5d4e408c02..9af6c021abbed6 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1765,62 +1765,62 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts) GetSSL(self, ssl); VALUE io = rb_attr_get(self, id_i_io); - for(;;){ - ret = func(ssl); + for (;;) { + ret = func(ssl); - cb_state = rb_attr_get(self, ID_callback_state); + cb_state = rb_attr_get(self, ID_callback_state); if (!NIL_P(cb_state)) { - /* must cleanup OpenSSL error stack before re-raising */ - ossl_clear_error(); - rb_jump_tag(NUM2INT(cb_state)); - } + /* must cleanup OpenSSL error stack before re-raising */ + ossl_clear_error(); + rb_jump_tag(NUM2INT(cb_state)); + } - if (ret > 0) - break; + if (ret > 0) + break; - switch((ret2 = ssl_get_error(ssl, ret))){ - case SSL_ERROR_WANT_WRITE: + switch ((ret2 = ssl_get_error(ssl, ret))) { + case SSL_ERROR_WANT_WRITE: if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); io_wait_writable(io); continue; - case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_READ: if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); io_wait_readable(io); continue; - case SSL_ERROR_SYSCALL: + case SSL_ERROR_SYSCALL: #ifdef __APPLE__ /* See ossl_ssl_write_internal() */ if (errno == EPROTOTYPE) continue; #endif - if (errno) rb_sys_fail(funcname); - ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); + if (errno) rb_sys_fail(funcname); + ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", + funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) - case SSL_ERROR_SSL: - err = ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_SSL && - ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { - const char *err_msg = ERR_reason_error_string(err), - *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); - if (!err_msg) - err_msg = "(null)"; - if (!verify_msg) - verify_msg = "(null)"; - ossl_clear_error(); /* let ossl_raise() not append message */ - ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s: %s (%s)", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl), - err_msg, verify_msg); - } + case SSL_ERROR_SSL: + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_SSL && + ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { + const char *err_msg = ERR_reason_error_string(err), + *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); + if (!err_msg) + err_msg = "(null)"; + if (!verify_msg) + verify_msg = "(null)"; + ossl_clear_error(); /* let ossl_raise() not append message */ + ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s: %s (%s)", + funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl), + err_msg, verify_msg); + } #endif - /* fallthrough */ - default: - ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); - } + /* fallthrough */ + default: + ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", + funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); + } } return self; From cb344e4e25c0979e2dfd1492fb91eef137bf059f Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 7 Jun 2023 16:01:01 +0900 Subject: [PATCH 054/158] [ruby/openssl] ssl: adjust "certificate verify failed" error on SSL_ERROR_SYSCALL Enrich SSLError's message with the low-level certificate verification result, even if SSL_get_error() returns SSL_ERROR_SYSCALL. This is currently done on SSL_ERROR_SSL only. According to the man page of SSL_get_error(), SSL_ERROR_SYSCALL may be returned for "other errors, check the error queue for details". This apparently means we have to treat SSL_ERROR_SYSCALL, if errno is not set, as equivalent to SSL_ERROR_SSL. https://github.com/ruby/openssl/commit/5113777e82 --- ext/openssl/ossl_ssl.c | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 9af6c021abbed6..5baba736b46d54 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1756,9 +1756,6 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts) int ret, ret2; VALUE cb_state; int nonblock = opts != Qfalse; -#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) - unsigned long err; -#endif rb_ivar_set(self, ID_callback_state, Qnil); @@ -1796,30 +1793,33 @@ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts) continue; #endif if (errno) rb_sys_fail(funcname); - ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); - + /* fallthrough */ + default: { + VALUE error_append = Qnil; #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) - case SSL_ERROR_SSL: - err = ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_SSL && - ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { - const char *err_msg = ERR_reason_error_string(err), - *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); - if (!err_msg) - err_msg = "(null)"; - if (!verify_msg) - verify_msg = "(null)"; - ossl_clear_error(); /* let ossl_raise() not append message */ - ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s: %s (%s)", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl), - err_msg, verify_msg); - } + unsigned long err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_SSL && + ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { + const char *err_msg = ERR_reason_error_string(err), + *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); + if (!err_msg) + err_msg = "(null)"; + if (!verify_msg) + verify_msg = "(null)"; + ossl_clear_error(); /* let ossl_raise() not append message */ + error_append = rb_sprintf(": %s (%s)", err_msg, verify_msg); + } #endif - /* fallthrough */ - default: - ossl_raise(eSSLError, "%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s", - funcname, ret2, errno, peeraddr_ip_str(self), SSL_state_string_long(ssl)); + ossl_raise(eSSLError, + "%s%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s%"PRIsVALUE, + funcname, + ret2 == SSL_ERROR_SYSCALL ? " SYSCALL" : "", + ret2, + errno, + peeraddr_ip_str(self), + SSL_state_string_long(ssl), + error_append); + } } } From 4465941e68e076d3198a071600f1047b7a382e0b Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 7 Jun 2023 16:15:29 +0900 Subject: [PATCH 055/158] [ruby/openssl] Revert "Relax error message check for OpenSSL 3.1" This reverts commit https://github.com/ruby/openssl/commit/fc4629d246f2. The test case "test_connect_certificate_verify_failed_exception_message" does want to check the reason behind a certificate verification failure to be included in the exception message. https://github.com/ruby/openssl/commit/c309745eb8 --- test/openssl/test_ssl.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index db76f1dc4c04ac..c80168f2ff69ba 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -1046,7 +1046,9 @@ def test_connect_certificate_verify_failed_exception_message start_server(ignore_listener_error: true) { |port| ctx = OpenSSL::SSL::SSLContext.new ctx.set_params - assert_raise_with_message(OpenSSL::SSL::SSLError, /certificate/) { + # OpenSSL <= 1.1.0: "self signed certificate in certificate chain" + # OpenSSL >= 3.0.0: "self-signed certificate in certificate chain" + assert_raise_with_message(OpenSSL::SSL::SSLError, /self.signed/) { server_connect(port, ctx) } } From 4541cd4cbae66900f8407ea8d2ec899634cd255d Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 29 Jun 2023 20:26:06 +0900 Subject: [PATCH 056/158] [ruby/openssl] [DOC] prefer "password" to "passphrase" Let's consistently use the word "password". Although they are considered synonymous, the mixed usage in the rdoc can cause confusion. OpenSSL::KDF.scrypt is an exception. This is because RFC 7914 refers to the input parameter as "passphrase". https://github.com/ruby/openssl/commit/06d67640e9 --- ext/openssl/ossl.c | 20 ++++++++++---------- ext/openssl/ossl_kdf.c | 2 +- ext/openssl/ossl_pkey_rsa.c | 20 ++++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index e67832d466eb9b..ac32747e4a31cd 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -207,7 +207,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_) while (1) { /* - * when the flag is nonzero, this passphrase + * when the flag is nonzero, this password * will be used to perform encryption; otherwise it will * be used to perform decryption. */ @@ -676,12 +676,12 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) * * Keys saved to disk without encryption are not secure as anyone who gets * ahold of the key may use it unless it is encrypted. In order to securely - * export a key you may export it with a pass phrase. + * export a key you may export it with a password. * * cipher = OpenSSL::Cipher.new 'aes-256-cbc' - * pass_phrase = 'my secure pass phrase goes here' + * password = 'my secure password goes here' * - * key_secure = key.export cipher, pass_phrase + * key_secure = key.export cipher, password * * open 'private.secure.pem', 'w' do |io| * io.write key_secure @@ -705,13 +705,13 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) * * === Loading an Encrypted Key * - * OpenSSL will prompt you for your pass phrase when loading an encrypted key. - * If you will not be able to type in the pass phrase you may provide it when + * OpenSSL will prompt you for your password when loading an encrypted key. + * If you will not be able to type in the password you may provide it when * loading the key: * * key4_pem = File.read 'private.secure.pem' - * pass_phrase = 'my secure pass phrase goes here' - * key4 = OpenSSL::PKey.read key4_pem, pass_phrase + * password = 'my secure password goes here' + * key4 = OpenSSL::PKey.read key4_pem, password * * == RSA Encryption * @@ -904,12 +904,12 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) * not readable by other users. * * ca_key = OpenSSL::PKey::RSA.new 2048 - * pass_phrase = 'my secure pass phrase goes here' + * password = 'my secure password goes here' * * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * * open 'ca_key.pem', 'w', 0400 do |io| - * io.write ca_key.export(cipher, pass_phrase) + * io.write ca_key.export(cipher, password) * end * * === CA Certificate diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c index 0d25a7304b11f1..48b161d4f47749 100644 --- a/ext/openssl/ossl_kdf.c +++ b/ext/openssl/ossl_kdf.c @@ -21,7 +21,7 @@ static VALUE mKDF, eKDF; * (https://tools.ietf.org/html/rfc2898#section-5.2). * * === Parameters - * pass :: The passphrase. + * pass :: The password. * salt :: The salt. Salts prevent attacks based on dictionaries of common * passwords and attacks based on rainbow tables. It is a public * value that can be safely stored along with the password (e.g. diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 072adabe62bf88..a9dce0d8557821 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -50,8 +50,8 @@ VALUE eRSAError; /* * call-seq: * RSA.new -> rsa - * RSA.new(encoded_key [, passphrase]) -> rsa - * RSA.new(encoded_key) { passphrase } -> rsa + * RSA.new(encoded_key [, password ]) -> rsa + * RSA.new(encoded_key) { password } -> rsa * RSA.new(size [, exponent]) -> rsa * * Generates or loads an \RSA keypair. @@ -61,9 +61,9 @@ VALUE eRSAError; * #set_crt_params. * * If called with a String, tries to parse as DER or PEM encoding of an \RSA key. - * Note that, if _passphrase_ is not specified but the key is encrypted with a - * passphrase, \OpenSSL will prompt for it. - * See also OpenSSL::PKey.read which can parse keys of any kinds. + * Note that if _password_ is not specified, but the key is encrypted with a + * password, \OpenSSL will prompt for it. + * See also OpenSSL::PKey.read which can parse keys of any kind. * * If called with a number, generates a new key pair. This form works as an * alias of RSA.generate. @@ -71,7 +71,7 @@ VALUE eRSAError; * Examples: * OpenSSL::PKey::RSA.new 2048 * OpenSSL::PKey::RSA.new File.read 'rsa.pem' - * OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase' + * OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my password' */ static VALUE ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) @@ -217,11 +217,11 @@ can_export_rsaprivatekey(VALUE self) /* * call-seq: - * rsa.export([cipher, pass_phrase]) => PEM-format String - * rsa.to_pem([cipher, pass_phrase]) => PEM-format String - * rsa.to_s([cipher, pass_phrase]) => PEM-format String + * rsa.export([cipher, password]) => PEM-format String + * rsa.to_pem([cipher, password]) => PEM-format String + * rsa.to_s([cipher, password]) => PEM-format String * - * Outputs this keypair in PEM encoding. If _cipher_ and _pass_phrase_ are + * Outputs this keypair in PEM encoding. If _cipher_ and _password_ are * given they will be used to encrypt the key. _cipher_ must be an * OpenSSL::Cipher instance. */ From fae6fd07fe49d3149c922e15c5a75cd32631e858 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 28 Jun 2023 12:10:50 +0900 Subject: [PATCH 057/158] [ruby/openssl] [DOC] prefer PKey#private_to_pem and #public_to_pem in RDoc Suggest the use of OpenSSL::PKey::PKey#private_to_pem and #public_to_pem in the top-level documentation. For new programs, these are recommended over OpenSSL::PKey::RSA#export (also aliased as #to_s and #to_pem) unless there is a specific reason to use it, i.e., unless the PKCS#1 output format specifically is required. The output format of OpenSSL::PKey::RSA#export depends on whether the key is a public key or a private key, which is very counter-intuitive. Additionally, when called with arguments to encrypt a private key, as in this example, OpenSSL's own, non-standard format is used. The man page of PEM_write_bio_PrivateKey_traditional(3) in OpenSSL 1.1.1 or later states that it "should only be used for compatibility with legacy programs". https://github.com/ruby/openssl/commit/56312038d6 --- ext/openssl/ossl.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index ac32747e4a31cd..b1ba48c8696125 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -669,8 +669,8 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) * * key = OpenSSL::PKey::RSA.new 2048 * - * open 'private_key.pem', 'w' do |io| io.write key.to_pem end - * open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end + * File.write 'private_key.pem', key.private_to_pem + * File.write 'public_key.pem', key.public_to_pem * * === Exporting a Key * @@ -681,11 +681,9 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) * cipher = OpenSSL::Cipher.new 'aes-256-cbc' * password = 'my secure password goes here' * - * key_secure = key.export cipher, password + * key_secure = key.private_to_pem cipher, password * - * open 'private.secure.pem', 'w' do |io| - * io.write key_secure - * end + * File.write 'private.secure.pem', key_secure * * OpenSSL::Cipher.ciphers returns a list of available ciphers. * @@ -906,10 +904,10 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2) * ca_key = OpenSSL::PKey::RSA.new 2048 * password = 'my secure password goes here' * - * cipher = OpenSSL::Cipher.new 'aes-256-cbc' + * cipher = 'aes-256-cbc' * * open 'ca_key.pem', 'w', 0400 do |io| - * io.write ca_key.export(cipher, password) + * io.write ca_key.private_to_pem(cipher, password) * end * * === CA Certificate From 0eaee5c000bf2fc6e1866881a6f9a4d7820c16d4 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Wed, 28 Jun 2023 12:09:27 +0900 Subject: [PATCH 058/158] [ruby/openssl] [DOC] enhance RDoc for exporting pkeys Describe the behavior of OpenSSL::PKey::{DH,DSA,EC,RSA}#to_pem and #to_der more clearly. They return a different result depending on whether the pkey is a public or private key. This was not documented adequately. Also, suggest the use of OpenSSL::PKey::PKey#private_to_pem and #public_to_pem instead, if possible. https://github.com/ruby/openssl/commit/d22769af8f --- ext/openssl/ossl_pkey.c | 18 ++++++++++ ext/openssl/ossl_pkey_dh.c | 29 +++++++++++---- ext/openssl/ossl_pkey_dsa.c | 65 +++++++++++++++++++++++++++++----- ext/openssl/ossl_pkey_ec.c | 70 +++++++++++++++++++++++++++++++++---- ext/openssl/ossl_pkey_rsa.c | 63 ++++++++++++++++++++++++++++++--- 5 files changed, 219 insertions(+), 26 deletions(-) diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 952a6851e6febb..6d73d259c49ac5 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -875,6 +875,18 @@ ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self) * * Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der * for more details. + * + * An unencrypted PEM-encoded key will look like: + * + * -----BEGIN PRIVATE KEY----- + * [...] + * -----END PRIVATE KEY----- + * + * An encrypted PEM-encoded key will look like: + * + * -----BEGIN ENCRYPTED PRIVATE KEY----- + * [...] + * -----END ENCRYPTED PRIVATE KEY----- */ static VALUE ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self) @@ -953,6 +965,12 @@ ossl_pkey_public_to_der(VALUE self) * pkey.public_to_pem -> string * * Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format. + * + * A PEM-encoded key will look like: + * + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- */ static VALUE ossl_pkey_public_to_pem(VALUE self) diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 83c41378fe33ac..a231814a99b875 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -216,9 +216,20 @@ ossl_dh_is_private(VALUE self) * dh.to_pem -> aString * dh.to_s -> aString * - * Encodes this DH to its PEM encoding. Note that any existing per-session - * public/private keys will *not* get encoded, just the Diffie-Hellman - * parameters will be encoded. + * Serializes the DH parameters to a PEM-encoding. + * + * Note that any existing per-session public/private keys will *not* get + * encoded, just the Diffie-Hellman parameters will be encoded. + * + * PEM-encoded parameters will look like: + * + * -----BEGIN DH PARAMETERS----- + * [...] + * -----END DH PARAMETERS----- + * + * See also #public_to_pem (X.509 SubjectPublicKeyInfo) and + * #private_to_pem (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for + * serialization with the private or public key components. */ static VALUE ossl_dh_export(VALUE self) @@ -244,10 +255,14 @@ ossl_dh_export(VALUE self) * call-seq: * dh.to_der -> aString * - * Encodes this DH to its DER encoding. Note that any existing per-session - * public/private keys will *not* get encoded, just the Diffie-Hellman - * parameters will be encoded. - + * Serializes the DH parameters to a DER-encoding + * + * Note that any existing per-session public/private keys will *not* get + * encoded, just the Diffie-Hellman parameters will be encoded. + * + * See also #public_to_der (X.509 SubjectPublicKeyInfo) and + * #private_to_der (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for + * serialization with the private or public key components. */ static VALUE ossl_dh_to_der(VALUE self) diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index b097f8c9d23738..058ce738882adb 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -211,16 +211,58 @@ ossl_dsa_is_private(VALUE self) * dsa.to_pem([cipher, password]) -> aString * dsa.to_s([cipher, password]) -> aString * - * Encodes this DSA to its PEM encoding. + * Serializes a private or public key to a PEM-encoding. * - * === Parameters - * * _cipher_ is an OpenSSL::Cipher. - * * _password_ is a string containing your password. + * [When the key contains public components only] * - * === Examples - * DSA.to_pem -> aString - * DSA.to_pem(cipher, 'mypassword') -> aString + * Serializes it into an X.509 SubjectPublicKeyInfo. + * The parameters _cipher_ and _password_ are ignored. * + * A PEM-encoded key will look like: + * + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- + * + * Consider using #public_to_pem instead. This serializes the key into an + * X.509 SubjectPublicKeyInfo regardless of whether it is a public key + * or a private key. + * + * [When the key contains private components, and no parameters are given] + * + * Serializes it into a traditional \OpenSSL DSAPrivateKey. + * + * A PEM-encoded key will look like: + * + * -----BEGIN DSA PRIVATE KEY----- + * [...] + * -----END DSA PRIVATE KEY----- + * + * [When the key contains private components, and _cipher_ and _password_ are given] + * + * Serializes it into a traditional \OpenSSL DSAPrivateKey and encrypts it in + * OpenSSL's traditional PEM encryption format. + * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an + * instance of OpenSSL::Cipher. + * + * An encrypted PEM-encoded key will look like: + * + * -----BEGIN DSA PRIVATE KEY----- + * Proc-Type: 4,ENCRYPTED + * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + * + * [...] + * -----END DSA PRIVATE KEY----- + * + * Note that this format uses MD5 to derive the encryption key, and hence + * will not be available on FIPS-compliant systems. + * + * This method is kept for compatibility. + * This should only be used when the traditional, non-standard \OpenSSL format + * is required. + * + * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. */ static VALUE ossl_dsa_export(int argc, VALUE *argv, VALUE self) @@ -238,8 +280,15 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) * call-seq: * dsa.to_der -> aString * - * Encodes this DSA to its DER encoding. + * Serializes a private or public key to a DER-encoding. + * + * See #to_pem for details. + * + * This method is kept for compatibility. + * This should only be used when the traditional, non-standard \OpenSSL format + * is required. * + * Consider using #public_to_der or #private_to_der instead. */ static VALUE ossl_dsa_to_der(VALUE self) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 329c12d90bbb4e..4b3a1fd0febb09 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -400,13 +400,61 @@ static VALUE ossl_ec_key_is_private(VALUE self) /* * call-seq: - * key.export([cipher, pass_phrase]) => String - * key.to_pem([cipher, pass_phrase]) => String + * key.export([cipher, password]) => String + * key.to_pem([cipher, password]) => String * - * Outputs the EC key in PEM encoding. If _cipher_ and _pass_phrase_ are given - * they will be used to encrypt the key. _cipher_ must be an OpenSSL::Cipher - * instance. Note that encryption will only be effective for a private key, - * public keys will always be encoded in plain text. + * Serializes a private or public key to a PEM-encoding. + * + * [When the key contains public components only] + * + * Serializes it into an X.509 SubjectPublicKeyInfo. + * The parameters _cipher_ and _password_ are ignored. + * + * A PEM-encoded key will look like: + * + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- + * + * Consider using #public_to_pem instead. This serializes the key into an + * X.509 SubjectPublicKeyInfo regardless of whether it is a public key + * or a private key. + * + * [When the key contains private components, and no parameters are given] + * + * Serializes it into a SEC 1/RFC 5915 ECPrivateKey. + * + * A PEM-encoded key will look like: + * + * -----BEGIN EC PRIVATE KEY----- + * [...] + * -----END EC PRIVATE KEY----- + * + * [When the key contains private components, and _cipher_ and _password_ are given] + * + * Serializes it into a SEC 1/RFC 5915 ECPrivateKey + * and encrypts it in OpenSSL's traditional PEM encryption format. + * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an + * instance of OpenSSL::Cipher. + * + * An encrypted PEM-encoded key will look like: + * + * -----BEGIN EC PRIVATE KEY----- + * Proc-Type: 4,ENCRYPTED + * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + * + * [...] + * -----END EC PRIVATE KEY----- + * + * Note that this format uses MD5 to derive the encryption key, and hence + * will not be available on FIPS-compliant systems. + * + * This method is kept for compatibility. + * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is + * required. + * + * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. */ static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self) @@ -426,7 +474,15 @@ ossl_ec_key_export(int argc, VALUE *argv, VALUE self) * call-seq: * key.to_der => String * - * See the OpenSSL documentation for i2d_ECPrivateKey_bio() + * Serializes a private or public key to a DER-encoding. + * + * See #to_pem for details. + * + * This method is kept for compatibility. + * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is + * required. + * + * Consider using #public_to_der or #private_to_der instead. */ static VALUE ossl_ec_key_to_der(VALUE self) diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index a9dce0d8557821..389f76f309e3b4 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -221,9 +221,57 @@ can_export_rsaprivatekey(VALUE self) * rsa.to_pem([cipher, password]) => PEM-format String * rsa.to_s([cipher, password]) => PEM-format String * - * Outputs this keypair in PEM encoding. If _cipher_ and _password_ are - * given they will be used to encrypt the key. _cipher_ must be an - * OpenSSL::Cipher instance. + * Serializes a private or public key to a PEM-encoding. + * + * [When the key contains public components only] + * + * Serializes it into an X.509 SubjectPublicKeyInfo. + * The parameters _cipher_ and _password_ are ignored. + * + * A PEM-encoded key will look like: + * + * -----BEGIN PUBLIC KEY----- + * [...] + * -----END PUBLIC KEY----- + * + * Consider using #public_to_pem instead. This serializes the key into an + * X.509 SubjectPublicKeyInfo regardless of whether the key is a public key + * or a private key. + * + * [When the key contains private components, and no parameters are given] + * + * Serializes it into a PKCS #1 RSAPrivateKey. + * + * A PEM-encoded key will look like: + * + * -----BEGIN RSA PRIVATE KEY----- + * [...] + * -----END RSA PRIVATE KEY----- + * + * [When the key contains private components, and _cipher_ and _password_ are given] + * + * Serializes it into a PKCS #1 RSAPrivateKey + * and encrypts it in OpenSSL's traditional PEM encryption format. + * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an + * instance of OpenSSL::Cipher. + * + * An encrypted PEM-encoded key will look like: + * + * -----BEGIN RSA PRIVATE KEY----- + * Proc-Type: 4,ENCRYPTED + * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0 + * + * [...] + * -----END RSA PRIVATE KEY----- + * + * Note that this format uses MD5 to derive the encryption key, and hence + * will not be available on FIPS-compliant systems. + * + * This method is kept for compatibility. + * This should only be used when the PKCS #1 RSAPrivateKey format is required. + * + * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem + * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead. */ static VALUE ossl_rsa_export(int argc, VALUE *argv, VALUE self) @@ -238,7 +286,14 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) * call-seq: * rsa.to_der => DER-format String * - * Outputs this keypair in DER encoding. + * Serializes a private or public key to a DER-encoding. + * + * See #to_pem for details. + * + * This method is kept for compatibility. + * This should only be used when the PKCS #1 RSAPrivateKey format is required. + * + * Consider using #public_to_der or #private_to_der instead. */ static VALUE ossl_rsa_to_der(VALUE self) From 8dd5c20224771abacfcfba848d9465131f14f3fe Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Wed, 3 May 2023 20:48:34 +0200 Subject: [PATCH 059/158] [ruby/openssl] Raise an error when the specified OpenSSL library directory doesn't exist. OpenSSL built from the source creates the library directory to the `/path/to/openssl_dir/lib64` as a default. In the case, the `bundle exec rake compile -- --with-openssl-dir=` cannot compile with the lib64 directory, and may compile with system OpenSSL's libraries unintentionally. This commit is to check this case to avoid linking with an unintentional library directory. https://github.com/ruby/openssl/commit/ca54087462 --- ext/openssl/extconf.rb | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 368145d23a3212..4bcf7b9cf02e11 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -13,12 +13,32 @@ require "mkmf" +ssl_dirs = nil if defined?(::TruffleRuby) # Always respect the openssl prefix chosen by truffle/openssl-prefix require 'truffle/openssl-prefix' - dir_config_given = dir_config("openssl", ENV["OPENSSL_PREFIX"]).any? + ssl_dirs = dir_config("openssl", ENV["OPENSSL_PREFIX"]) else - dir_config_given = dir_config("openssl").any? + ssl_dirs = dir_config("openssl") +end +dir_config_given = ssl_dirs.any? + +_, ssl_ldir = ssl_dirs +if ssl_ldir&.split(File::PATH_SEPARATOR)&.none? { |dir| File.directory?(dir) } + # According to the `mkmf.rb#dir_config`, the `--with-openssl-dir=` uses + # the value of the `File.basename(RbConfig::MAKEFILE_CONFIG["libdir"])` as a + # loaded library directory name. + ruby_ldir_name = File.basename(RbConfig::MAKEFILE_CONFIG["libdir"]) + + raise "OpenSSL library directory could not be found in '#{ssl_ldir}'. " \ + "You might want to fix this error in one of the following ways.\n" \ + " * Recompile OpenSSL by configuring it with --libdir=#{ruby_ldir_name} " \ + " to specify the OpenSSL library directory.\n" \ + " * Recompile Ruby by configuring it with --libdir= to specify the " \ + "Ruby library directory.\n" \ + " * Compile this openssl gem with --with-openssl-include= and " \ + "--with-openssl-lib= options to specify the OpenSSL include and " \ + "library directories." end dir_config("kerberos") From 01d368e7b06ccf34f92c535a117a2856956d2bcb Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 10 Aug 2023 02:45:15 +0900 Subject: [PATCH 060/158] [ruby/openssl] ssl: raise SSLError if loading ca_file or ca_path fails When compiled with OpenSSL <= 1.1.1, OpenSSL::SSL::SSLContext#setup does not raise an exception on an error return from SSL_CTX_load_verify_locations(), but instead only prints a verbose-mode warning. This is not helpful since it very likely indicates an actual error, such as the specified file not being readable. Also, OpenSSL's error queue is not correctly cleared: $ ruby -w -ropenssl -e'OpenSSL.debug=true; ctx=OpenSSL::SSL::SSLContext.new; ctx.ca_file="bad-path"; ctx.setup; pp OpenSSL.errors' -e:1: warning: can't set verify locations ["error:02001002:system library:fopen:No such file or directory", "error:2006D080:BIO routines:BIO_new_file:no such file", "error:0B084002:x509 certificate routines:X509_load_cert_crl_file: system lib"] The behavior is currently different when compiled with OpenSSL >= 3.0: SSLError is raised if SSL_CTX_load_verify_file() or SSL_CTX_load_verify_dir() fails. This inconsistency was unintentionally introduced by commit https://github.com/ruby/openssl/commit/5375a55ffc35 ("ssl: use SSL_CTX_load_verify_{file,dir}() if available", 2020-02-22). However, raising SSLError seems more appropriate in this situation. Let's adjust the OpenSSL <= 1.1.1 code so that it behaves the same way as the OpenSSL >= 3.0 code currently does. Fixes: https://github.com/ruby/openssl/issues/649 https://github.com/ruby/openssl/commit/7eb10f7b75 --- ext/openssl/ossl_ssl.c | 6 +++--- test/openssl/test_ssl.rb | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 5baba736b46d54..236d455ff2a48e 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -885,9 +885,9 @@ ossl_sslctx_setup(VALUE self) if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path)) ossl_raise(eSSLError, "SSL_CTX_load_verify_dir"); #else - if(ca_file || ca_path){ - if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) - rb_warning("can't set verify locations"); + if (ca_file || ca_path) { + if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) + ossl_raise(eSSLError, "SSL_CTX_load_verify_locations"); } #endif diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index c80168f2ff69ba..07dc9a343cef8e 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -481,6 +481,40 @@ def test_exception_in_verify_callback_is_ignored } end + def test_ca_file + start_server(ignore_listener_error: true) { |port| + # X509_STORE is shared; setting ca_file to SSLContext affects store + store = OpenSSL::X509::Store.new + assert_equal false, store.verify(@svr_cert) + + ctx = Tempfile.create("ca_cert.pem") { |f| + f.puts(@ca_cert.to_pem) + f.close + + ctx = OpenSSL::SSL::SSLContext.new + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + ctx.cert_store = store + ctx.ca_file = f.path + ctx.setup + ctx + } + assert_nothing_raised { + server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets } + } + assert_equal true, store.verify(@svr_cert) + } + end + + def test_ca_file_not_found + path = Tempfile.create("ca_cert.pem") { |f| f.path } + ctx = OpenSSL::SSL::SSLContext.new + ctx.ca_file = path + # OpenSSL >= 1.1.0: /no certificate or crl found/ + assert_raise(OpenSSL::SSL::SSLError) { + ctx.setup + } + end + def test_finished_messages server_finished = nil server_peer_finished = nil From 382b42be9446e1d215109cc47db9ebc156cb8f8f Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 1 Jul 2023 21:55:31 +0900 Subject: [PATCH 061/158] [ruby/openssl] config: relax test assertions against error messages Test that the error message contains the necessary text instead of the exact match. Exceptions raised by ossl_raise() may carry additional context information in the message. https://github.com/ruby/openssl/commit/fd6f76c0d3 --- test/openssl/test_config.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb index 24a215a486701f..6dbb9c61388644 100644 --- a/test/openssl/test_config.rb +++ b/test/openssl/test_config.rb @@ -91,22 +91,19 @@ def test_s_parse_format assert_equal('123baz456bar798', c['dollar']['qux']) assert_equal('123baz456bar798.123baz456bar798', c['dollar']['quxx']) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: variable has no value/) do OpenSSL::Config.parse("foo = $bar") end - assert_equal("error in line 1: variable has no value", excn.message) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: no close brace/) do OpenSSL::Config.parse("foo = $(bar") end - assert_equal("error in line 1: no close brace", excn.message) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: missing equal sign/) do OpenSSL::Config.parse("f o =b ar # no space in key") end - assert_equal("error in line 1: missing equal sign", excn.message) - excn = assert_raise(OpenSSL::ConfigError) do + assert_raise_with_message(OpenSSL::ConfigError, /error in line 7: missing close square bracket/) do OpenSSL::Config.parse(<<__EOC__) # comment 1 # comments @@ -117,7 +114,6 @@ def test_s_parse_format [third # section not terminated __EOC__ end - assert_equal("error in line 7: missing close square bracket", excn.message) end def test_s_parse_include From 12bdacdca5d19988f3ffe60714f518ec7324b35a Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 1 Jul 2023 21:53:38 +0900 Subject: [PATCH 062/158] [ruby/openssl] Include "additional data" message in OpenSSL errors Error entries in the OpenSSL error queue may contain additional contextual information associated with the error, which can be helpful when debugging. This "additional data" is currently only printed to stderr when OpenSSL.debug is enabled. Let's include this in the exception messages raised with ossl_raise(), too. $ ruby -Ilib -ropenssl -e'OpenSSL.debug=true; OpenSSL::SSL::SSLContext.new.ecdh_curves="P-256:not-a-curve"' -e:1: warning: error on stack: error:0A080106:SSL routines:gid_cb:passed invalid argument (group 'not-a-curve' cannot be set) -e:1:in `ecdh_curves=': passed invalid argument (group 'not-a-curve' cannot be set) (OpenSSL::SSL::SSLError) from -e:1:in `
' https://github.com/ruby/openssl/commit/1c5bbdd68e --- ext/openssl/ossl.c | 29 +++++++++++++++++------------ test/openssl/test_ossl.rb | 12 ++++++++++++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index b1ba48c8696125..0bd2fa497e629d 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -272,23 +272,28 @@ VALUE ossl_make_error(VALUE exc, VALUE str) { unsigned long e; + const char *data; + int flags; - e = ERR_peek_last_error(); + if (NIL_P(str)) + str = rb_str_new(NULL, 0); + +#ifdef HAVE_ERR_GET_ERROR_ALL + e = ERR_peek_last_error_all(NULL, NULL, NULL, &data, &flags); +#else + e = ERR_peek_last_error_line_data(NULL, NULL, &data, &flags); +#endif if (e) { - const char *msg = ERR_reason_error_string(e); + const char *msg = ERR_reason_error_string(e); - if (NIL_P(str)) { - if (msg) str = rb_str_new_cstr(msg); - } - else { - if (RSTRING_LEN(str)) rb_str_cat2(str, ": "); - rb_str_cat2(str, msg ? msg : "(null)"); - } - ossl_clear_error(); + if (RSTRING_LEN(str)) rb_str_cat_cstr(str, ": "); + rb_str_cat_cstr(str, msg ? msg : "(null)"); + if (flags & ERR_TXT_STRING && data) + rb_str_catf(str, " (%s)", data); + ossl_clear_error(); } - if (NIL_P(str)) str = rb_str_new(0, 0); - return rb_exc_new3(exc, str); + return rb_exc_new_str(exc, str); } void diff --git a/test/openssl/test_ossl.rb b/test/openssl/test_ossl.rb index e1d86bd40b9f1a..5759c75b81d469 100644 --- a/test/openssl/test_ossl.rb +++ b/test/openssl/test_ossl.rb @@ -60,6 +60,18 @@ def test_memcmp_timing assert_operator(a_b_time, :<, a_c_time * 10, "fixed_length_secure_compare timing test failed") assert_operator(a_c_time, :<, a_b_time * 10, "fixed_length_secure_compare timing test failed") end + + def test_error_data + # X509V3_EXT_nconf_nid() called from OpenSSL::X509::ExtensionFactory#create_ext is a function + # that uses ERR_raise_data() to append additional information about the error. + # + # The generated message should look like: + # "subjectAltName = IP:not.a.valid.ip.address: bad ip address (value=not.a.valid.ip.address)" + ef = OpenSSL::X509::ExtensionFactory.new + assert_raise_with_message(OpenSSL::X509::ExtensionError, /\(value=not.a.valid.ip.address\)/) { + ef.create_ext("subjectAltName", "IP:not.a.valid.ip.address") + } + end end end From 8ca0d53fd09b2032d990b0ab92ec63f408861dbc Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Mon, 14 Aug 2023 17:13:22 +0200 Subject: [PATCH 063/158] [ruby/openssl] Use openssl? instead of OpenSSL::OPENSSL_VERSION_NUMBER. Update the `openssl?` method by adding status argument. Note the format is below. * OpenSSL 3: 0xMNN00PP0 (major minor 00 patch 0) * OpenSSL 1: 0xMNNFFPPS (major minor fix patch status) See for details. https://github.com/ruby/openssl/commit/db8deaacd3 --- test/openssl/test_cipher.rb | 2 +- test/openssl/test_pkey.rb | 2 +- test/openssl/utils.rb | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb index 1c8610b2a9b3bc..8faa57064872c4 100644 --- a/test/openssl/test_cipher.rb +++ b/test/openssl/test_cipher.rb @@ -205,7 +205,7 @@ def test_aes_ccm assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct2) } end if has_cipher?("aes-128-ccm") && OpenSSL::Cipher.new("aes-128-ccm").authenticated? && - OpenSSL::OPENSSL_VERSION_NUMBER >= 0x1010103f # version >= 1.1.1c + openssl?(1, 1, 1, 0x03, 0xf) # version >= 1.1.1c def test_aes_gcm # GCM spec Appendix B Test Case 4 diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index 691dd74aab5c91..9233132380a840 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -188,7 +188,7 @@ def test_x25519 end def raw_initialize - pend "Ed25519 is not implemented" unless OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10101000 && # >= v1.1.1 + pend "Ed25519 is not implemented" unless openssl?(1, 1, 1) # >= v1.1.1 assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("foo123", "xxx") } assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("ED25519", "xxx") } diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index f00084ffd322d7..3d4d05fe02ebc7 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -131,11 +131,12 @@ def get_subject_key_id(cert, hex: true) end end - def openssl?(major = nil, minor = nil, fix = nil, patch = 0) + def openssl?(major = nil, minor = nil, fix = nil, patch = 0, status = 0) return false if OpenSSL::OPENSSL_VERSION.include?("LibreSSL") return true unless major OpenSSL::OPENSSL_VERSION_NUMBER >= - major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10 + major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10 + + status * 0x1 end def libressl?(major = nil, minor = nil, fix = nil) From f5ca8d0e3149098e4b6c4a14d129268ec43c71d5 Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Wed, 9 Aug 2023 20:35:01 +0200 Subject: [PATCH 064/158] [ruby/openssl] test/openssl/test_pkey.rb: Fix pending tests in FIPS case. https://github.com/ruby/openssl/commit/f9980d88aa --- test/openssl/test_pkey.rb | 15 ++++++++++----- test/openssl/utils.rb | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index 9233132380a840..da3ae5d67d2ebf 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -82,8 +82,7 @@ def test_hmac_sign_verify end def test_ed25519 - # https://github.com/openssl/openssl/issues/20758 - pend('Not supported on FIPS mode enabled') if OpenSSL.fips_mode + pend_on_openssl_issue_21493 # Test vector from RFC 8032 Section 7.1 TEST 2 priv_pem = <<~EOF @@ -101,7 +100,13 @@ def test_ed25519 pub = OpenSSL::PKey.read(pub_pem) rescue OpenSSL::PKey::PKeyError # OpenSSL < 1.1.1 - pend "Ed25519 is not implemented" + if !openssl?(1, 1, 1) + pend "Ed25519 is not implemented" + elsif OpenSSL.fips_mode && openssl?(3, 1, 0, 0) + # See OpenSSL providers/fips/fipsprov.c PROV_NAMES_ED25519 entries + # with FIPS_UNAPPROVED_PROPERTIES in OpenSSL 3.1+. + pend "Ed25519 is not approved in OpenSSL 3.1+ FIPS code" + end end assert_instance_of OpenSSL::PKey::PKey, priv assert_instance_of OpenSSL::PKey::PKey, pub @@ -143,7 +148,7 @@ def test_ed25519 end def test_x25519 - pend('Not supported on FIPS mode enabled') if OpenSSL.fips_mode + pend_on_openssl_issue_21493 # Test vector from RFC 7748 Section 6.1 alice_pem = <<~EOF @@ -197,7 +202,7 @@ def raw_initialize end def test_compare? - pend('Not supported on FIPS mode enabled') if OpenSSL.fips_mode + pend_on_openssl_issue_21493 key1 = Fixtures.pkey("rsa1024") key2 = Fixtures.pkey("rsa1024") diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb index 3d4d05fe02ebc7..b5ffbe1c999e95 100644 --- a/test/openssl/utils.rb +++ b/test/openssl/utils.rb @@ -144,6 +144,22 @@ def libressl?(major = nil, minor = nil, fix = nil) return false unless version !major || (version.map(&:to_i) <=> [major, minor, fix]) >= 0 end + + # OpenSSL 3: x25519 a decode from and then encode to a pem file corrupts the + # key if fips+base provider is used + # This issue happens in OpenSSL between 3.0,0 and 3.0.10 or between 3.1.0 and + # 3.1.2. + # https://github.com/openssl/openssl/issues/21493 + # https://github.com/openssl/openssl/pull/21519 + def pend_on_openssl_issue_21493 + if OpenSSL.fips_mode && + ( + (openssl?(3, 0, 0, 0) && !openssl?(3, 0, 0, 11)) || + (openssl?(3, 1, 0, 0) && !openssl?(3, 1, 0, 3)) + ) + pend('See ') + end + end end class OpenSSL::TestCase < Test::Unit::TestCase From f1df06294474186137a9d1e80e65cb14ec3a5c66 Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Mon, 14 Aug 2023 16:02:42 +0200 Subject: [PATCH 065/158] [ruby/openssl] Enhance printing OpenSSL versions. * Updated the `OpenSSL::OPENSSL_VERSION_NUMBER` comment explaining the format. * Added the `OpenSSL::LIBRESSL_VERSION_NUMBER` to print LibreSSL version number, in the case that Ruby OpenSSL binding is compiled with LibreSSL. Note `test/openssl/utils.rb#libressl?` is not using this value in it for now. * Update `rake debug` to print the values in a readable way, adding `OpenSSL::OPENSSL_VERSION_NUMBER` and `OpenSSL::LIBRESSL_VERSION_NUMBER`. https://github.com/ruby/openssl/commit/d19e6360ed --- ext/openssl/ossl.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 0bd2fa497e629d..d27e56dca7452f 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -1152,10 +1152,27 @@ Init_openssl(void) /* * Version number of OpenSSL the ruby OpenSSL extension was built with - * (base 16) + * (base 16). The formats are below. + * + * [OpenSSL 3] 0xMNN00PP0 (major minor 00 patch 0) + * [OpenSSL before 3] 0xMNNFFPPS (major minor fix patch status) + * [LibreSSL] 0x20000000 (fixed value) + * + * See also the man page OPENSSL_VERSION_NUMBER(3). */ rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); +#if defined(LIBRESSL_VERSION_NUMBER) + /* + * Version number of LibreSSL the ruby OpenSSL extension was built with + * (base 16). The format is 0xMNNFFPPS (major minor fix patch + * status). This constant is only defined in LibreSSL cases. + * + * See also the man page OPENSSL_VERSION_NUMBER(3). + */ + rb_define_const(mOSSL, "LIBRESSL_VERSION_NUMBER", INT2NUM(LIBRESSL_VERSION_NUMBER)); +#endif + /* * Boolean indicating whether OpenSSL is FIPS-capable or not */ From 86492fca653a105d926eb0cad9128e22b324a378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 12 Jul 2023 10:58:27 +0200 Subject: [PATCH 066/158] [rubygems/rubygems] Avoid unnecessary loop through dependencies https://github.com/rubygems/rubygems/commit/2ab63bb94d --- lib/bundler/definition.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index e043630c2d5a96..397b2da7beeaf3 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -805,15 +805,13 @@ def converge_locked_specs def converge_specs(specs) converged = [] - - deps = @dependencies.select do |dep| - specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) } - end + deps = [] @specs_that_changed_sources = [] specs.each do |s| dep = @dependencies.find {|d| s.satisfies?(d) } + deps << dep if dep && (!dep.source || s.source.include?(dep.source)) # Replace the locked dependency's source with the equivalent source from the Gemfile s.source = if dep&.source From 6bc63ab9bb3828a59e2c87619922a33bf6b27da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 12 Jul 2023 11:15:10 +0200 Subject: [PATCH 067/158] [rubygems/rubygems] Refactor locked dep filtering more We only need to check whether the spec if for a direct dependency once. https://github.com/rubygems/rubygems/commit/65b455a5cb --- lib/bundler/definition.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 397b2da7beeaf3..5d3931e2b7a1fd 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -811,14 +811,14 @@ def converge_specs(specs) specs.each do |s| dep = @dependencies.find {|d| s.satisfies?(d) } - deps << dep if dep && (!dep.source || s.source.include?(dep.source)) # Replace the locked dependency's source with the equivalent source from the Gemfile - s.source = if dep&.source - gemfile_source = dep.source + s.source = if dep + gemfile_source = dep.source || sources.default_source lockfile_source = s.source @specs_that_changed_sources << s if gemfile_source != lockfile_source + deps << dep if !dep.source || lockfile_source.include?(dep.source) gemfile_source else From 002165f8fec925740330e62984e28fcc0eb53ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 12 Jul 2023 12:38:44 +0200 Subject: [PATCH 068/158] [rubygems/rubygems] Move `lockfile_source` variable out of condition branch https://github.com/rubygems/rubygems/commit/efebc64250 --- lib/bundler/definition.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 5d3931e2b7a1fd..c20e440a5693d6 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -811,18 +811,18 @@ def converge_specs(specs) specs.each do |s| dep = @dependencies.find {|d| s.satisfies?(d) } + lockfile_source = s.source # Replace the locked dependency's source with the equivalent source from the Gemfile s.source = if dep gemfile_source = dep.source || sources.default_source - lockfile_source = s.source @specs_that_changed_sources << s if gemfile_source != lockfile_source deps << dep if !dep.source || lockfile_source.include?(dep.source) gemfile_source else - sources.get_with_fallback(s.source) + sources.get_with_fallback(lockfile_source) end next if @unlock[:sources].include?(s.source.name) From c57ab646cbefc50a8e8d21faec8a60643b1a057c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 13 Jul 2023 12:47:46 +0200 Subject: [PATCH 069/158] [rubygems/rubygems] Extract a `default_source` method https://github.com/rubygems/rubygems/commit/784e08348e --- lib/bundler/definition.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index c20e440a5693d6..f970301a234fe8 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -390,8 +390,8 @@ def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false) both_sources.each do |name, (dep, lock_dep)| next if dep.nil? || lock_dep.nil? - gemfile_source = dep.source || sources.default_source - lock_source = lock_dep.source || sources.default_source + gemfile_source = dep.source || default_source + lock_source = lock_dep.source || default_source next if lock_source.include?(gemfile_source) gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source" @@ -815,7 +815,7 @@ def converge_specs(specs) # Replace the locked dependency's source with the equivalent source from the Gemfile s.source = if dep - gemfile_source = dep.source || sources.default_source + gemfile_source = dep.source || default_source @specs_that_changed_sources << s if gemfile_source != lockfile_source deps << dep if !dep.source || lockfile_source.include?(dep.source) @@ -875,7 +875,7 @@ def source_requirements source_requirements = if precompute_source_requirements_for_indirect_dependencies? all_requirements = source_map.all_requirements all_requirements = pin_locally_available_names(all_requirements) if @prefer_local - { :default => sources.default_source }.merge(all_requirements) + { :default => default_source }.merge(all_requirements) else { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements) end @@ -884,7 +884,7 @@ def source_requirements source_requirements[dep.name] = sources.metadata_source end - default_bundler_source = source_requirements["bundler"] || sources.default_source + default_bundler_source = source_requirements["bundler"] || default_source if @unlocking_bundler default_bundler_source.add_dependency_names("bundler") @@ -897,6 +897,10 @@ def source_requirements source_requirements end + def default_source + sources.default_source + end + def verify_changed_sources! @specs_that_changed_sources.each do |s| if s.source.specs.search(s.name).empty? From 7bb3e637ffedf34fa148d4fbf35b57681490c7e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 13 Jul 2023 12:48:05 +0200 Subject: [PATCH 070/158] [rubygems/rubygems] Don't update locked sources when not necessary https://github.com/rubygems/rubygems/commit/cfc82b592a --- lib/bundler/definition.rb | 9 +++++---- lib/bundler/source_list.rb | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index f970301a234fe8..8d90e2501d52dc 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -813,16 +813,17 @@ def converge_specs(specs) dep = @dependencies.find {|d| s.satisfies?(d) } lockfile_source = s.source - # Replace the locked dependency's source with the equivalent source from the Gemfile - s.source = if dep + if dep gemfile_source = dep.source || default_source @specs_that_changed_sources << s if gemfile_source != lockfile_source deps << dep if !dep.source || lockfile_source.include?(dep.source) - gemfile_source + # Replace the locked dependency's source with the equivalent source from the Gemfile + s.source = gemfile_source else - sources.get_with_fallback(lockfile_source) + # Replace the locked dependency's source with the default source, if the locked source is no longer in the Gemfile + s.source = default_source unless sources.get(lockfile_source) end next if @unlock[:sources].include?(s.source.name) diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb index 63798db941ed5d..4419695b7ff1ab 100644 --- a/lib/bundler/source_list.rb +++ b/lib/bundler/source_list.rb @@ -101,10 +101,6 @@ def get(source) source_list_for(source).find {|s| equivalent_source?(source, s) } end - def get_with_fallback(source) - get(source) || default_source - end - def lock_sources lock_other_sources + lock_rubygems_sources end From e92ace6be7e6501bfb7dec43a8d8abdf19ae80f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 21 Jul 2023 20:20:07 +0200 Subject: [PATCH 071/158] [rubygems/rubygems] Remove unneeded stuff This should be only for path sources, and unrelated to git. https://github.com/rubygems/rubygems/commit/0d8f31eeed --- lib/bundler/definition.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 8d90e2501d52dc..241a97fc7dc906 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -832,9 +832,9 @@ def converge_specs(specs) if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec) new_specs = begin s.source.specs - rescue PathError, GitError + rescue PathError # if we won't need the source (according to the lockfile), - # don't error if the path/git source isn't available + # don't error if the path source isn't available next if specs. for(requested_dependencies, false). none? {|locked_spec| locked_spec.source == s.source } From 4a3777bf6ba78473ace61fbaa663faaa4e7068e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 21 Jul 2023 20:30:41 +0200 Subject: [PATCH 072/158] [rubygems/rubygems] Extract s.name to a variable https://github.com/rubygems/rubygems/commit/689c39b42f --- lib/bundler/definition.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 241a97fc7dc906..2fbd56e5d7596e 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -810,6 +810,7 @@ def converge_specs(specs) @specs_that_changed_sources = [] specs.each do |s| + name = s.name dep = @dependencies.find {|d| s.satisfies?(d) } lockfile_source = s.source @@ -848,11 +849,11 @@ def converge_specs(specs) else # If the spec is no longer in the path source, unlock it. This # commonly happens if the version changed in the gemspec - @unlock[:gems] << s.name + @unlock[:gems] << name end end - if dep.nil? && requested_dependencies.find {|d| s.name == d.name } + if dep.nil? && requested_dependencies.find {|d| name == d.name } @unlock[:gems] << s.name else converged << s From 2e04336b6718b4ad59f9563b388d34cde24704ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 21 Jul 2023 21:01:58 +0200 Subject: [PATCH 073/158] [rubygems/rubygems] Fix git source conservativeness https://github.com/rubygems/rubygems/commit/9a0e0dfd5b --- lib/bundler/definition.rb | 1 + lib/bundler/source/git.rb | 7 +++ spec/bundler/lock/lockfile_spec.rb | 86 ++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 2fbd56e5d7596e..564530a98cdf1a 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -819,6 +819,7 @@ def converge_specs(specs) @specs_that_changed_sources << s if gemfile_source != lockfile_source deps << dep if !dep.source || lockfile_source.include?(dep.source) + @unlock[:gems] << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source # Replace the locked dependency's source with the equivalent source from the Gemfile s.source = gemfile_source diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb index 4a9f3731bd1f56..adbce5fce4962c 100644 --- a/lib/bundler/source/git.rb +++ b/lib/bundler/source/git.rb @@ -67,6 +67,13 @@ def eql?(other) alias_method :==, :eql? + def include?(other) + other.is_a?(Git) && uri == other.uri && + name == other.name && + glob == other.glob && + submodules == other.submodules + end + def to_s begin at = humanized_ref || current_branch diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index 4b78cb261d2556..ccf23a9e3c2144 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -540,6 +540,92 @@ G end + it "is conservative with dependencies of git gems" do + build_repo4 do + build_gem "orm_adapter", "0.4.1" + build_gem "orm_adapter", "0.5.0" + end + + FileUtils.mkdir_p lib_path("ckeditor/lib") + + @remote = build_git("ckeditor_remote", :bare => true) + + build_git "ckeditor", :path => lib_path("ckeditor") do |s| + s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.7'" + s.version = "4.0.7" + s.add_dependency "orm_adapter" + end + + update_git "ckeditor", :path => lib_path("ckeditor"), :remote => file_uri_for(@remote.path) + update_git "ckeditor", :path => lib_path("ckeditor"), :tag => "v4.0.7" + old_git = update_git "ckeditor", :path => lib_path("ckeditor"), :push => "v4.0.7" + + update_git "ckeditor", :path => lib_path("ckeditor"), :gemspec => true do |s| + s.write "lib/ckeditor.rb", "CKEDITOR = '4.0.8'" + s.version = "4.0.8" + s.add_dependency "orm_adapter" + end + update_git "ckeditor", :path => lib_path("ckeditor"), :tag => "v4.0.8" + + new_git = update_git "ckeditor", :path => lib_path("ckeditor"), :push => "v4.0.8" + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "ckeditor", :git => "#{@remote.path}", :tag => "v4.0.8" + G + + lockfile <<~L + GIT + remote: #{@remote.path} + revision: #{old_git.ref_for("v4.0.7")} + tag: v4.0.7 + specs: + ckeditor (4.0.7) + orm_adapter + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + orm_adapter (0.4.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + ckeditor! + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "lock" + + # Bumps the git gem, but keeps its dependency locked + expect(lockfile).to eq <<~L + GIT + remote: #{@remote.path} + revision: #{new_git.ref_for("v4.0.8")} + tag: v4.0.8 + specs: + ckeditor (4.0.8) + orm_adapter + + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + orm_adapter (0.4.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + ckeditor! + + BUNDLED WITH + #{Bundler::VERSION} + L + end + it "serializes pinned path sources to the lockfile" do build_lib "foo" From c076ac8a5f5cc2850ac59bc2239354c33fc05961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 10 Aug 2023 20:38:07 +0200 Subject: [PATCH 074/158] [rubygems/rubygems] Use better status for authentication failures https://github.com/rubygems/rubygems/commit/ffa395411f --- .../artifice/compact_index_strict_basic_authentication.rb | 2 +- .../support/artifice/endpoint_strict_basic_authentication.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb b/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb index fa25c4eca1492b..96259385e77c54 100644 --- a/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb +++ b/spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb @@ -10,7 +10,7 @@ class CompactIndexStrictBasicAuthentication < CompactIndexAPI # Only accepts password == "password" unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz" - halt 403, "Authentication failed" + halt 401, "Authentication failed" end end end diff --git a/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb index 8ce1bdd4adf028..dff360c5c535c2 100644 --- a/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb +++ b/spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb @@ -10,7 +10,7 @@ class EndpointStrictBasicAuthentication < Endpoint # Only accepts password == "password" unless env["HTTP_AUTHORIZATION"] == "Basic dXNlcjpwYXNz" - halt 403, "Authentication failed" + halt 401, "Authentication failed" end end end From e678affe70d7597464368197fb55d277f0c26bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 10 Aug 2023 17:23:32 +0200 Subject: [PATCH 075/158] [rubygems/rubygems] Bad auth should not fallback either https://github.com/rubygems/rubygems/commit/ba3ea27869 --- lib/bundler/fetcher/compact_index.rb | 2 +- spec/bundler/install/gems/compact_index_spec.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb index f9db920c323c5c..d3160251cb0056 100644 --- a/lib/bundler/fetcher/compact_index.rb +++ b/lib/bundler/fetcher/compact_index.rb @@ -15,7 +15,7 @@ def self.compact_index_request(method_name) method.bind(self).call(*args, &blk) rescue NetworkDownError, CompactIndexClient::Updater::MisMatchedChecksumError => e raise HTTPError, e.message - rescue AuthenticationRequiredError + rescue AuthenticationRequiredError, BadAuthenticationError # Fail since we got a 401 from the server. raise rescue HTTPError => e diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb index f0717de36df549..1d193a0f202e15 100644 --- a/spec/bundler/install/gems/compact_index_spec.rb +++ b/spec/bundler/install/gems/compact_index_spec.rb @@ -683,6 +683,15 @@ def require(*args) bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false expect(err).to include("Bad username or password") end + + it "does not fallback to old dependency API if bad authentication is provided" do + bundle "config set #{source_hostname} #{user}:wrong" + + bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false, :verbose => true + expect(err).to include("Bad username or password") + expect(out).to include("HTTP 401 Unauthorized http://user@localgemserver.test/versions") + expect(out).not_to include("HTTP 401 Unauthorized http://user@localgemserver.test/api/v1/dependencies") + end end describe "with no password" do From fe240b672b709e800f2b4fb996f04f2005329dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 10 Aug 2023 21:37:15 +0200 Subject: [PATCH 076/158] [rubygems/rubygems] Show better error when PAT can't authenticate to a private server Before: ``` Fetching gem metadata from https://rubygems.org/........ Fetching source index from https://rubygems.pkg.github.com/my-org/ Bad username or password for https://x-access-token@rubygems.pkg.github.com/my-org/. Please double-check your credentials and correct them. ``` After: ``` Fetching gem metadata from https://rubygems.org/........ Fetching source index from https://rubygems.pkg.github.com/my-org/ Access token could not be authenticated for https://x-access-token@rubygems.pkg.github.com/my-org/. Make sure it's valid and has the necessary scopes configured. ``` https://github.com/rubygems/rubygems/commit/2ae69c964a --- lib/bundler/fetcher.rb | 12 +++++++++- lib/bundler/fetcher/downloader.rb | 2 ++ lib/bundler/fetcher/index.rb | 3 +-- .../bundler/fetcher/downloader_spec.rb | 10 ++++++++ spec/bundler/bundler/fetcher/index_spec.rb | 23 +++---------------- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb index e12c15af8a8a24..2119799f688437 100644 --- a/lib/bundler/fetcher.rb +++ b/lib/bundler/fetcher.rb @@ -61,6 +61,16 @@ def initialize(remote_uri) end end + # This error is raised if HTTP authentication is correct, but lacks + # necessary permissions. + class AuthenticationForbiddenError < HTTPError + def initialize(remote_uri) + remote_uri = filter_uri(remote_uri) + super "Access token could not be authenticated for #{remote_uri}.\n" \ + "Make sure it's valid and has the necessary scopes configured." + end + end + # Exceptions classes that should bypass retry attempts. If your password didn't work the # first time, it's not going to the third time. NET_ERRORS = [:HTTPBadGateway, :HTTPBadRequest, :HTTPFailedDependency, @@ -70,7 +80,7 @@ def initialize(remote_uri) :HTTPRequestURITooLong, :HTTPUnauthorized, :HTTPUnprocessableEntity, :HTTPUnsupportedMediaType, :HTTPVersionNotSupported].freeze FAIL_ERRORS = begin - fail_errors = [AuthenticationRequiredError, BadAuthenticationError, FallbackError] + fail_errors = [AuthenticationRequiredError, BadAuthenticationError, AuthenticationForbiddenError, FallbackError] fail_errors << Gem::Requirement::BadRequirementError fail_errors.concat(NET_ERRORS.map {|e| Net.const_get(e) }) end.freeze diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb index 28d33f1aed3cbb..3062899e0e7a90 100644 --- a/lib/bundler/fetcher/downloader.rb +++ b/lib/bundler/fetcher/downloader.rb @@ -41,6 +41,8 @@ def fetch(uri, headers = {}, counter = 0) when Net::HTTPUnauthorized raise BadAuthenticationError, uri.host if uri.userinfo raise AuthenticationRequiredError, uri.host + when Net::HTTPForbidden + raise AuthenticationForbiddenError, uri.host when Net::HTTPNotFound raise FallbackError, "Net::HTTPNotFound: #{filtered_uri}" else diff --git a/lib/bundler/fetcher/index.rb b/lib/bundler/fetcher/index.rb index 6bb9fcc1939388..c623647f01cdcc 100644 --- a/lib/bundler/fetcher/index.rb +++ b/lib/bundler/fetcher/index.rb @@ -15,8 +15,7 @@ def specs(_gem_names) raise BadAuthenticationError, remote_uri if remote_uri.userinfo raise AuthenticationRequiredError, remote_uri when /403/ - raise BadAuthenticationError, remote_uri if remote_uri.userinfo - raise AuthenticationRequiredError, remote_uri + raise AuthenticationForbiddenError, remote_uri else raise HTTPError, "Could not fetch specs from #{display_uri} due to underlying error <#{e.message}>" end diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb index 0412ddb83a3a54..22aa3a8b0c6809 100644 --- a/spec/bundler/bundler/fetcher/downloader_spec.rb +++ b/spec/bundler/bundler/fetcher/downloader_spec.rb @@ -98,6 +98,16 @@ end end + context "when the request response is a Net::HTTPForbidden" do + let(:http_response) { Net::HTTPForbidden.new("1.1", 403, "Forbidden") } + let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") } + + it "should raise a Bundler::Fetcher::AuthenticationForbiddenError with the uri host" do + expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationForbiddenError, + /Access token could not be authenticated for www.uri-to-fetch.com/) + end + end + context "when the request response is a Net::HTTPNotFound" do let(:http_response) { Net::HTTPNotFound.new("1.1", 404, "Not Found") } diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb index f0db07583cb4ab..971b64ce8f5538 100644 --- a/spec/bundler/bundler/fetcher/index_spec.rb +++ b/spec/bundler/bundler/fetcher/index_spec.rb @@ -63,26 +63,9 @@ context "when a 403 response occurs" do let(:error_message) { "403" } - before do - allow(remote_uri).to receive(:userinfo).and_return(userinfo) - end - - context "and there was userinfo" do - let(:userinfo) { double(:userinfo) } - - it "should raise a Bundler::Fetcher::BadAuthenticationError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError, - %r{Bad username or password for http://remote-uri.org}) - end - end - - context "and there was no userinfo" do - let(:userinfo) { nil } - - it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do - expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError, - %r{Authentication is required for http://remote-uri.org}) - end + it "should raise a Bundler::Fetcher::AuthenticationForbiddenError" do + expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationForbiddenError, + %r{Access token could not be authenticated for http://remote-uri.org}) end end From 0982c5fa00f6163d04b17229e72d128263b98d50 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Wed, 9 Aug 2023 11:55:19 +0900 Subject: [PATCH 077/158] Resync Lrama v0.5.3 Previous sync included unrelated files and missed template file update. --- tool/lrama/exe/lex_state | 14 - tool/lrama/lib/lrama/irb.rb | 8 - tool/lrama/lib/lrama/irb/load_grammar.rb | 9 - tool/lrama/lib/lrama/json_reporter.rb | 28 -- tool/lrama/template/bison/yacc.c | 363 +++++++++++++++++++++++ 5 files changed, 363 insertions(+), 59 deletions(-) delete mode 100755 tool/lrama/exe/lex_state delete mode 100644 tool/lrama/lib/lrama/irb.rb delete mode 100644 tool/lrama/lib/lrama/irb/load_grammar.rb delete mode 100644 tool/lrama/lib/lrama/json_reporter.rb diff --git a/tool/lrama/exe/lex_state b/tool/lrama/exe/lex_state deleted file mode 100755 index 0acdeaadd6fa31..00000000000000 --- a/tool/lrama/exe/lex_state +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env ruby - - -$LOAD_PATH << File.join(__dir__, "../lib") -require "lrama" - -grammar_file = ARGV.shift -y = File.read(grammar_file) -warning = Lrama::Warning.new -grammar = Lrama::Parser.new(y).parse -states = Lrama::States.new(grammar, warning) -states.compute - -Lrama::LexState.new(states).compute diff --git a/tool/lrama/lib/lrama/irb.rb b/tool/lrama/lib/lrama/irb.rb deleted file mode 100644 index 6f093cdedde1de..00000000000000 --- a/tool/lrama/lib/lrama/irb.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "lrama/irb/load_grammar" - -# You need to explicitly require this file to add irb commands -# See: "lib/irb/extend-command.rb" in ruby/irb -module Lrama - module IRB - end -end diff --git a/tool/lrama/lib/lrama/irb/load_grammar.rb b/tool/lrama/lib/lrama/irb/load_grammar.rb deleted file mode 100644 index a4285eaa004991..00000000000000 --- a/tool/lrama/lib/lrama/irb/load_grammar.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'irb/cmd/nop' - -module Lrama - module IRB - class LoadGrammar < IRB::ExtendCommand::Nop - - end - end -end diff --git a/tool/lrama/lib/lrama/json_reporter.rb b/tool/lrama/lib/lrama/json_reporter.rb deleted file mode 100644 index f6cd2532bd9a61..00000000000000 --- a/tool/lrama/lib/lrama/json_reporter.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'json' - -module Lrama - class JsonReporter - include Lrama::Report::Duration - - def initialize(states) - @states = states - end - - def report(io, **options) - report_duration(:report) do - _report(io, **options) - end - end - - private - - def _report(io, grammar: false, states: false, itemsets: false, lookaheads: false, solved: false, verbose: false) - # TODO: Unused terms - # TODO: Unused rules - - report_conflicts(io) - report_grammar(io) if grammar - report_states(io, itemsets, lookaheads, solved, verbose) - end - end -end diff --git a/tool/lrama/template/bison/yacc.c b/tool/lrama/template/bison/yacc.c index 857afb26c0e05b..61d23d506b5137 100644 --- a/tool/lrama/template/bison/yacc.c +++ b/tool/lrama/template/bison/yacc.c @@ -542,6 +542,13 @@ static const <%= output.int_type_for(output.context.yytranslate) %> yytranslate[ <%= output.yytranslate %> }; +<%- if output.error_recovery -%> +/* YYTRANSLATE_INVERTED[SYMBOL-NUM] -- Token number corresponding to SYMBOL-NUM */ +static const <%= output.int_type_for(output.context.yytranslate_inverted) %> yytranslate_inverted[] = +{ +<%= output.yytranslate_inverted %> +}; +<%- end -%> #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const <%= output.int_type_for(output.context.yyrline) %> yyrline[] = @@ -1211,6 +1218,303 @@ yydestruct (const char *yymsg, +<%- if output.error_recovery -%> +#ifndef YYMAXREPAIR +# define YYMAXREPAIR 3 +#endif + +enum repair_type { + insert, + delete, + shift, +}; + +struct repair { + enum repair_type type; + yysymbol_kind_t term; +}; +typedef struct repair repair; + +struct repairs { + /* For debug */ + int id; + /* For breadth-first traversing */ + struct repairs *next; + YYPTRDIFF_T stack_length; + /* Bottom of states */ + yy_state_t *states; + /* Top of states */ + yy_state_t *state; + /* repair length */ + int repair_length; + /* */ + struct repairs *prev_repair; + struct repair repair; +}; +typedef struct repairs repairs; + +struct yy_term { + yysymbol_kind_t kind; + YYSTYPE value; + YYLTYPE location; +}; +typedef struct yy_term yy_term; + +struct repair_terms { + int id; + int length; + yy_term terms[]; +}; +typedef struct repair_terms repair_terms; + +static void +yy_error_token_initialize (yysymbol_kind_t yykind, YYSTYPE * const yyvaluep, YYLTYPE * const yylocationp<%= output.user_formals %>) +{ + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +switch (yykind) + { +<%= output.symbol_actions_for_error_token -%> + default: + break; + } + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + +static repair_terms * +yy_create_repair_terms(repairs *reps) +{ + repairs *r = reps; + repair_terms *rep_terms; + int count = 0; + + while (r->prev_repair) + { + count++; + r = r->prev_repair; + } + + rep_terms = (repair_terms *) malloc (sizeof (repair_terms) + sizeof (yy_term) * count); + rep_terms->id = reps->id; + rep_terms->length = count; + + r = reps; + while (r->prev_repair) + { + rep_terms->terms[count-1].kind = r->repair.term; + count--; + r = r->prev_repair; + } + + return rep_terms; +} + +static void +yy_print_repairs(repairs *reps) +{ + repairs *r = reps; + + fprintf (stderr, + "id: %d, repair_length: %d, repair_state: %d, prev_repair_id: %d\n", + reps->id, reps->repair_length, *reps->state, reps->prev_repair->id); + + while (r->prev_repair) + { + fprintf (stderr, "%s ", yysymbol_name (r->repair.term)); + r = r->prev_repair; + } + + fprintf (stderr, "\n"); +} + +static void +yy_print_repair_terms(repair_terms *rep_terms) +{ + for (int i = 0; i < rep_terms->length; i++) + fprintf (stderr, "%s ", yysymbol_name (rep_terms->terms[i].kind)); + + fprintf (stderr, "\n"); +} + +static void +yy_free_repairs(repairs *reps) +{ + while (reps) + { + repairs *r = reps; + reps = reps->next; + free (r->states); + free (r); + } +} + +static int +yy_process_repairs(repairs *reps, yysymbol_kind_t token) +{ + int yyn; + int yystate = *reps->state; + int yylen = 0; + yysymbol_kind_t yytoken = token; + + goto yyrecover_backup; + +yyrecover_newstate: + // TODO: check reps->stack_length + reps->state += 1; + *reps->state = (yy_state_t) yystate; + + +yyrecover_backup: + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yyrecover_default; + + /* "Reading a token" */ + if (yytoken == YYSYMBOL_YYEMPTY) + return 1; + + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yyrecover_default; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyrecover_errlab; + yyn = -yyn; + goto yyrecover_reduce; + } + + /* shift */ + yystate = yyn; + yytoken = YYSYMBOL_YYEMPTY; + goto yyrecover_newstate; + + +yyrecover_default: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyrecover_errlab; + goto yyrecover_reduce; + + +yyrecover_reduce: + yylen = yyr2[yyn]; + /* YYPOPSTACK */ + reps->state -= yylen; + yylen = 0; + + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *reps->state; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *reps->state + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yyrecover_newstate; + +yyrecover_errlab: + return 0; +} + +static repair_terms * +yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar) +{ + yysymbol_kind_t yytoken = YYTRANSLATE (yychar); + repair_terms *rep_terms = YY_NULLPTR; + int count = 0; + + repairs *head = (repairs *) malloc (sizeof (repairs)); + repairs *current = head; + repairs *tail = head; + YYPTRDIFF_T stack_length = yyssp - yyss + 1; + + head->id = count; + head->next = 0; + head->stack_length = stack_length; + head->states = (yy_state_t *) malloc (sizeof (yy_state_t) * (stack_length)); + head->state = head->states + (yyssp - yyss); + YYCOPY (head->states, yyss, stack_length); + head->repair_length = 0; + head->prev_repair = 0; + + stack_length = (stack_length * 2 > 100) ? (stack_length * 2) : 100; + count++; + + while (current) + { + int yystate = *current->state; + int yyn = yypact[yystate]; + /* See also: yypcontext_expected_tokens */ + if (!yypact_value_is_default (yyn)) + { + int yyxbegin = yyn < 0 ? -yyn : 0; + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + { + if (yyx != YYSYMBOL_YYerror) + { + if (current->repair_length + 1 > YYMAXREPAIR) + continue; + + repairs *new = (repairs *) malloc (sizeof (repairs)); + new->id = count; + new->next = 0; + new->stack_length = stack_length; + new->states = (yy_state_t *) malloc (sizeof (yy_state_t) * (stack_length)); + new->state = new->states + (current->state - current->states); + YYCOPY (new->states, current->states, current->state - current->states + 1); + new->repair_length = current->repair_length + 1; + new->prev_repair = current; + new->repair.type = insert; + new->repair.term = (yysymbol_kind_t) yyx; + + /* Process PDA assuming next token is yyx */ + if (! yy_process_repairs (new, yyx)) + { + free (new); + continue; + } + + tail->next = new; + tail = new; + count++; + + if (yyx == yytoken) + { + rep_terms = yy_create_repair_terms (current); + fprintf (stderr, "repair_terms found. id: %d, length: %d\n", rep_terms->id, rep_terms->length); + yy_print_repairs (current); + yy_print_repair_terms (rep_terms); + + goto done; + } + + fprintf (stderr, + "New repairs is enqueued. count: %d, yystate: %d, yyx: %d\n", + count, yystate, yyx); + yy_print_repairs (new); + } + } + } + + current = current->next; + } + +done: + + yy_free_repairs(head); + + if (!rep_terms) + { + fprintf (stderr, "repair_terms not found\n"); + } + + return rep_terms; +} +<%- end -%> @@ -1281,6 +1585,12 @@ YYLTYPE yylloc = yyloc_default; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[3]; +<%- if output.error_recovery -%> + repair_terms *rep_terms = 0; + yy_term term_backup; + int rep_terms_index; + int yychar_backup; +<%- end -%> /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; @@ -1415,6 +1725,36 @@ YYLTYPE yylloc = yyloc_default; /* Not known => get a lookahead token if don't already have one. */ +<%- if output.error_recovery -%> + if (yychar == YYEMPTY && rep_terms) + { + + if (rep_terms_index < rep_terms->length) + { + YYDPRINTF ((stderr, "An error recovery token is used\n")); + yy_term term = rep_terms->terms[rep_terms_index]; + yytoken = term.kind; + yylval = term.value; + yylloc = term.location; + yychar = yytranslate_inverted[yytoken]; + YY_SYMBOL_PRINT ("Next error recovery token is", yytoken, &yylval, &yylloc<%= output.user_args %>); + rep_terms_index++; + } + else + { + YYDPRINTF ((stderr, "Error recovery is completed\n")); + yytoken = term_backup.kind; + yylval = term_backup.value; + yylloc = term_backup.location; + yychar = yychar_backup; + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc<%= output.user_args %>); + + free (rep_terms); + rep_terms = 0; + yychar_backup = 0; + } + } +<%- end -%> /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ if (yychar == YYEMPTY) { @@ -1639,6 +1979,29 @@ YYLTYPE yylloc = yyloc_default; | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: +<%- if output.error_recovery -%> + { + rep_terms = yyrecover (yyss, yyssp, yychar); + if (rep_terms) + { + for (int i = 0; i < rep_terms->length; i++) + { + yy_term *term = &rep_terms->terms[i]; + yy_error_token_initialize (term->kind, &term->value, &term->location<%= output.user_args %>); + } + + yychar_backup = yychar; + /* Can be packed into (the tail of) rep_terms? */ + term_backup.kind = yytoken; + term_backup.value = yylval; + term_backup.location = yylloc; + rep_terms_index = 0; + yychar = YYEMPTY; + + goto yybackup; + } + } +<%- end -%> yyerrstatus = 3; /* Each real token shifted decrements this. */ /* Pop stack until we find a state that shifts the error token. */ From 5a40f7db54dfcc7dadb75dde32c25b88c78d6a85 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Wed, 16 Aug 2023 11:13:41 +0100 Subject: [PATCH 078/158] [ruby/irb] Encapsulate input details in Statement objects (https://github.com/ruby/irb/pull/682) * Introduce Statement class * Split Statement class for better clarity https://github.com/ruby/irb/commit/65e8e68690 --- lib/irb.rb | 42 ++++-------------------- lib/irb/ruby-lex.rb | 25 +++++++++++--- lib/irb/statement.rb | 78 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 41 deletions(-) create mode 100644 lib/irb/statement.rb diff --git a/lib/irb.rb b/lib/irb.rb index c884d70a67b7e2..93ab6370ed68d1 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -570,26 +570,19 @@ def eval_input configure_io - @scanner.each_top_level_statement do |line, line_no, is_assignment| + @scanner.each_top_level_statement do |statement, line_no| signal_status(:IN_EVAL) do begin # If the integration with debugger is activated, we need to handle certain input differently - if @context.with_debugger - command_class = load_command_class(line) - # First, let's pass debugging command's input to debugger - # Secondly, we need to let debugger evaluate non-command input - # Otherwise, the expression will be evaluated in the debugger's main session thread - # This is the only way to run the user's program in the expected thread - if !command_class || ExtendCommand::DebugCommand > command_class - return line - end + if @context.with_debugger && statement.should_be_handled_by_debugger? + return statement.code end - evaluate_line(line, line_no) + @context.evaluate(statement.evaluable_code, line_no) # Don't echo if the line ends with a semicolon - if @context.echo? && !line.match?(/;\s*\z/) - if is_assignment + if @context.echo? && !statement.suppresses_echo? + if statement.is_assignment? if @context.echo_on_assignment? output_value(@context.echo_on_assignment? == :truncate) end @@ -659,29 +652,6 @@ def configure_io end end - def evaluate_line(line, line_no) - # Transform a non-identifier alias (@, $) or keywords (next, break) - command, args = line.split(/\s/, 2) - if original = @context.command_aliases[command.to_sym] - line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s) - command = original - end - - # Hook command-specific transformation - command_class = ExtendCommandBundle.load_command(command) - if command_class&.respond_to?(:transform_args) - line = "#{command} #{command_class.transform_args(args)}" - end - - @context.evaluate(line, line_no) - end - - def load_command_class(line) - command, _ = line.split(/\s/, 2) - command_name = @context.command_aliases[command.to_sym] - ExtendCommandBundle.load_command(command_name || command) - end - def convert_invalid_byte_sequence(str, enc) str.force_encoding(enc) str.scrub { |c| diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index 282e6ef05f225f..3a0173a6be2ffe 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -7,6 +7,7 @@ require "ripper" require "jruby" if RUBY_ENGINE == "jruby" require_relative "nesting_parser" +require_relative "statement" # :stopdoc: class RubyLex @@ -221,16 +222,30 @@ def each_top_level_statement break unless code if code != "\n" - code.force_encoding(@context.io.encoding) - yield code, @line_no, assignment_expression?(code) + yield build_statement(code), @line_no end increase_line_no(code.count("\n")) rescue TerminateLineInput end end - def assignment_expression?(line) - # Try to parse the line and check if the last of possibly multiple + def build_statement(code) + code.force_encoding(@context.io.encoding) + command_or_alias, arg = code.split(/\s/, 2) + # Transform a non-identifier alias (@, $) or keywords (next, break) + command_name = @context.command_aliases[command_or_alias.to_sym] + command = command_name || command_or_alias + command_class = IRB::ExtendCommandBundle.load_command(command) + + if command_class + IRB::Statement::Command.new(code, command, arg, command_class) + else + IRB::Statement::Expression.new(code, assignment_expression?(code)) + end + end + + def assignment_expression?(code) + # Try to parse the code and check if the last of possibly multiple # expressions is an assignment type. # If the expression is invalid, Ripper.sexp should return nil which will @@ -239,7 +254,7 @@ def assignment_expression?(line) # array of parsed expressions. The first element of each expression is the # expression's type. verbose, $VERBOSE = $VERBOSE, nil - code = "#{RubyLex.generate_local_variables_assign_code(@context.local_variables) || 'nil;'}\n#{line}" + code = "#{RubyLex.generate_local_variables_assign_code(@context.local_variables) || 'nil;'}\n#{code}" # Get the last node_type of the line. drop(1) is to ignore the local_variables_assign_code part. node_type = Ripper.sexp(code)&.dig(1)&.drop(1)&.dig(-1, 0) ASSIGNMENT_NODE_TYPES.include?(node_type) diff --git a/lib/irb/statement.rb b/lib/irb/statement.rb new file mode 100644 index 00000000000000..9493c3ffb1277a --- /dev/null +++ b/lib/irb/statement.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +module IRB + class Statement + attr_reader :code + + def is_assignment? + raise NotImplementedError + end + + def suppresses_echo? + raise NotImplementedError + end + + def should_be_handled_by_debugger? + raise NotImplementedError + end + + def evaluable_code + raise NotImplementedError + end + + class Expression < Statement + def initialize(code, is_assignment) + @code = code + @is_assignment = is_assignment + end + + def suppresses_echo? + @code.match?(/;\s*\z/) + end + + def should_be_handled_by_debugger? + true + end + + def is_assignment? + @is_assignment + end + + def evaluable_code + @code + end + end + + class Command < Statement + def initialize(code, command, arg, command_class) + @code = code + @command = command + @arg = arg + @command_class = command_class + end + + def is_assignment? + false + end + + def suppresses_echo? + false + end + + def should_be_handled_by_debugger? + IRB::ExtendCommand::DebugCommand > @command_class + end + + def evaluable_code + # Hook command-specific transformation to return valid Ruby code + if @command_class.respond_to?(:transform_args) + arg = @command_class.transform_args(@arg) + else + arg = @arg + end + + [@command, arg].compact.join(' ') + end + end + end +end From 089227e94823542acfdafa68541d330eee42ffea Mon Sep 17 00:00:00 2001 From: haseponpon <36598331+p0pemaru@users.noreply.github.com> Date: Wed, 16 Aug 2023 22:51:17 +0900 Subject: [PATCH 079/158] [DOC] Specify the unit of return value for `Time#-` --- time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/time.c b/time.c index 617326f9961647..d0c1d0811e1804 100644 --- a/time.c +++ b/time.c @@ -4410,7 +4410,7 @@ time_plus(VALUE time1, VALUE time2) * * When +other_time+ is given, * returns a Float whose value is the difference - * of the numeric values of +self+ and +other_time+: + * of the numeric values of +self+ and +other_time+ in seconds: * * t - t # => 0.0 * From 82e480ff40cd41de993b92ddc42ef79a807ff2be Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Aug 2023 15:45:27 +0900 Subject: [PATCH 080/158] Silent test-all on AppVeyor --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 6865393b1aefb8..0a25dceab43a46 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -93,7 +93,7 @@ for: - nmake -l "TESTOPTS=-v -q" btest - nmake -l "TESTOPTS=-v -q" test-basic - >- - nmake -l "TESTOPTS=-v --timeout-scale=3.0 + nmake -l "TESTOPTS=--timeout-scale=3.0 --excludes=../test/.excludes/_appveyor -j%JOBS% --exclude win32ole --exclude test_bignum From f0edcd8283e1aeda9ff2d04926ec8041b421f890 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Aug 2023 20:45:29 +0900 Subject: [PATCH 081/158] Extract platform dependent part as `fdopen_internal` --- io.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/io.c b/io.c index f54f01963fe3b2..90b6cc1db0bf5f 100644 --- a/io.c +++ b/io.c @@ -6966,8 +6966,8 @@ rb_sysopen(VALUE fname, int oflags, mode_t perm) return fd; } -FILE * -rb_fdopen(int fd, const char *modestr) +static inline FILE * +fdopen_internal(int fd, const char *modestr) { FILE *file; @@ -6976,24 +6976,25 @@ rb_fdopen(int fd, const char *modestr) #endif file = fdopen(fd, modestr); if (!file) { - int e = errno; -#if defined(__sun) - if (e == 0) { - rb_gc(); - errno = 0; - file = fdopen(fd, modestr); - } - else +#ifdef _WIN32 + if (errno == 0) errno = EINVAL; +#elif defined(__sun) + if (errno == 0) errno = EMFILE; #endif + } + return file; +} + +FILE * +rb_fdopen(int fd, const char *modestr) +{ + FILE *file = fdopen_internal(fd, modestr); + if (!file) { + int e = errno; if (rb_gc_for_fd(e)) { - file = fdopen(fd, modestr); + file = fdopen_internal(fd, modestr); } if (!file) { -#ifdef _WIN32 - if (e == 0) e = EINVAL; -#elif defined(__sun) - if (e == 0) e = EMFILE; -#endif rb_syserr_fail(e, 0); } } From 7d3634a121736eea1a43a332b9abd0540d3a6300 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Aug 2023 20:47:28 +0900 Subject: [PATCH 082/158] Extract GC for fd parts as `TRY_WITH_GC ` --- io.c | 57 ++++++++++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/io.c b/io.c index 90b6cc1db0bf5f..6e27ed6273ae35 100644 --- a/io.c +++ b/io.c @@ -1063,20 +1063,24 @@ rb_gc_for_fd(int err) return 0; } +/* try `expr` upto twice while it returns false and `errno` + * is to GC. Each `errno`s are available as `first_errno` and + * `retried_errno` respectively */ +#define TRY_WITH_GC(expr) \ + for (int first_errno, retried_errno = 0, retried = 0; \ + (!retried && \ + !(expr) && \ + (!rb_gc_for_fd(first_errno = errno) || !(expr)) && \ + (retried_errno = errno, 1)); \ + (void)retried_errno, retried = 1) + static int ruby_dup(int orig) { - int fd; + int fd = -1; - fd = rb_cloexec_dup(orig); - if (fd < 0) { - int e = errno; - if (rb_gc_for_fd(e)) { - fd = rb_cloexec_dup(orig); - } - if (fd < 0) { - rb_syserr_fail(e, 0); - } + TRY_WITH_GC((fd = rb_cloexec_dup(orig)) >= 0) { + rb_syserr_fail(first_errno, 0); } rb_update_max_fd(fd); return fd; @@ -6945,7 +6949,7 @@ rb_sysopen_internal(struct sysopen_struct *data) static int rb_sysopen(VALUE fname, int oflags, mode_t perm) { - int fd; + int fd = -1; struct sysopen_struct data; data.fname = rb_str_encode_ospath(fname); @@ -6953,15 +6957,8 @@ rb_sysopen(VALUE fname, int oflags, mode_t perm) data.oflags = oflags; data.perm = perm; - fd = rb_sysopen_internal(&data); - if (fd < 0) { - int e = errno; - if (rb_gc_for_fd(e)) { - fd = rb_sysopen_internal(&data); - } - if (fd < 0) { - rb_syserr_fail_path(e, fname); - } + TRY_WITH_GC((fd = rb_sysopen_internal(&data)) >= 0) { + rb_syserr_fail_path(first_errno, fname); } return fd; } @@ -6988,15 +6985,10 @@ fdopen_internal(int fd, const char *modestr) FILE * rb_fdopen(int fd, const char *modestr) { - FILE *file = fdopen_internal(fd, modestr); - if (!file) { - int e = errno; - if (rb_gc_for_fd(e)) { - file = fdopen_internal(fd, modestr); - } - if (!file) { - rb_syserr_fail(e, 0); - } + FILE *file = 0; + + TRY_WITH_GC((file = fdopen_internal(fd, modestr)) != 0) { + rb_syserr_fail(first_errno, 0); } /* xxx: should be _IONBF? A buffer in FILE may have trouble. */ @@ -7287,12 +7279,7 @@ int rb_pipe(int *pipes) { int ret; - ret = rb_cloexec_pipe(pipes); - if (ret < 0) { - if (rb_gc_for_fd(errno)) { - ret = rb_cloexec_pipe(pipes); - } - } + TRY_WITH_GC((ret = rb_cloexec_pipe(pipes)) >= 0); if (ret == 0) { rb_update_max_fd(pipes[0]); rb_update_max_fd(pipes[1]); From 0d7e847153ed5b6006b686085207527ff2f28853 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Aug 2023 23:52:04 +0900 Subject: [PATCH 083/158] Consider the special node when printing Appreciation to the reporter, Huichiao Tsai . --- parse.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index c1c8a7514b0ce8..d5942983eacd14 100644 --- a/parse.y +++ b/parse.y @@ -1466,7 +1466,10 @@ static int looking_at_eol_p(struct parser_params *p); %define parse.error verbose %printer { #ifndef RIPPER - if ($$) { + if ($$ == (NODE *)-1) { + rb_parser_printf(p, "NODE_SPECIAL"); + } + else if ($$) { rb_parser_printf(p, "%s", ruby_node_name(nd_type($$))); } #else From f339937abb6a5057a7ed57c52dad708349db5412 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Aug 2023 00:37:47 +0900 Subject: [PATCH 084/158] RJIT: Remove macros inherited from MJIT but no longer used --- configure.ac | 24 ------------------------ defs/gmake.mk | 3 --- template/Makefile.in | 6 ------ 3 files changed, 33 deletions(-) diff --git a/configure.ac b/configure.ac index 2cc4e6beba4d6e..caacfebbedce3d 100644 --- a/configure.ac +++ b/configure.ac @@ -420,21 +420,6 @@ AC_SUBST(OUTFLAG) AC_SUBST(COUTFLAG) AC_SUBST(CSRCFLAG) -: ${RJIT_CC=$CC} -AS_IF([test "x$cross_compiling" = xno], [ - AC_PATH_PROG([RJIT_CC], ${RJIT_CC}) - - # if $CC is in /usr/lib/ccache/$CC, search original $CC (disable ccache) - AS_IF([echo $RUBY_DEBUG | grep ci > /dev/null && - echo $RJIT_CC | grep ^/usr/lib/ccache > /dev/null], [ - PATH=`echo $PATH | sed "s/\/usr\/lib\/ccache://"` RJIT_CC=`which $CC`]) - - AS_CASE([$target_os], - [*mingw*], [command -v cygpath > /dev/null && RJIT_CC=`cygpath -ma $RJIT_CC`]) - shift 2 - RJIT_CC="$RJIT_CC${1+ }$*" -]) - AS_CASE(["$build_os"], [darwin1*.*], [ # Xcode linker warns for deprecated architecture and wrongly @@ -2960,14 +2945,6 @@ LIBEXT=a AC_SUBST(DLDFLAGS)dnl AC_SUBST(ARCH_FLAG)dnl -AC_SUBST(RJIT_CC)dnl -AS_CASE(["$GCC:$target_os"], - [yes:aix*], [rjit_std_cflag="-std=gnu99"], - [rjit_std_cflag=]) -AC_SUBST(RJIT_CFLAGS, [${RJIT_CFLAGS-"-w ${rjit_std_cflag} ${orig_cflags}"}])dnl -AC_SUBST(RJIT_OPTFLAGS, [${RJIT_OPTFLAGS-'$(optflags)'}])dnl -AC_SUBST(RJIT_DEBUGFLAGS, [${RJIT_DEBUGFLAGS-'$(debugflags)'}])dnl -AC_SUBST(RJIT_LDSHARED)dnl AC_SUBST(STATIC)dnl AC_SUBST(CCDLFLAGS)dnl @@ -4127,7 +4104,6 @@ AS_IF([test "${universal_binary-no}" = yes ], [ ]) } -: ${RJIT_LDSHARED=`echo "$LDSHARED" | sed ['s|\$(LD)|'"${LD}"'|g;s|\$(CC)|$(RJIT_CC)|g']`} [end]_group MAINLIBS="$LIBS" diff --git a/defs/gmake.mk b/defs/gmake.mk index bc1ef9b79c2651..155122376ad025 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -14,9 +14,6 @@ override ACTIONS_ENDGROUP = @echo "::endgroup::" endif ifneq ($(filter darwin%,$(target_os)),) -# Remove debug option not to generate thousands of .dSYM -RJIT_DEBUGFLAGS := $(filter-out -g%,$(RJIT_DEBUGFLAGS)) - INSTRUBY_ENV += SDKROOT= endif INSTRUBY_ARGS += --gnumake diff --git a/template/Makefile.in b/template/Makefile.in index 4a19a3cec6de7d..e95b0dd32a83cc 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -96,12 +96,6 @@ USE_RUBYGEMS = @USE_RUBYGEMS@ USE_RUBYGEMS_ = $(USE_RUBYGEMS:yes=) CPPFLAGS = @CPPFLAGS@ $(USE_RUBYGEMS_:no=-DDISABLE_RUBYGEMS=1) RJIT_SUPPORT = @RJIT_SUPPORT@ -RJIT_CC = @RJIT_CC@ -RJIT_CFLAGS = @RJIT_CFLAGS@ -RJIT_OPTFLAGS = @RJIT_OPTFLAGS@ -RJIT_DEBUGFLAGS = @RJIT_DEBUGFLAGS@ -RJIT_LDSHARED = @RJIT_LDSHARED@ -RJIT_DLDFLAGS = $(XDLDFLAGS) YJIT_SUPPORT=@YJIT_SUPPORT@ YJIT_LIBS=@YJIT_LIBS@ YJIT_OBJ=@YJIT_OBJ@ From c5dad5f1d74e4d1acbae943e00a9465a7c921fa5 Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Tue, 15 Aug 2023 09:29:00 -0700 Subject: [PATCH 085/158] Sync script updates --- tool/sync_default_gems.rb | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index d2c17f35af3814..f0f091e1c50902 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -371,7 +371,7 @@ def sync_default_gems(gem) `git checkout ext/digest/depend ext/digest/*/depend` when "set" sync_lib gem, upstream - cp_r(Dir.glob("#{upstream}/test/*"), "test/set") + cp_r("#{upstream}/test", ".") when "optparse" sync_lib gem, upstream rm_rf(%w[doc/optparse]) @@ -420,7 +420,7 @@ def sync_default_gems(gem) cp_r("#{upstream}/include/yarp/.", "yarp") cp_r("#{upstream}/include/yarp.h", "yarp") - rm("yarp/config.h") + rm_f("yarp/config.h") File.write("yarp/config.h", "#include \"ruby/config.h\"\n") rm("yarp/extconf.rb") @@ -441,6 +441,27 @@ def sync_default_gems(gem) |test\/lib\/.* )\z/mx + YARP_IGNORE_FILE_PATTERN = + /\A(?:[A-Z]\w*\.(?:md|txt) + |[^\/]+\.yml + |\.gitignore + |\.git.* + |[A-Z]\w+file + |COPYING + |CONTRIBUTING\.md + |Gemfile + |Gemfile\.lock + |Makefile\.in + |README\.md + |bin\/.* + |configure\.ac + |rakelib\/.* + |templates\/.* + |test\/lib\/.* + |tasks\/.* + |ext\/yarp\/extconf\.rb + )\z/mx + def message_filter(repo, sha, input: ARGF) log = input.read log.delete!("\r") @@ -508,9 +529,15 @@ def sync_default_gems_with_commits(gem, ranges, edit: nil) end # Ignore Merge commit and insufficiency commit for ruby core repository. + case gem + when "yarp" + ignore_file_pattern = YARP_IGNORE_FILE_PATTERN + else + ignore_file_pattern = IGNORE_FILE_PATTERN + end commits.delete_if do |sha, subject| files = pipe_readlines(%W"git diff-tree -z --no-commit-id --name-only -r #{sha}") - subject.start_with?("Merge", "Auto Merge") or files.all?(IGNORE_FILE_PATTERN) + subject.start_with?("Merge", "Auto Merge") or files.all?(ignore_file_pattern) end if commits.empty? @@ -559,7 +586,7 @@ def sync_default_gems_with_commits(gem, ranges, edit: nil) result = pipe_readlines(%W"git status --porcelain -z") result.map! {|line| line[/\A(?:.U|[UA]A) (.*)/, 1]} result.compact! - ignore, conflict = result.partition {|name| IGNORE_FILE_PATTERN =~ name} + ignore, conflict = result.partition {|name| ignore_file_pattern =~ name} unless ignore.empty? system(*%W"git reset HEAD --", *ignore) File.unlink(*ignore) @@ -600,7 +627,7 @@ def sync_default_gems_with_commits(gem, ranges, edit: nil) puts "Remove files added to toplevel: #{toplevels.join(', ')}" system(*%w"git rm -r --", *toplevels) end - tools = changed.select {|f|f.start_with?("test/fixtures/", "test/lib/", "tool/")} + tools = changed.select {|f|f.start_with?("test/lib/", "tool/")} unless tools.empty? system(*%W"git rm -r --", *tools) system(*%W"git checkout HEAD~ --", *tools) From 0f8091947debc467b58a2b04c150dc7a38026ed3 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Tue, 18 Jul 2023 16:25:52 -0400 Subject: [PATCH 086/158] [ruby/yarp] Move the gem's C extension into lib/yarp/ and change the require from "yarp.so" to "yarp/yarp", which is more aligned with existing community conventions for gems. https://github.com/ruby/yarp/commit/64b70e2658 --- lib/yarp.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/yarp.rb b/lib/yarp.rb index 8730ef6f0f3ff4..39ff7e3269d58e 100644 --- a/lib/yarp.rb +++ b/lib/yarp.rb @@ -240,4 +240,5 @@ def self.newlines(source) require_relative "yarp/ripper_compat" require_relative "yarp/serialize" require_relative "yarp/pack" -require "yarp.so" + +require "yarp/yarp" From 76c77b5eca3f02db894819823d3a1ab55455754d Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Thu, 27 Jul 2023 14:46:19 -0400 Subject: [PATCH 087/158] [ruby/yarp] WIP - Introduce contextually parsing programs vs evals This is more or less the code I used in my POC in JRuby to parse evals. Evals depend on parent variable scopes and will produce a different syntax tree. Questions: 1. How does MRI compile evals currently? I cannot find anything. 2. This passes in a char * of data. It does not encode the variables we pass in because the system calling this already knows. Is this adequate though? 3. Can I get guidance on how best to test this? https://github.com/ruby/yarp/commit/f441b6fd2c --- yarp/extension.c | 10 +++++----- yarp/yarp.c | 42 ++++++++++++++++++++++++++++++++++++------ yarp/yarp.h | 4 ++-- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/yarp/extension.c b/yarp/extension.c index 4e801b3b05f55c..7ede50bb0f91b2 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -194,7 +194,7 @@ dump_input(input_t *input, const char *filepath) { yp_parser_t parser; yp_parser_init(&parser, input->source, input->size, filepath); - yp_node_t *node = yp_parse(&parser); + yp_node_t *node = yp_parse(&parser, false); yp_serialize(&parser, node, &buffer); VALUE result = rb_str_new(buffer.value, buffer.length); @@ -378,7 +378,7 @@ lex_input(input_t *input, const char *filepath) { }; parser.lex_callback = &lex_callback; - yp_node_t *node = yp_parse(&parser); + yp_node_t *node = yp_parse(&parser, false); // Here we need to update the source range to have the correct newline // offsets. We do it here because we've already created the object and given @@ -439,7 +439,7 @@ parse_input(input_t *input, const char *filepath) { yp_parser_t parser; yp_parser_init(&parser, input->source, input->size, filepath); - yp_node_t *node = yp_parse(&parser); + yp_node_t *node = yp_parse(&parser, false); rb_encoding *encoding = rb_enc_find(parser.encoding.name); VALUE source = yp_source_new(&parser); @@ -582,7 +582,7 @@ memsize(VALUE self, VALUE string) { size_t length = RSTRING_LEN(string); yp_parser_init(&parser, RSTRING_PTR(string), length, NULL); - yp_node_t *node = yp_parse(&parser); + yp_node_t *node = yp_parse(&parser, false); yp_memsize_t memsize; yp_node_memsize(node, &memsize); @@ -608,7 +608,7 @@ profile_file(VALUE self, VALUE filepath) { yp_parser_t parser; yp_parser_init(&parser, input.source, input.size, checked); - yp_node_t *node = yp_parse(&parser); + yp_node_t *node = yp_parse(&parser, false); yp_node_destroy(&parser, node); yp_parser_free(&parser); diff --git a/yarp/yarp.c b/yarp/yarp.c index 2ae3b3ea28f1f9..50871beedfe6c8 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12735,8 +12735,8 @@ parse_expression(yp_parser_t *parser, yp_binding_power_t binding_power, const ch } static yp_node_t * -parse_program(yp_parser_t *parser) { - yp_parser_scope_push(parser, true); +parse_program(yp_parser_t *parser, bool eval) { + yp_parser_scope_push(parser, !eval); parser_lex(parser); yp_statements_node_t *statements = parse_statements(parser, YP_CONTEXT_MAIN); @@ -12756,6 +12756,34 @@ parse_program(yp_parser_t *parser) { return (yp_node_t *) yp_program_node_create(parser, &locals, statements); } +// Assume always a valid string since it is from trusted source (Ruby impl internals). +// Format: [num_scopes, (num_vars1, (var_char1*, 0)*)*] +static void +yp_populate_eval_scopes(yp_parser_t *parser, const char *data) { + const char *p = data; + size_t number_of_scopes = (size_t) *p; + + p++; + for (size_t scope_index = 0; scope_index < number_of_scopes; scope_index++) { + size_t number_of_variables = (size_t) *p++; + + yp_parser_scope_push(parser, scope_index == 0); + + for (size_t variable_index = 0; variable_index < number_of_variables; variable_index++) { + char *eos = strchr(p, 0); + + yp_token_t lvar = (yp_token_t) { + .type = YP_TOKEN_IDENTIFIER, + .start = p, + .end = eos + }; + yp_parser_local_add_token(parser, &lvar); + + p = ++eos; + } + } +} + /******************************************************************************/ /* External functions */ /******************************************************************************/ @@ -12892,8 +12920,8 @@ yp_parser_free(yp_parser_t *parser) { // Parse the Ruby source associated with the given parser and return the tree. YP_EXPORTED_FUNCTION yp_node_t * -yp_parse(yp_parser_t *parser) { - return parse_program(parser); +yp_parse(yp_parser_t *parser, bool eval) { + return parse_program(parser, eval); } YP_EXPORTED_FUNCTION void @@ -12910,11 +12938,13 @@ yp_serialize(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { // Parse and serialize the AST represented by the given source to the given // buffer. YP_EXPORTED_FUNCTION void -yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer) { +yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *parent_scopes) { + bool eval = parent_scopes != NULL; yp_parser_t parser; yp_parser_init(&parser, source, size, NULL); + if (eval) yp_populate_eval_scopes(&parser, parent_scopes); - yp_node_t *node = yp_parse(&parser); + yp_node_t *node = yp_parse(&parser, eval); yp_serialize(&parser, node, buffer); yp_node_destroy(&parser, node); diff --git a/yarp/yarp.h b/yarp/yarp.h index 4bbffdbb1060d6..492038a6e287dd 100644 --- a/yarp/yarp.h +++ b/yarp/yarp.h @@ -51,7 +51,7 @@ YP_EXPORTED_FUNCTION void yp_parser_register_encoding_decode_callback(yp_parser_ YP_EXPORTED_FUNCTION void yp_parser_free(yp_parser_t *parser); // Parse the Ruby source associated with the given parser and return the tree. -YP_EXPORTED_FUNCTION yp_node_t * yp_parse(yp_parser_t *parser); +YP_EXPORTED_FUNCTION yp_node_t * yp_parse(yp_parser_t *parser, bool eval); // Pretty-prints the AST represented by the given node to the given buffer. YP_EXPORTED_FUNCTION void yp_prettyprint(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer); @@ -61,7 +61,7 @@ YP_EXPORTED_FUNCTION void yp_serialize(yp_parser_t *parser, yp_node_t *node, yp_ // Parse and serialize the AST represented by the given source to the given // buffer. -YP_EXPORTED_FUNCTION void yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer); +YP_EXPORTED_FUNCTION void yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *parent_scopes); // Returns a string representation of the given token type. YP_EXPORTED_FUNCTION const char * yp_token_type_to_str(yp_token_type_t token_type); From ede55edbd55ae0c476957723e18f8764679fde4b Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Thu, 27 Jul 2023 14:58:11 -0400 Subject: [PATCH 088/158] [ruby/yarp] Remove trailing whitespace https://github.com/ruby/yarp/commit/04de272383 --- yarp/yarp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 50871beedfe6c8..69059cd29f8e23 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12944,7 +12944,7 @@ yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const c yp_parser_init(&parser, source, size, NULL); if (eval) yp_populate_eval_scopes(&parser, parent_scopes); - yp_node_t *node = yp_parse(&parser, eval); + yp_node_t *node = yp_parse(&parser, eval); yp_serialize(&parser, node, buffer); yp_node_destroy(&parser, node); From 86b32dac9223895f236c944548fbf5379a5b1037 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 31 Jul 2023 09:33:01 -0400 Subject: [PATCH 089/158] [ruby/yarp] Handle pound terminator in isolation https://github.com/ruby/yarp/commit/1cfce46107 --- yarp/yarp.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 69059cd29f8e23..622da66fbcbadf 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -6645,10 +6645,13 @@ parser_lex(yp_parser_t *parser) { LEX(YP_TOKEN_EOF); } + // Get a reference to the current mode. + yp_lex_mode_t *mode = parser->lex_modes.current; + // These are the places where we need to split up the content of the // regular expression. We'll use strpbrk to find the first of these // characters. - const char *breakpoints = parser->lex_modes.current->as.regexp.breakpoints; + const char *breakpoints = mode->as.regexp.breakpoints; const char *breakpoint = yp_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); while (breakpoint != NULL) { @@ -6673,14 +6676,15 @@ parser_lex(yp_parser_t *parser) { break; } case '#': { - yp_token_type_t type = lex_interpolation(parser, breakpoint); - if (type != YP_TOKEN_NOT_PROVIDED) { - LEX(type); - } + // If the terminator is #, then we need to fall into the + // default case. Otherwise we'll attempt to lex + // interpolation. + if (mode->as.regexp.terminator != '#') { + yp_token_type_t type = lex_interpolation(parser, breakpoint); + if (type != YP_TOKEN_NOT_PROVIDED) { + LEX(type); + } - // We need to check if the terminator was # before skipping over - // to the next breakpoint - if (parser->lex_modes.current->as.regexp.terminator != '#') { // If we haven't returned at this point then we had something // that looked like an interpolated class or instance variable // like "#@" but wasn't actually. In this case we'll just skip @@ -6691,11 +6695,11 @@ parser_lex(yp_parser_t *parser) { } /* fallthrough */ default: { - if (*breakpoint == parser->lex_modes.current->as.regexp.incrementor) { + if (*breakpoint == mode->as.regexp.incrementor) { // If we've hit the incrementor, then we need to skip past it and // find the next breakpoint. breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - parser->lex_modes.current->as.regexp.nesting++; + mode->as.regexp.nesting++; break; } @@ -6704,7 +6708,7 @@ parser_lex(yp_parser_t *parser) { // that in the list of newlines. yp_newline_list_append(&parser->newline_list, breakpoint); - if (parser->lex_modes.current->as.regexp.terminator != '\n') { + if (mode->as.regexp.terminator != '\n') { // If the terminator is not a newline, then we // can set the next breakpoint and continue. breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); @@ -6715,11 +6719,11 @@ parser_lex(yp_parser_t *parser) { // terminator so we need to continue on. } - assert(*breakpoint == parser->lex_modes.current->as.regexp.terminator); + assert(*breakpoint == mode->as.regexp.terminator); - if (parser->lex_modes.current->as.regexp.nesting > 0) { + if (mode->as.regexp.nesting > 0) { breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - parser->lex_modes.current->as.regexp.nesting--; + mode->as.regexp.nesting--; break; } From 41e8ba01ae644d10e6aebc832fc616e1af8e7159 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 31 Jul 2023 10:48:17 -0400 Subject: [PATCH 090/158] [ruby/yarp] Mark locations in the tree where newlines can occur https://github.com/ruby/yarp/commit/479e835756 --- yarp/yarp.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 622da66fbcbadf..f8301daa6badfc 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -2202,7 +2202,7 @@ yp_if_node_create(yp_parser_t *parser, *node = (yp_if_node_t) { { - .type = YP_NODE_IF_NODE, + .type = YP_NODE_IF_NODE | YP_NODE_FLAG_NEWLINE, .location = { .start = if_keyword->start, .end = end @@ -2228,7 +2228,7 @@ yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_t *node = (yp_if_node_t) { { - .type = YP_NODE_IF_NODE, + .type = YP_NODE_IF_NODE | YP_NODE_FLAG_NEWLINE, .location = { .start = statement->location.start, .end = predicate->location.end @@ -2260,7 +2260,7 @@ yp_if_node_ternary_create(yp_parser_t *parser, yp_node_t *predicate, yp_node_t * *node = (yp_if_node_t) { { - .type = YP_NODE_IF_NODE, + .type = YP_NODE_IF_NODE | YP_NODE_FLAG_NEWLINE, .location = { .start = predicate->location.start, .end = false_expression->location.end, @@ -3683,6 +3683,9 @@ yp_statements_node_body_append(yp_statements_node_t *node, yp_node_t *statement) yp_node_list_append(&node->body, statement); node->base.location.end = statement->location.end; + + // Every statement gets marked as a place where a newline can occur. + statement->type |= YP_NODE_FLAG_NEWLINE; } // Allocate a new StringConcatNode node. @@ -3913,7 +3916,7 @@ yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *node = (yp_unless_node_t) { { - .type = YP_NODE_UNLESS_NODE, + .type = YP_NODE_UNLESS_NODE | YP_NODE_FLAG_NEWLINE, .location = { .start = keyword->start, .end = end @@ -3939,7 +3942,7 @@ yp_unless_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const *node = (yp_unless_node_t) { { - .type = YP_NODE_UNLESS_NODE, + .type = YP_NODE_UNLESS_NODE | YP_NODE_FLAG_NEWLINE, .location = { .start = statement->location.start, .end = predicate->location.end From f1658efe38347ec90c87c64dcee4f8e4656aa388 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 31 Jul 2023 13:34:22 -0400 Subject: [PATCH 091/158] [ruby/yarp] Split out newline test https://github.com/ruby/yarp/commit/eeb4f6cb9d --- test/newline_test.rb | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 test/newline_test.rb diff --git a/test/newline_test.rb b/test/newline_test.rb new file mode 100644 index 00000000000000..09d0c09e5b36e7 --- /dev/null +++ b/test/newline_test.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require "yarp_test_helper" + +class NewlineTest < Test::Unit::TestCase + class NewlineVisitor < YARP::Visitor + attr_reader :source, :newlines + + def initialize(source) + @source = source + @newlines = [] + end + + def visit(node) + newlines << source.line(node.location.start_offset) if node&.newline? + super(node) + end + end + + root = File.dirname(__dir__) + Dir["{lib,test}/**/*.rb", base: root].each do |relative| + filepath = File.join(root, relative) + + define_method "test_newline_flags_#{relative}" do + source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) + expected = rubyvm_lines(source) + + result = YARP.parse(source, relative) + assert_empty result.errors + + result.mark_newlines + visitor = NewlineVisitor.new(result.source) + result.value.accept(visitor) + actual = visitor.newlines + + if relative == "lib/yarp/serialize.rb" + # while (b = io.getbyte) >= 128 has 2 newline flags + expected.delete_at actual.index(62) + elsif relative == "lib/yarp/lex_compat.rb" + # extra flag for: dedent_next =\n ((token.event: due to bytecode order + actual.delete(514) + # different line for: token =\n case event: due to bytecode order + actual.delete(571) + expected.delete(572) + # extra flag for: lex_state =\n if RIPPER: due to bytecode order + actual.delete(604) + # extra flag for: (token[2].start_with?("\#$") || token[2].start_with?("\#@")) + # unclear when ParenthesesNode should allow a second flag on the same line or not + actual.delete(731) + end + + assert_equal expected, actual + end + end + + private + + def ignore_warnings + previous_verbosity = $VERBOSE + $VERBOSE = nil + yield + ensure + $VERBOSE = previous_verbosity + end + + def rubyvm_lines(source) + queue = [ignore_warnings { RubyVM::InstructionSequence.compile(source) }] + lines = [] + + while iseq = queue.shift + lines.concat(iseq.trace_points.filter_map { |line, event| line if event == :line }) + iseq.each_child { |insn| queue << insn unless insn.label.start_with?("ensure in ") } + end + + lines.sort + end +end From 45efbadba55beace717eaad384c7125c801abd86 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 31 Jul 2023 14:17:17 -0400 Subject: [PATCH 092/158] [ruby/yarp] Enable all of -wconversion https://github.com/ruby/yarp/commit/638163f6c6 --- yarp/regexp.c | 8 +++++--- yarp/unescape.c | 28 ++++++++++++++-------------- yarp/util/yp_char.c | 2 +- yarp/util/yp_char.h | 2 +- yarp/util/yp_constant_pool.c | 2 +- yarp/yarp.c | 2 +- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/yarp/regexp.c b/yarp/regexp.c index c8aeaa0adb5d13..4855859442fba6 100644 --- a/yarp/regexp.c +++ b/yarp/regexp.c @@ -281,7 +281,9 @@ typedef enum { #define YP_REGEXP_OPTION_STATE_SLOTS (YP_REGEXP_OPTION_STATE_SLOT_MAXIMUM - YP_REGEXP_OPTION_STATE_SLOT_MINIMUM + 1) // This is the set of options that are configurable on the regular expression. -typedef struct { unsigned char values[YP_REGEXP_OPTION_STATE_SLOTS]; } yp_regexp_options_t; +typedef struct { + unsigned char values[YP_REGEXP_OPTION_STATE_SLOTS]; +} yp_regexp_options_t; // Initialize a new set of options to their default values. static void @@ -300,7 +302,7 @@ yp_regexp_options_init(yp_regexp_options_t *options) { static bool yp_regexp_options_add(yp_regexp_options_t *options, unsigned char key) { if (key >= YP_REGEXP_OPTION_STATE_SLOT_MINIMUM && key <= YP_REGEXP_OPTION_STATE_SLOT_MAXIMUM) { - key -= YP_REGEXP_OPTION_STATE_SLOT_MINIMUM; + key = (unsigned char) (key - YP_REGEXP_OPTION_STATE_SLOT_MINIMUM); switch (options->values[key]) { case YP_REGEXP_OPTION_STATE_INVALID: @@ -323,7 +325,7 @@ yp_regexp_options_add(yp_regexp_options_t *options, unsigned char key) { static bool yp_regexp_options_remove(yp_regexp_options_t *options, unsigned char key) { if (key >= YP_REGEXP_OPTION_STATE_SLOT_MINIMUM && key <= YP_REGEXP_OPTION_STATE_SLOT_MAXIMUM) { - key -= YP_REGEXP_OPTION_STATE_SLOT_MINIMUM; + key = (unsigned char) (key - YP_REGEXP_OPTION_STATE_SLOT_MINIMUM); switch (options->values[key]) { case YP_REGEXP_OPTION_STATE_INVALID: diff --git a/yarp/unescape.c b/yarp/unescape.c index 5370b273557909..296caf01aada52 100644 --- a/yarp/unescape.c +++ b/yarp/unescape.c @@ -64,19 +64,19 @@ unescape_octal(const char *backslash, unsigned char *value) { return 2; } - *value = (*value << 3) | (backslash[2] - '0'); + *value = (unsigned char) ((*value << 3) | (backslash[2] - '0')); if (!yp_char_is_octal_digit(backslash[3])) { return 3; } - *value = (*value << 3) | (backslash[3] - '0'); + *value = (unsigned char) ((*value << 3) | (backslash[3] - '0')); return 4; } // Convert a hexadecimal digit into its equivalent value. static inline unsigned char unescape_hexadecimal_digit(const char value) { - return (value <= '9') ? (unsigned char) (value - '0') : (value & 0x7) + 9; + return (unsigned char) ((value <= '9') ? (value - '0') : (value & 0x7) + 9); } // Scan the 1-2 digits of hexadecimal into the value. Returns the number of @@ -88,7 +88,7 @@ unescape_hexadecimal(const char *backslash, unsigned char *value) { return 3; } - *value = (*value << 4) | unescape_hexadecimal_digit(backslash[3]); + *value = (unsigned char) ((*value << 4) | unescape_hexadecimal_digit(backslash[3])); return 4; } @@ -113,22 +113,22 @@ unescape_unicode_write(char *dest, uint32_t value, const char *start, const char if (value <= 0x7F) { // 0xxxxxxx - bytes[0] = value; + bytes[0] = (unsigned char) value; return 1; } if (value <= 0x7FF) { // 110xxxxx 10xxxxxx - bytes[0] = 0xC0 | (value >> 6); - bytes[1] = 0x80 | (value & 0x3F); + bytes[0] = (unsigned char) (0xC0 | (value >> 6)); + bytes[1] = (unsigned char) (0x80 | (value & 0x3F)); return 2; } if (value <= 0xFFFF) { // 1110xxxx 10xxxxxx 10xxxxxx - bytes[0] = 0xE0 | (value >> 12); - bytes[1] = 0x80 | ((value >> 6) & 0x3F); - bytes[2] = 0x80 | (value & 0x3F); + bytes[0] = (unsigned char) (0xE0 | (value >> 12)); + bytes[1] = (unsigned char) (0x80 | ((value >> 6) & 0x3F)); + bytes[2] = (unsigned char) (0x80 | (value & 0x3F)); return 3; } @@ -136,10 +136,10 @@ unescape_unicode_write(char *dest, uint32_t value, const char *start, const char // the input is invalid. if (value <= 0x10FFFF) { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - bytes[0] = 0xF0 | (value >> 18); - bytes[1] = 0x80 | ((value >> 12) & 0x3F); - bytes[2] = 0x80 | ((value >> 6) & 0x3F); - bytes[3] = 0x80 | (value & 0x3F); + bytes[0] = (unsigned char) (0xF0 | (value >> 18)); + bytes[1] = (unsigned char) (0x80 | ((value >> 12) & 0x3F)); + bytes[2] = (unsigned char) (0x80 | ((value >> 6) & 0x3F)); + bytes[3] = (unsigned char) (0x80 | (value & 0x3F)); return 4; } diff --git a/yarp/util/yp_char.c b/yarp/util/yp_char.c index 1c0c20edd92083..d27a04104ec62e 100644 --- a/yarp/util/yp_char.c +++ b/yarp/util/yp_char.c @@ -75,7 +75,7 @@ yp_strspn_whitespace(const char *string, ptrdiff_t length) { // whitespace while also tracking the location of each newline. Disallows // searching past the given maximum number of characters. size_t -yp_strspn_whitespace_newlines(const char *string, long length, yp_newline_list_t *newline_list, bool stop_at_newline) { +yp_strspn_whitespace_newlines(const char *string, ptrdiff_t length, yp_newline_list_t *newline_list, bool stop_at_newline) { if (length <= 0) return 0; size_t size = 0; diff --git a/yarp/util/yp_char.h b/yarp/util/yp_char.h index dcc011f0a12f17..010d34d6693c56 100644 --- a/yarp/util/yp_char.h +++ b/yarp/util/yp_char.h @@ -15,7 +15,7 @@ size_t yp_strspn_whitespace(const char *string, ptrdiff_t length); // whitespace while also tracking the location of each newline. Disallows // searching past the given maximum number of characters. size_t -yp_strspn_whitespace_newlines(const char *string, long length, yp_newline_list_t *newline_list, bool); +yp_strspn_whitespace_newlines(const char *string, ptrdiff_t length, yp_newline_list_t *newline_list, bool); // Returns the number of characters at the start of the string that are inline // whitespace. Disallows searching past the given maximum number of characters. diff --git a/yarp/util/yp_constant_pool.c b/yarp/util/yp_constant_pool.c index 8c1889c6b41cb6..fdece2dabb25b0 100644 --- a/yarp/util/yp_constant_pool.c +++ b/yarp/util/yp_constant_pool.c @@ -110,7 +110,7 @@ yp_constant_pool_init(yp_constant_pool_t *pool, size_t capacity) { // if any potential calls to resize fail. yp_constant_id_t yp_constant_pool_insert(yp_constant_pool_t *pool, const char *start, size_t length) { - if (pool->size >= pool->capacity * 0.75) { + if (pool->size >= (pool->capacity / 4 * 3)) { if (!yp_constant_pool_resize(pool)) return 0; } diff --git a/yarp/yarp.c b/yarp/yarp.c index f8301daa6badfc..f831d03ee166e4 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -5929,7 +5929,7 @@ parser_lex(yp_parser_t *parser) { } size_t ident_length = (size_t) (parser->current.end - ident_start); - if (quote != YP_HEREDOC_QUOTE_NONE && !match(parser, quote)) { + if (quote != YP_HEREDOC_QUOTE_NONE && !match(parser, (char) quote)) { // TODO: handle unterminated heredoc } From 242f3c3a77007c260d7d868cff3fd5f293e8aaa1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 1 Aug 2023 11:05:12 -0400 Subject: [PATCH 093/158] [ruby/yarp] Don't read off the end when parsing % literals https://github.com/ruby/yarp/commit/aff40871e6 --- yarp/yarp.c | 66 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index f831d03ee166e4..9aa4e264c67a7b 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -6360,53 +6360,89 @@ parser_lex(yp_parser_t *parser) { switch (*parser->current.end) { case 'i': { parser->current.end++; - lex_mode_push_list(parser, false, *parser->current.end++); + + if (parser->current.end < parser->end) { + lex_mode_push_list(parser, false, *parser->current.end++); + } + LEX(YP_TOKEN_PERCENT_LOWER_I); } case 'I': { parser->current.end++; - lex_mode_push_list(parser, true, *parser->current.end++); + + if (parser->current.end < parser->end) { + lex_mode_push_list(parser, true, *parser->current.end++); + } + LEX(YP_TOKEN_PERCENT_UPPER_I); } case 'r': { parser->current.end++; - lex_mode_push_regexp(parser, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); - parser->current.end++; + + if (parser->current.end < parser->end) { + lex_mode_push_regexp(parser, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); + parser->current.end++; + } + LEX(YP_TOKEN_REGEXP_BEGIN); } case 'q': { parser->current.end++; - lex_mode_push_string(parser, false, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); - parser->current.end++; + + if (parser->current.end < parser->end) { + lex_mode_push_string(parser, false, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); + parser->current.end++; + } + LEX(YP_TOKEN_STRING_BEGIN); } case 'Q': { parser->current.end++; - lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); - parser->current.end++; + + if (parser->current.end < parser->end) { + lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); + parser->current.end++; + } + LEX(YP_TOKEN_STRING_BEGIN); } case 's': { parser->current.end++; - lex_mode_push_string(parser, false, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); - lex_state_set(parser, YP_LEX_STATE_FNAME | YP_LEX_STATE_FITEM); - parser->current.end++; + + if (parser->current.end < parser->end) { + lex_mode_push_string(parser, false, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); + lex_state_set(parser, YP_LEX_STATE_FNAME | YP_LEX_STATE_FITEM); + parser->current.end++; + } + LEX(YP_TOKEN_SYMBOL_BEGIN); } case 'w': { parser->current.end++; - lex_mode_push_list(parser, false, *parser->current.end++); + + if (parser->current.end < parser->end) { + lex_mode_push_list(parser, false, *parser->current.end++); + } + LEX(YP_TOKEN_PERCENT_LOWER_W); } case 'W': { parser->current.end++; - lex_mode_push_list(parser, true, *parser->current.end++); + + if (parser->current.end < parser->end) { + lex_mode_push_list(parser, true, *parser->current.end++); + } + LEX(YP_TOKEN_PERCENT_UPPER_W); } case 'x': { parser->current.end++; - lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); - parser->current.end++; + + if (parser->current.end < parser->end) { + lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); + parser->current.end++; + } + LEX(YP_TOKEN_PERCENT_LOWER_X); } default: From cededf73dca8986aec44e01647be8bef8cb85579 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 1 Aug 2023 11:11:40 -0400 Subject: [PATCH 094/158] [ruby/yarp] For errored % characters, use TOKEN_PERCENT and not TOKEN_STRING_BEGIN https://github.com/ruby/yarp/commit/2ec671fe1e --- yarp/yarp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 9aa4e264c67a7b..ee9aa1b172404f 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -6325,12 +6325,14 @@ parser_lex(yp_parser_t *parser) { // % %= %i %I %q %Q %w %W case '%': { - // In a BEG state, if you encounter a % then you must be starting - // something. In this case if there is no subsequent character then - // we have an invalid token. + // In a BEG state, if you encounter a % then you must be + // starting something. In this case if there is no + // subsequent character then we have an invalid token. We're + // going to say it's the percent operator because we don't + // want to move into the string lex mode unnecessarily. if (lex_state_beg_p(parser) && (parser->current.end >= parser->end)) { yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "unexpected end of input"); - LEX(YP_TOKEN_STRING_BEGIN); + LEX(YP_TOKEN_PERCENT); } if (!lex_state_beg_p(parser) && match(parser, '=')) { From 4c4e75c0de961e5a838f52bb056ddae505722489 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 1 Aug 2023 11:16:13 -0400 Subject: [PATCH 095/158] [ruby/yarp] Add error cases for ustar appearing in infix position https://github.com/ruby/yarp/commit/8736c17359 --- yarp/yarp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yarp/yarp.c b/yarp/yarp.c index ee9aa1b172404f..fc0bd54d0f0464 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12463,6 +12463,10 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t return (yp_node_t *) yp_call_node_binary_create(parser, node, &token, argument); } + case YP_TOKEN_USTAR: + case YP_TOKEN_USTAR_STAR: + // The only times this will occur are when we are in an error state, + // but we'll put them in here so that errors can propagate. case YP_TOKEN_BANG_EQUAL: case YP_TOKEN_BANG_TILDE: case YP_TOKEN_EQUAL_EQUAL: From e56da35637cbb0107274047ea7ffb277d3ebddef Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 1 Aug 2023 11:21:14 -0400 Subject: [PATCH 096/158] [ruby/yarp] Handle invalid regexps more gracefully https://github.com/ruby/yarp/commit/584a49f123 --- yarp/yarp.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index fc0bd54d0f0464..2d719a62d66e4b 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12445,17 +12445,13 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t yp_location_t *content_loc = &((yp_regular_expression_node_t *) node)->content_loc; - YP_ATTRIBUTE_UNUSED bool captured_group_names = - yp_regexp_named_capture_group_names(content_loc->start, (size_t) (content_loc->end - content_loc->start), &named_captures); + if (yp_regexp_named_capture_group_names(content_loc->start, (size_t) (content_loc->end - content_loc->start), &named_captures)) { + for (size_t index = 0; index < named_captures.length; index++) { + yp_string_t *name = &named_captures.strings[index]; + assert(name->type == YP_STRING_SHARED); - // We assert that the regex was successfully parsed - assert(captured_group_names); - - for (size_t index = 0; index < named_captures.length; index++) { - yp_string_t *name = &named_captures.strings[index]; - assert(name->type == YP_STRING_SHARED); - - yp_parser_local_add_location(parser, name->as.shared.start, name->as.shared.end); + yp_parser_local_add_location(parser, name->as.shared.start, name->as.shared.end); + } } yp_string_list_free(&named_captures); From eca3b9343757c9d70dff5f4172396c0a6643cbf0 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 1 Aug 2023 11:21:25 -0400 Subject: [PATCH 097/158] [ruby/yarp] **nil can be a STAR_STAR token https://github.com/ruby/yarp/commit/33b06f252c --- yarp/yarp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 2d719a62d66e4b..e8065d16685208 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -3023,7 +3023,7 @@ yp_nil_node_create(yp_parser_t *parser, const yp_token_t *token) { // Allocate and initialize a new NoKeywordsParameterNode node. static yp_no_keywords_parameter_node_t * yp_no_keywords_parameter_node_create(yp_parser_t *parser, const yp_token_t *operator, const yp_token_t *keyword) { - assert(operator->type == YP_TOKEN_USTAR_STAR); + assert(operator->type == YP_TOKEN_USTAR_STAR || operator->type == YP_TOKEN_STAR_STAR); assert(keyword->type == YP_TOKEN_KEYWORD_NIL); yp_no_keywords_parameter_node_t *node = YP_ALLOC_NODE(parser, yp_no_keywords_parameter_node_t); From 31960a9627f7810a294b835dfe073cab1106e1de Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 1 Aug 2023 11:26:09 -0400 Subject: [PATCH 098/158] [ruby/yarp] Handle missing block parameters https://github.com/ruby/yarp/commit/bc9049418d --- yarp/yarp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index e8065d16685208..83c4cc2ccfc037 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -1014,7 +1014,7 @@ yp_block_parameters_node_closing_set(yp_block_parameters_node_t *node, const yp_ // Append a new block-local variable to a BlockParametersNode node. static void yp_block_parameters_node_append_local(yp_block_parameters_node_t *node, const yp_token_t *local) { - assert(local->type == YP_TOKEN_IDENTIFIER); + assert(local->type == YP_TOKEN_IDENTIFIER || local->type == YP_TOKEN_MISSING); yp_location_list_append(&node->locals, local); if (node->base.location.start == NULL) node->base.location.start = local->start; From 2ccaaaa1017fa411134648bbaa6fa8f8b875e16d Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 29 Jul 2023 16:13:52 +0200 Subject: [PATCH 099/158] [ruby/yarp] Add simpler exported unescape function to librubyparser * Moves logic from the C extension to librubyparser which can be shared with the Fiddle backend. https://github.com/ruby/yarp/commit/aa48d5e444 --- yarp/extension.c | 28 +++++++--------------------- yarp/unescape.c | 21 ++++++++++++++++++++- yarp/unescape.h | 4 ++++ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/yarp/extension.c b/yarp/extension.c index 7ede50bb0f91b2..36e9941d647dd1 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -529,30 +529,16 @@ named_captures(VALUE self, VALUE source) { // version. static VALUE unescape(VALUE source, yp_unescape_type_t unescape_type) { - yp_string_t string; - VALUE result; + yp_string_t result; - yp_list_t error_list; - yp_list_init(&error_list); - - const char *start = RSTRING_PTR(source); - size_t length = RSTRING_LEN(source); - - yp_parser_t parser; - yp_parser_init(&parser, start, length, ""); - - yp_unescape_manipulate_string(&parser, start, length, &string, unescape_type, &error_list); - if (yp_list_empty_p(&error_list)) { - result = rb_str_new(yp_string_source(&string), yp_string_length(&string)); + if (yp_unescape_string(RSTRING_PTR(source), RSTRING_LEN(source), unescape_type, &result)) { + VALUE str = rb_str_new(yp_string_source(&result), yp_string_length(&result)); + yp_string_free(&result); + return str; } else { - result = Qnil; + yp_string_free(&result); + return Qnil; } - - yp_string_free(&string); - yp_list_free(&error_list); - yp_parser_free(&parser); - - return result; } // Do not unescape anything in the given string. This is here to provide a diff --git a/yarp/unescape.c b/yarp/unescape.c index 296caf01aada52..3f6e70216c4b31 100644 --- a/yarp/unescape.c +++ b/yarp/unescape.c @@ -1,4 +1,4 @@ -#include "yarp/unescape.h" +#include "yarp.h" /******************************************************************************/ /* Character checks */ @@ -528,6 +528,25 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len string->as.owned.length = dest_length + ((size_t) (end - cursor)); } +YP_EXPORTED_FUNCTION bool +yp_unescape_string(const char *start, size_t length, yp_unescape_type_t unescape_type, yp_string_t *result) { + bool success; + + yp_list_t error_list; + yp_list_init(&error_list); + + yp_parser_t parser; + yp_parser_init(&parser, start, length, ""); + + yp_unescape_manipulate_string(&parser, start, length, result, unescape_type, &error_list); + success = yp_list_empty_p(&error_list); + + yp_list_free(&error_list); + yp_parser_free(&parser); + + return success; +} + // This function is similar to yp_unescape_manipulate_string, except it doesn't // actually perform any string manipulations. Instead, it calculates how long // the unescaped character is, and returns that value diff --git a/yarp/unescape.h b/yarp/unescape.h index 15e7cf2e179a63..b76ac9f7a4158c 100644 --- a/yarp/unescape.h +++ b/yarp/unescape.h @@ -33,6 +33,10 @@ typedef enum { // given unescape mode. YP_EXPORTED_FUNCTION void yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t length, yp_string_t *string, yp_unescape_type_t unescape_type, yp_list_t *error_list); +// Accepts a source string and a type of unescaping and returns the unescaped version. +// The caller must yp_string_free(result); after calling this function. +YP_EXPORTED_FUNCTION bool yp_unescape_string(const char *start, size_t length, yp_unescape_type_t unescape_type, yp_string_t *result); + YP_EXPORTED_FUNCTION size_t yp_unescape_calculate_difference(const char *value, const char *end, yp_unescape_type_t unescape_type, bool expect_single_codepoint, yp_list_t *error_list); #endif From e712bc9b937c7b9c2993f0d3289f64bb81c70970 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 29 Jul 2023 16:49:54 +0200 Subject: [PATCH 100/158] [ruby/yarp] Move efficient file reading using demand paging to librubyparser * So it can be reused by the Fiddle backend, etc and not just the C extension. * Add YP_STRING_MAPPED to use a consistent interface for yp_string_t. That way yp_string_free() can be used like for other string types. * Fix handling of empty file for !HAVE_MMAP && !_WIN32 https://github.com/ruby/yarp/commit/e40bc35801 --- yarp/extension.c | 192 +++++++----------------------------------- yarp/extension.h | 10 --- yarp/util/yp_string.c | 129 ++++++++++++++++++++++++++++ yarp/util/yp_string.h | 19 ++++- 4 files changed, 176 insertions(+), 174 deletions(-) diff --git a/yarp/extension.c b/yarp/extension.c index 36e9941d647dd1..a189b1a8769dbb 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -14,14 +14,6 @@ VALUE rb_cYARPParseResult; /* IO of Ruby code */ /******************************************************************************/ -// Represents an input of Ruby code. It can either be coming from a file or a -// string. If it's a file, we'll use demand paging to read the contents of the -// file into a string. If it's already a string, we'll reference it directly. -typedef struct { - const char *source; - size_t size; -} input_t; - // Check if the given filepath is a string. If it's nil, then return NULL. If // it's not a string, then raise a type error. Otherwise return the filepath as // a C string. @@ -41,142 +33,15 @@ check_filepath(VALUE filepath) { return StringValueCStr(filepath); } -// Read the file indicated by the filepath parameter into source and load its -// contents and size into the given input_t. -// -// 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`. -static int -input_load_filepath(input_t *input, const char *filepath) { -#ifdef _WIN32 - // Open the file for reading. - HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (file == INVALID_HANDLE_VALUE) { - perror("CreateFile failed"); - return 1; - } - - // Get the file size. - DWORD file_size = GetFileSize(file, NULL); - if (file_size == INVALID_FILE_SIZE) { - CloseHandle(file); - perror("GetFileSize failed"); - return 1; - } - - // 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) { - CloseHandle(file); - input->size = 0; - input->source = ""; - return 0; - } - - // Create a mapping of the file. - HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); - if (mapping == NULL) { - CloseHandle(file); - perror("CreateFileMapping failed"); - return 1; - } - - // Map the file into memory. - input->source = (const char *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); - CloseHandle(mapping); - CloseHandle(file); - - if (input->source == NULL) { - perror("MapViewOfFile failed"); - return 1; - } - - // Set the size of the source. - input->size = (size_t) file_size; - return 0; -#else - // Open the file for reading - int fd = open(filepath, O_RDONLY); - if (fd == -1) { - perror("open"); - return 1; - } - - // Stat the file to get the file size - struct stat sb; - if (fstat(fd, &sb) == -1) { - close(fd); - perror("fstat"); - return 1; - } - - // mmap the file descriptor to virtually get the contents - input->size = sb.st_size; - -#ifdef HAVE_MMAP - if (!input->size) { - close(fd); - input->source = ""; - return 0; - } - - const char *result = mmap(NULL, input->size, PROT_READ, MAP_PRIVATE, fd, 0); - if (result == MAP_FAILED) { - perror("Map failed"); - return 1; - } else { - input->source = result; - } -#else - input->source = malloc(input->size); - if (input->source == NULL) return 1; - - ssize_t read_size = read(fd, (void *) input->source, input->size); - if (read_size < 0 || (size_t)read_size != input->size) { - perror("Read size is incorrect"); - free((void *) input->source); - return 1; - } -#endif - - close(fd); - return 0; -#endif -} - -// Load the contents and size of the given string into the given input_t. +// Load the contents and size of the given string into the given yp_string_t. static void -input_load_string(input_t *input, VALUE string) { +input_load_string(yp_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)); } - input->source = RSTRING_PTR(string); - input->size = RSTRING_LEN(string); -} - -// Free any resources associated with the given input_t. This is the corollary -// function to source_file_load. It will unmap the file if it was mapped, or -// free the memory if it was allocated. -static void -input_unload_filepath(input_t *input) { - // We don't need to free anything with 0 sized files because we handle that - // with a constant string instead. - if (!input->size) return; - void *memory = (void *) input->source; - -#if defined(_WIN32) - UnmapViewOfFile(memory); -#elif defined(HAVE_MMAP) - munmap(memory, input->size); -#else - free(memory); -#endif + yp_string_constant_init(input, RSTRING_PTR(string), RSTRING_LEN(string)); } /******************************************************************************/ @@ -185,14 +50,14 @@ input_unload_filepath(input_t *input) { // Dump the AST corresponding to the given input to a string. static VALUE -dump_input(input_t *input, const char *filepath) { +dump_input(yp_string_t *input, const char *filepath) { yp_buffer_t buffer; if (!yp_buffer_init(&buffer)) { rb_raise(rb_eNoMemError, "failed to allocate memory"); } yp_parser_t parser; - yp_parser_init(&parser, input->source, input->size, filepath); + yp_parser_init(&parser, yp_string_source(input), yp_string_length(input), filepath); yp_node_t *node = yp_parse(&parser, false); yp_serialize(&parser, node, &buffer); @@ -212,7 +77,7 @@ dump(int argc, VALUE *argv, VALUE self) { VALUE filepath; rb_scan_args(argc, argv, "11", &string, &filepath); - input_t input; + yp_string_t input; input_load_string(&input, string); return dump_input(&input, check_filepath(filepath)); } @@ -220,13 +85,13 @@ dump(int argc, VALUE *argv, VALUE self) { // Dump the AST corresponding to the given file to a string. static VALUE dump_file(VALUE self, VALUE filepath) { - input_t input; + yp_string_t input; const char *checked = check_filepath(filepath); - if (input_load_filepath(&input, checked) != 0) return Qnil; + if (!yp_string_mapped_init(&input, checked)) return Qnil; VALUE value = dump_input(&input, checked); - input_unload_filepath(&input); + yp_string_free(&input); return value; } @@ -356,13 +221,13 @@ lex_encoding_changed_callback(yp_parser_t *parser) { // Return an array of tokens corresponding to the given source. static VALUE -lex_input(input_t *input, const char *filepath) { +lex_input(yp_string_t *input, const char *filepath) { yp_parser_t parser; - yp_parser_init(&parser, input->source, input->size, filepath); + yp_parser_init(&parser, yp_string_source(input), yp_string_length(input), filepath); yp_parser_register_encoding_changed_callback(&parser, lex_encoding_changed_callback); VALUE offsets = rb_ary_new(); - VALUE source_argv[] = { rb_str_new(input->source, input->size), offsets }; + VALUE source_argv[] = { rb_str_new(yp_string_source(input), yp_string_length(input)), offsets }; VALUE source = rb_class_new_instance(2, source_argv, rb_cYARPSource); lex_data_t lex_data = { @@ -410,7 +275,7 @@ lex(int argc, VALUE *argv, VALUE self) { VALUE filepath; rb_scan_args(argc, argv, "11", &string, &filepath); - input_t input; + yp_string_t input; input_load_string(&input, string); return lex_input(&input, check_filepath(filepath)); } @@ -418,13 +283,13 @@ lex(int argc, VALUE *argv, VALUE self) { // Return an array of tokens corresponding to the given file. static VALUE lex_file(VALUE self, VALUE filepath) { - input_t input; + yp_string_t input; const char *checked = check_filepath(filepath); - if (input_load_filepath(&input, checked) != 0) return Qnil; + if (!yp_string_mapped_init(&input, checked)) return Qnil; VALUE value = lex_input(&input, checked); - input_unload_filepath(&input); + yp_string_free(&input); return value; } @@ -435,9 +300,9 @@ lex_file(VALUE self, VALUE filepath) { // Parse the given input and return a ParseResult instance. static VALUE -parse_input(input_t *input, const char *filepath) { +parse_input(yp_string_t *input, const char *filepath) { yp_parser_t parser; - yp_parser_init(&parser, input->source, input->size, filepath); + yp_parser_init(&parser, yp_string_source(input), yp_string_length(input), filepath); yp_node_t *node = yp_parse(&parser, false); rb_encoding *encoding = rb_enc_find(parser.encoding.name); @@ -466,13 +331,14 @@ parse(int argc, VALUE *argv, VALUE self) { VALUE filepath; rb_scan_args(argc, argv, "11", &string, &filepath); - input_t input; + yp_string_t input; input_load_string(&input, string); #ifdef YARP_DEBUG_MODE_BUILD - char* dup = malloc(input.size); - memcpy(dup, input.source, input.size); - input.source = dup; + size_t length = yp_string_length(&input); + char* dup = malloc(length); + memcpy(dup, yp_string_source(&input), length); + yp_string_constant_init(&input, dup, length); #endif VALUE value = parse_input(&input, check_filepath(filepath)); @@ -487,13 +353,13 @@ parse(int argc, VALUE *argv, VALUE self) { // Parse the given file and return a ParseResult instance. static VALUE parse_file(VALUE self, VALUE filepath) { - input_t input; + yp_string_t input; const char *checked = check_filepath(filepath); - if (input_load_filepath(&input, checked) != 0) return Qnil; + if (!yp_string_mapped_init(&input, checked)) return Qnil; VALUE value = parse_input(&input, checked); - input_unload_filepath(&input); + yp_string_free(&input); return value; } @@ -586,13 +452,13 @@ memsize(VALUE self, VALUE string) { // parser for memory and speed. static VALUE profile_file(VALUE self, VALUE filepath) { - input_t input; + yp_string_t input; const char *checked = check_filepath(filepath); - if (input_load_filepath(&input, checked) != 0) return Qnil; + if (!yp_string_mapped_init(&input, checked)) return Qnil; yp_parser_t parser; - yp_parser_init(&parser, input.source, input.size, checked); + yp_parser_init(&parser, yp_string_source(&input), yp_string_length(&input), checked); yp_node_t *node = yp_parse(&parser, false); yp_node_destroy(&parser, node); diff --git a/yarp/extension.h b/yarp/extension.h index d19c390f2bbc77..1f281240c2d061 100644 --- a/yarp/extension.h +++ b/yarp/extension.h @@ -5,16 +5,6 @@ #include #include "yarp.h" -// The following headers are necessary to read files using demand paging. -#ifdef _WIN32 -#include -#else -#include -#include -#include -#include -#endif - #define EXPECTED_YARP_VERSION "0.4.0" VALUE yp_source_new(yp_parser_t *parser); diff --git a/yarp/util/yp_string.c b/yarp/util/yp_string.c index 248c082a863921..12ae5537c05bd8 100644 --- a/yarp/util/yp_string.c +++ b/yarp/util/yp_string.c @@ -1,5 +1,15 @@ #include "yarp/util/yp_string.h" +// The following headers are necessary to read files using demand paging. +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#endif + // Initialize a shared string that is based on initial input. void yp_string_shared_init(yp_string_t *string, const char *start, const char *end) { @@ -36,6 +46,17 @@ yp_string_constant_init(yp_string_t *string, const char *source, size_t length) }; } +static void +yp_string_mapped_init_internal(yp_string_t *string, char *source, size_t length) { + *string = (yp_string_t) { + .type = YP_STRING_MAPPED, + .as.mapped = { + .source = source, + .length = length + } + }; +} + // Returns the memory size associated with the string. size_t yp_string_memsize(const yp_string_t *string) { @@ -84,5 +105,113 @@ YP_EXPORTED_FUNCTION void yp_string_free(yp_string_t *string) { if (string->type == YP_STRING_OWNED) { free(string->as.owned.source); + } else if (string->type == YP_STRING_MAPPED && string->as.mapped.length) { + void *memory = (void *) string->as.mapped.source; + #if defined(_WIN32) + UnmapViewOfFile(memory); + #elif defined(HAVE_MMAP) + munmap(memory, string->as.mapped.length); + #else + free(memory); + #endif + } +} + +bool +yp_string_mapped_init(yp_string_t *string, const char *filepath) { +#ifdef _WIN32 + // Open the file for reading. + HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (file == INVALID_HANDLE_VALUE) { + perror("CreateFile failed"); + return false; + } + + // Get the file size. + DWORD file_size = GetFileSize(file, NULL); + if (file_size == INVALID_FILE_SIZE) { + CloseHandle(file); + perror("GetFileSize failed"); + return false; + } + + // 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) { + CloseHandle(file); + yp_string_mapped_init_internal(string, "", 0); + return true; + } + + // Create a mapping of the file. + HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); + if (mapping == NULL) { + CloseHandle(file); + perror("CreateFileMapping failed"); + return false; } + + // Map the file into memory. + char *source = (char *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); + CloseHandle(mapping); + CloseHandle(file); + + if (source == NULL) { + perror("MapViewOfFile failed"); + return false; + } + + yp_string_mapped_init_internal(string, source, (size_t) file_size); + return true; +#else + // Open the file for reading + int fd = open(filepath, O_RDONLY); + if (fd == -1) { + perror("open"); + return false; + } + + // Stat the file to get the file size + struct stat sb; + if (fstat(fd, &sb) == -1) { + close(fd); + perror("fstat"); + return false; + } + + // mmap the file descriptor to virtually get the contents + size_t size = (size_t) sb.st_size; + char *source = NULL; + + if (size == 0) { + close(fd); + yp_string_mapped_init_internal(string, "", 0); + return true; + } + +#ifdef HAVE_MMAP + source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (source == MAP_FAILED) { + perror("Map failed"); + return false; + } +#else + source = malloc(size); + if (source == NULL) { + return false; + } + + ssize_t read_size = read(fd, (void *) source, size); + if (read_size < 0 || (size_t)read_size != size) { + perror("Read size is incorrect"); + free((void *) source); + return false; + } +#endif + + close(fd); + yp_string_mapped_init_internal(string, source, size); + return true; +#endif } diff --git a/yarp/util/yp_string.h b/yarp/util/yp_string.h index eecd71ea5b3c89..4d9612674d9cee 100644 --- a/yarp/util/yp_string.h +++ b/yarp/util/yp_string.h @@ -3,13 +3,14 @@ #include "yarp/defines.h" +#include #include #include #include // This struct represents a string value. typedef struct { - enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT } type; + enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT, YP_STRING_MAPPED } type; union { struct { @@ -26,6 +27,11 @@ typedef struct { const char *source; size_t length; } constant; + + struct { + char *source; + size_t length; + } mapped; } as; } yp_string_t; @@ -38,6 +44,17 @@ void yp_string_owned_init(yp_string_t *string, char *source, size_t length); // Initialize a constant string that doesn't own its memory source. void yp_string_constant_init(yp_string_t *string, const char *source, size_t length); +// Read the file indicated by the filepath parameter into source and load its +// contents and size into the given yp_string_t. +// The given yp_string_t should be freed using yp_string_free() 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`. +bool yp_string_mapped_init(yp_string_t *string, const char *filepath); + // Returns the memory size associated with the string. size_t yp_string_memsize(const yp_string_t *string); From 7cc5b22bbc2768cb9280fcd879cc934b0f44deeb Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 29 Jul 2023 16:55:48 +0200 Subject: [PATCH 101/158] [ruby/yarp] Add comment that extension.c should not contain non-trivial logic https://github.com/ruby/yarp/commit/638f6849be --- yarp/extension.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yarp/extension.c b/yarp/extension.c index a189b1a8769dbb..1044dc3d085344 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -1,5 +1,8 @@ #include "yarp/extension.h" +// NOTE: this file should contain only bindings. +// All non-trivial logic should be in librubyparser so it can be shared its the various callers. + VALUE rb_cYARP; VALUE rb_cYARPSource; VALUE rb_cYARPToken; From ab2f638a275ae8aaf55a4937dcb3f898cf7ddad0 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 29 Jul 2023 17:27:26 +0200 Subject: [PATCH 102/158] [ruby/yarp] Test YARP.parse_file by using it in tests https://github.com/ruby/yarp/commit/c603bba89a --- test/newline_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/newline_test.rb b/test/newline_test.rb index 09d0c09e5b36e7..29c3b7f017a9fc 100644 --- a/test/newline_test.rb +++ b/test/newline_test.rb @@ -25,7 +25,7 @@ def visit(node) source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) expected = rubyvm_lines(source) - result = YARP.parse(source, relative) + result = YARP.parse_file(filepath) assert_empty result.errors result.mark_newlines From b6f26c2e4a95e71f67b84e36b4368d6d820ffb5b Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 1 Aug 2023 17:37:57 +0200 Subject: [PATCH 103/158] [ruby/yarp] Use common fields for yp_string_t * Otherwise it is undefined behavior to access the field of another `.as`. * Accessing the right `.as` field according mode would be extra overhead. https://github.com/ruby/yarp/commit/7dc41ee803 --- yarp/unescape.c | 6 ++---- yarp/util/yp_string.c | 49 +++++++++++++++---------------------------- yarp/util/yp_string.h | 27 +++++------------------- yarp/yarp.c | 9 ++++---- 4 files changed, 28 insertions(+), 63 deletions(-) diff --git a/yarp/unescape.c b/yarp/unescape.c index 3f6e70216c4b31..32bfb6e53d02a2 100644 --- a/yarp/unescape.c +++ b/yarp/unescape.c @@ -461,10 +461,8 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len return; } - yp_string_owned_init(string, allocated, length); - // This is the memory address where we're putting the unescaped string. - char *dest = string->as.owned.source; + char *dest = allocated; size_t dest_length = 0; // This is the current position in the source string that we're looking at. @@ -525,7 +523,7 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len // We also need to update the length at the end. This is because every escape // reduces the length of the final string, and we don't want garbage at the // end. - string->as.owned.length = dest_length + ((size_t) (end - cursor)); + yp_string_owned_init(string, allocated, dest_length + ((size_t) (end - cursor))); } YP_EXPORTED_FUNCTION bool diff --git a/yarp/util/yp_string.c b/yarp/util/yp_string.c index 12ae5537c05bd8..45822635924438 100644 --- a/yarp/util/yp_string.c +++ b/yarp/util/yp_string.c @@ -13,12 +13,11 @@ // Initialize a shared string that is based on initial input. void yp_string_shared_init(yp_string_t *string, const char *start, const char *end) { + assert(start <= end); *string = (yp_string_t) { .type = YP_STRING_SHARED, - .as.shared = { - .start = start, - .end = end - } + .source = (char*) start, + .length = (size_t) (end - start) }; } @@ -27,10 +26,8 @@ void yp_string_owned_init(yp_string_t *string, char *source, size_t length) { *string = (yp_string_t) { .type = YP_STRING_OWNED, - .as.owned = { - .source = source, - .length = length - } + .source = source, + .length = length }; } @@ -39,10 +36,8 @@ void yp_string_constant_init(yp_string_t *string, const char *source, size_t length) { *string = (yp_string_t) { .type = YP_STRING_CONSTANT, - .as.constant = { - .source = source, - .length = length - } + .source = (char*) source, + .length = length }; } @@ -50,10 +45,8 @@ static void yp_string_mapped_init_internal(yp_string_t *string, char *source, size_t length) { *string = (yp_string_t) { .type = YP_STRING_MAPPED, - .as.mapped = { - .source = source, - .length = length - } + .source = source, + .length = length }; } @@ -62,7 +55,7 @@ size_t yp_string_memsize(const yp_string_t *string) { size_t size = sizeof(yp_string_t); if (string->type == YP_STRING_OWNED) { - size += string->as.owned.length; + size += string->length; } return size; } @@ -77,40 +70,32 @@ yp_string_ensure_owned(yp_string_t *string) { const char *source = yp_string_source(string); yp_string_owned_init(string, malloc(length), length); - memcpy(string->as.owned.source, source, length); + memcpy(string->source, source, length); } // Returns the length associated with the string. YP_EXPORTED_FUNCTION size_t yp_string_length(const yp_string_t *string) { - if (string->type == YP_STRING_SHARED) { - return (size_t) (string->as.shared.end - string->as.shared.start); - } else { - return string->as.owned.length; - } + return string->length; } // Returns the start pointer associated with the string. YP_EXPORTED_FUNCTION const char * yp_string_source(const yp_string_t *string) { - if (string->type == YP_STRING_SHARED) { - return string->as.shared.start; - } else { - return string->as.owned.source; - } + return string->source; } // Free the associated memory of the given string. YP_EXPORTED_FUNCTION void yp_string_free(yp_string_t *string) { if (string->type == YP_STRING_OWNED) { - free(string->as.owned.source); - } else if (string->type == YP_STRING_MAPPED && string->as.mapped.length) { - void *memory = (void *) string->as.mapped.source; + free(string->source); + } else if (string->type == YP_STRING_MAPPED && string->length) { + void *memory = (void *) string->source; #if defined(_WIN32) UnmapViewOfFile(memory); #elif defined(HAVE_MMAP) - munmap(memory, string->as.mapped.length); + munmap(memory, string->length); #else free(memory); #endif diff --git a/yarp/util/yp_string.h b/yarp/util/yp_string.h index 4d9612674d9cee..108915ce2dac91 100644 --- a/yarp/util/yp_string.h +++ b/yarp/util/yp_string.h @@ -3,6 +3,7 @@ #include "yarp/defines.h" +#include #include #include #include @@ -11,30 +12,12 @@ // This struct represents a string value. typedef struct { enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT, YP_STRING_MAPPED } type; - - union { - struct { - const char *start; - const char *end; - } shared; - - struct { - char *source; - size_t length; - } owned; - - struct { - const char *source; - size_t length; - } constant; - - struct { - char *source; - size_t length; - } mapped; - } as; + char *source; + size_t length; } yp_string_t; +#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_CONSTANT, .source = NULL, .length = 0 }) + // Initialize a shared string that is based on initial input. void yp_string_shared_init(yp_string_t *string, const char *start, const char *end); diff --git a/yarp/yarp.c b/yarp/yarp.c index 83c4cc2ccfc037..61baae3a5fb867 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -445,7 +445,6 @@ not_provided(yp_parser_t *parser) { return (yp_token_t) { .type = YP_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start }; } -#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_SHARED, .as.shared.start = NULL, .as.shared.end = NULL }) #define YP_LOCATION_NULL_VALUE(parser) ((yp_location_t) { .start = parser->start, .end = parser->start }) #define YP_LOCATION_TOKEN_VALUE(token) ((yp_location_t) { .start = (token)->start, .end = (token)->end }) #define YP_LOCATION_NODE_VALUE(node) ((yp_location_t) { .start = (node)->location.start, .end = (node)->location.end }) @@ -9345,8 +9344,8 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu // 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 = string->as.owned.length; - char *source_start = string->as.owned.source; + size_t dest_length = yp_string_length(string); + char *source_start = string->source; const char *source_cursor = source_start; const char *source_end = source_cursor + dest_length; @@ -9400,7 +9399,7 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu dedent_next = true; } - string->as.owned.length = dest_length; + string->length = dest_length; } } @@ -12450,7 +12449,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t yp_string_t *name = &named_captures.strings[index]; assert(name->type == YP_STRING_SHARED); - yp_parser_local_add_location(parser, name->as.shared.start, name->as.shared.end); + yp_parser_local_add_location(parser, name->source, name->source + name->length); } } From 3d032cf3e894fbfea00a81acf1fd90a29de9bb63 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 2 Aug 2023 09:49:26 -0400 Subject: [PATCH 104/158] [ruby/yarp] Simplify creation of numerics https://github.com/ruby/yarp/commit/e5f6ffa23a --- lib/yarp/lex_compat.rb | 10 +- test/newline_test.rb | 10 +- yarp/parser.h | 11 +- yarp/yarp.c | 285 +++++++++++++++++++++++------------------ 4 files changed, 173 insertions(+), 143 deletions(-) diff --git a/lib/yarp/lex_compat.rb b/lib/yarp/lex_compat.rb index e15f26ec95413f..984aa8185eb273 100644 --- a/lib/yarp/lex_compat.rb +++ b/lib/yarp/lex_compat.rb @@ -55,6 +55,9 @@ class LexCompat EQUAL_GREATER: :on_op, EQUAL_TILDE: :on_op, FLOAT: :on_float, + FLOAT_IMAGINARY: :on_imaginary, + FLOAT_RATIONAL: :on_rational, + FLOAT_RATIONAL_IMAGINARY: :on_imaginary, GREATER: :on_op, GREATER_EQUAL: :on_op, GREATER_GREATER: :on_op, @@ -64,8 +67,10 @@ class LexCompat HEREDOC_START: :on_heredoc_beg, IDENTIFIER: :on_ident, IGNORED_NEWLINE: :on_ignored_nl, - IMAGINARY_NUMBER: :on_imaginary, INTEGER: :on_int, + INTEGER_IMAGINARY: :on_imaginary, + INTEGER_RATIONAL: :on_rational, + INTEGER_RATIONAL_IMAGINARY: :on_imaginary, INSTANCE_VARIABLE: :on_ivar, INVALID: :INVALID, KEYWORD___ENCODING__: :on_kw, @@ -145,7 +150,8 @@ class LexCompat PLUS: :on_op, PLUS_EQUAL: :on_op, QUESTION_MARK: :on_op, - RATIONAL_NUMBER: :on_rational, + RATIONAL_FLOAT: :on_rational, + RATIONAL_INTEGER: :on_rational, REGEXP_BEGIN: :on_regexp_beg, REGEXP_END: :on_regexp_end, SEMICOLON: :on_semicolon, diff --git a/test/newline_test.rb b/test/newline_test.rb index 29c3b7f017a9fc..5a81f52637ec81 100644 --- a/test/newline_test.rb +++ b/test/newline_test.rb @@ -38,15 +38,15 @@ def visit(node) expected.delete_at actual.index(62) elsif relative == "lib/yarp/lex_compat.rb" # extra flag for: dedent_next =\n ((token.event: due to bytecode order - actual.delete(514) + actual.delete(520) # different line for: token =\n case event: due to bytecode order - actual.delete(571) - expected.delete(572) + actual.delete(577) + expected.delete(578) # extra flag for: lex_state =\n if RIPPER: due to bytecode order - actual.delete(604) + actual.delete(610) # extra flag for: (token[2].start_with?("\#$") || token[2].start_with?("\#@")) # unclear when ParenthesesNode should allow a second flag on the same line or not - actual.delete(731) + actual.delete(737) end assert_equal expected, actual diff --git a/yarp/parser.h b/yarp/parser.h index a23f88608497aa..2091be7fd92c8f 100644 --- a/yarp/parser.h +++ b/yarp/parser.h @@ -96,10 +96,7 @@ typedef struct yp_lex_mode { // 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. - YP_LEX_STRING, - - // you lexed a number with extra information attached - YP_LEX_NUMERIC, + YP_LEX_STRING } mode; union { @@ -163,12 +160,6 @@ typedef struct yp_lex_mode { char breakpoints[6]; } string; - struct { - yp_token_type_t type; - const char *start; - const char *end; - } numeric; - struct { // These pointers point to the beginning and end of the heredoc // identifier. diff --git a/yarp/yarp.c b/yarp/yarp.c index 61baae3a5fb867..1ad624a9a93536 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -111,7 +111,6 @@ debug_lex_mode(yp_parser_t *parser) { case YP_LEX_LIST: fprintf(stderr, "LIST (terminator=%c, interpolation=%d)", lex_mode->as.list.terminator, lex_mode->as.list.interpolation); break; case YP_LEX_REGEXP: fprintf(stderr, "REGEXP (terminator=%c)", lex_mode->as.regexp.terminator); break; case YP_LEX_STRING: fprintf(stderr, "STRING (terminator=%c, interpolation=%d)", lex_mode->as.string.terminator, lex_mode->as.string.interpolation); break; - case YP_LEX_NUMERIC: fprintf(stderr, "NUMERIC (token_type=%s)", yp_token_type_to_str(lex_mode->as.numeric.type)); break; } lex_mode = lex_mode->prev; @@ -1916,6 +1915,69 @@ yp_float_node_create(yp_parser_t *parser, const yp_token_t *token) { return node; } +// Allocate and initialize a new FloatNode node from a FLOAT_IMAGINARY token. +static yp_imaginary_node_t * +yp_float_node_imaginary_create(yp_parser_t *parser, const yp_token_t *token) { + assert(token->type == YP_TOKEN_FLOAT_IMAGINARY); + + yp_imaginary_node_t *node = YP_ALLOC_NODE(parser, yp_imaginary_node_t); + *node = (yp_imaginary_node_t) { + { + .type = YP_NODE_IMAGINARY_NODE, + .location = YP_LOCATION_TOKEN_VALUE(token) + }, + .numeric = (yp_node_t *) yp_float_node_create(parser, &((yp_token_t) { + .type = YP_TOKEN_FLOAT, + .start = token->start, + .end = token->end - 1 + })) + }; + + return node; +} + +// Allocate and initialize a new FloatNode node from a FLOAT_RATIONAL token. +static yp_rational_node_t * +yp_float_node_rational_create(yp_parser_t *parser, const yp_token_t *token) { + assert(token->type == YP_TOKEN_FLOAT_RATIONAL); + + yp_rational_node_t *node = YP_ALLOC_NODE(parser, yp_rational_node_t); + *node = (yp_rational_node_t) { + { + .type = YP_NODE_RATIONAL_NODE, + .location = YP_LOCATION_TOKEN_VALUE(token) + }, + .numeric = (yp_node_t *) yp_float_node_create(parser, &((yp_token_t) { + .type = YP_TOKEN_FLOAT, + .start = token->start, + .end = token->end - 1 + })) + }; + + return node; +} + +// Allocate and initialize a new FloatNode node from a FLOAT_RATIONAL_IMAGINARY token. +static yp_imaginary_node_t * +yp_float_node_rational_imaginary_create(yp_parser_t *parser, const yp_token_t *token) { + assert(token->type == YP_TOKEN_FLOAT_RATIONAL_IMAGINARY); + + yp_imaginary_node_t *node = YP_ALLOC_NODE(parser, yp_imaginary_node_t); + *node = (yp_imaginary_node_t) { + { + .type = YP_NODE_IMAGINARY_NODE, + .location = YP_LOCATION_TOKEN_VALUE(token) + }, + .numeric = (yp_node_t *) yp_float_node_rational_create(parser, &((yp_token_t) { + .type = YP_TOKEN_FLOAT_RATIONAL, + .start = token->start, + .end = token->end - 1 + })) + }; + + return node; +} + // Allocate and initialize a new ForNode node. static yp_for_node_t * yp_for_node_create( @@ -2297,90 +2359,66 @@ yp_integer_node_create(yp_parser_t *parser, const yp_token_t *token) { return node; } -// Allocate and initialize a new RationalNode node. +// Allocate and initialize a new IntegerNode node from an INTEGER_IMAGINARY token. +static yp_imaginary_node_t * +yp_integer_node_imaginary_create(yp_parser_t *parser, const yp_token_t *token) { + assert(token->type == YP_TOKEN_INTEGER_IMAGINARY); + + yp_imaginary_node_t *node = YP_ALLOC_NODE(parser, yp_imaginary_node_t); + *node = (yp_imaginary_node_t) { + { + .type = YP_NODE_IMAGINARY_NODE, + .location = YP_LOCATION_TOKEN_VALUE(token) + }, + .numeric = (yp_node_t *) yp_integer_node_create(parser, &((yp_token_t) { + .type = YP_TOKEN_INTEGER, + .start = token->start, + .end = token->end - 1 + })) + }; + + return node; +} + +// Allocate and initialize a new IntegerNode node from an INTEGER_RATIONAL token. static yp_rational_node_t * -yp_rational_node_create(yp_parser_t *parser, const yp_token_t *token) { - assert(token->type == YP_TOKEN_RATIONAL_NUMBER); - assert(parser->lex_modes.current->mode == YP_LEX_NUMERIC); - - yp_node_t *numeric_node; - yp_token_t numeric_token = { - .type = parser->lex_modes.current->as.numeric.type, - .start = parser->lex_modes.current->as.numeric.start, - .end = parser->lex_modes.current->as.numeric.end - }; - switch (parser->lex_modes.current->as.numeric.type) { - case YP_TOKEN_INTEGER: { - lex_mode_pop(parser); - numeric_node = (yp_node_t *)yp_integer_node_create(parser, &numeric_token); - break; - } - case YP_TOKEN_FLOAT: { - lex_mode_pop(parser); - numeric_node = (yp_node_t *)yp_float_node_create(parser, &numeric_token); - break; - } - default: { - lex_mode_pop(parser); - numeric_node = (yp_node_t *)yp_missing_node_create(parser, numeric_token.start, numeric_token.end); - (void)numeric_node; // Suppress clang-analyzer-deadcode.DeadStores warning - assert(false && "unreachable"); - } - } +yp_integer_node_rational_create(yp_parser_t *parser, const yp_token_t *token) { + assert(token->type == YP_TOKEN_INTEGER_RATIONAL); yp_rational_node_t *node = YP_ALLOC_NODE(parser, yp_rational_node_t); - *node = (yp_rational_node_t) { - { .type = YP_NODE_RATIONAL_NODE, .location = YP_LOCATION_TOKEN_VALUE(token) }, - .numeric = numeric_node, + { + .type = YP_NODE_RATIONAL_NODE, + .location = YP_LOCATION_TOKEN_VALUE(token) + }, + .numeric = (yp_node_t *) yp_integer_node_create(parser, &((yp_token_t) { + .type = YP_TOKEN_INTEGER, + .start = token->start, + .end = token->end - 1 + })) }; - assert(parser->lex_modes.current->mode != YP_LEX_NUMERIC); + return node; } -// Allocate and initialize a new ImaginaryNode node. +// Allocate and initialize a new IntegerNode node from an INTEGER_RATIONAL_IMAGINARY token. static yp_imaginary_node_t * -yp_imaginary_node_create(yp_parser_t *parser, const yp_token_t *token) { - assert(token->type == YP_TOKEN_IMAGINARY_NUMBER); - assert(parser->lex_modes.current->mode == YP_LEX_NUMERIC); - - yp_node_t *numeric_node; - yp_token_t numeric_token = { - .type = parser->lex_modes.current->as.numeric.type, - .start = parser->lex_modes.current->as.numeric.start, - .end = parser->lex_modes.current->as.numeric.end - }; - switch (parser->lex_modes.current->as.numeric.type) { - case YP_TOKEN_INTEGER: { - lex_mode_pop(parser); - numeric_node = (yp_node_t *)yp_integer_node_create(parser, &numeric_token); - break; - } - case YP_TOKEN_FLOAT: { - lex_mode_pop(parser); - numeric_node = (yp_node_t *)yp_float_node_create(parser, &numeric_token); - break; - } - case YP_TOKEN_RATIONAL_NUMBER: { - lex_mode_pop(parser); - numeric_node = (yp_node_t *)yp_rational_node_create(parser, &numeric_token); - break; - } - default: { - lex_mode_pop(parser); - numeric_node = (yp_node_t *)yp_missing_node_create(parser, numeric_token.start, numeric_token.end); - (void)numeric_node; // Suppress clang-analyzer-deadcode.DeadStores warning - assert(false && "unreachable"); - } - } +yp_integer_node_rational_imaginary_create(yp_parser_t *parser, const yp_token_t *token) { + assert(token->type == YP_TOKEN_INTEGER_RATIONAL_IMAGINARY); yp_imaginary_node_t *node = YP_ALLOC_NODE(parser, yp_imaginary_node_t); - *node = (yp_imaginary_node_t) { - { .type = YP_NODE_IMAGINARY_NODE, .location = YP_LOCATION_TOKEN_VALUE(token) }, - .numeric = numeric_node + { + .type = YP_NODE_IMAGINARY_NODE, + .location = YP_LOCATION_TOKEN_VALUE(token) + }, + .numeric = (yp_node_t *) yp_integer_node_rational_create(parser, &((yp_token_t) { + .type = YP_TOKEN_INTEGER_RATIONAL, + .start = token->start, + .end = token->end - 1 + })) }; - assert(parser->lex_modes.current->mode != YP_LEX_NUMERIC); + return node; } @@ -4775,37 +4813,6 @@ lex_numeric_prefix(yp_parser_t *parser) { return type; } -static yp_token_type_t -lex_finalize_numeric_type(yp_parser_t *parser, yp_token_type_t numeric_type, const char *numeric_end, const char *rational_end, const char *imaginary_end) { - if (rational_end || imaginary_end) { - lex_mode_push(parser, (yp_lex_mode_t) { - .mode = YP_LEX_NUMERIC, - .as.numeric.type = numeric_type, - .as.numeric.start = parser->current.start, - .as.numeric.end = numeric_end - }); - } - - if (rational_end && imaginary_end) { - lex_mode_push(parser, (yp_lex_mode_t) { - .mode = YP_LEX_NUMERIC, - .as.numeric.type = YP_TOKEN_RATIONAL_NUMBER, - .as.numeric.start = parser->current.start, - .as.numeric.end = rational_end - }); - } - - if (imaginary_end) { - return YP_TOKEN_IMAGINARY_NUMBER; - } - - if (rational_end) { - return YP_TOKEN_RATIONAL_NUMBER; - } - - return numeric_type; -} - static yp_token_type_t lex_numeric(yp_parser_t *parser) { yp_token_type_t type = YP_TOKEN_INTEGER; @@ -4814,22 +4821,35 @@ lex_numeric(yp_parser_t *parser) { type = lex_numeric_prefix(parser); const char *end = parser->current.end; - const char *rational_end = NULL; - const char *imaginary_end = NULL; + yp_token_type_t suffix_type = type; - if (match(parser, 'r')) { - rational_end = parser->current.end; - } + if (type == YP_TOKEN_INTEGER) { + if (match(parser, 'r')) { + suffix_type = YP_TOKEN_INTEGER_RATIONAL; - if (match(parser, 'i')) { - imaginary_end = parser->current.end; + if (match(parser, 'i')) { + suffix_type = YP_TOKEN_INTEGER_RATIONAL_IMAGINARY; + } + } else if (match(parser, 'i')) { + suffix_type = YP_TOKEN_INTEGER_IMAGINARY; + } + } else { + if (match(parser, 'r')) { + suffix_type = YP_TOKEN_FLOAT_RATIONAL; + + if (match(parser, 'i')) { + suffix_type = YP_TOKEN_FLOAT_RATIONAL_IMAGINARY; + } + } else if (match(parser, 'i')) { + suffix_type = YP_TOKEN_FLOAT_IMAGINARY; + } } const unsigned char uc = (const unsigned char) peek(parser); if (uc != '\0' && (uc >= 0x80 || ((uc >= 'a' && uc <= 'z') || (uc >= 'A' && uc <= 'Z')) || uc == '_')) { parser->current.end = end; } else { - type = lex_finalize_numeric_type(parser, type, end, rational_end, imaginary_end); + type = suffix_type; } } @@ -5449,7 +5469,6 @@ parser_lex(yp_parser_t *parser) { case YP_LEX_DEFAULT: case YP_LEX_EMBEXPR: case YP_LEX_EMBVAR: - case YP_LEX_NUMERIC: // We have a specific named label here because we are going to jump back to // this location in the event that we have lexed a token that should not be @@ -8936,13 +8955,15 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) { // This macro allows you to define a case statement for all of the token types // that represent the beginning of nodes that are "primitives" in a pattern // matching expression. -#define YP_CASE_PRIMITIVE YP_TOKEN_INTEGER: case YP_TOKEN_FLOAT: case YP_TOKEN_RATIONAL_NUMBER: \ - case YP_TOKEN_IMAGINARY_NUMBER: case YP_TOKEN_SYMBOL_BEGIN: case YP_TOKEN_REGEXP_BEGIN: case YP_TOKEN_BACKTICK: \ - case YP_TOKEN_PERCENT_LOWER_X: case YP_TOKEN_PERCENT_LOWER_I: case YP_TOKEN_PERCENT_LOWER_W: \ - case YP_TOKEN_PERCENT_UPPER_I: case YP_TOKEN_PERCENT_UPPER_W: case YP_TOKEN_STRING_BEGIN: case YP_TOKEN_KEYWORD_NIL: \ - case YP_TOKEN_KEYWORD_SELF: case YP_TOKEN_KEYWORD_TRUE: case YP_TOKEN_KEYWORD_FALSE: case YP_TOKEN_KEYWORD___FILE__: \ - case YP_TOKEN_KEYWORD___LINE__: case YP_TOKEN_KEYWORD___ENCODING__: case YP_TOKEN_MINUS_GREATER: \ - case YP_TOKEN_HEREDOC_START: case YP_TOKEN_UMINUS_NUM: case YP_TOKEN_CHARACTER_LITERAL +#define YP_CASE_PRIMITIVE YP_TOKEN_INTEGER: case YP_TOKEN_INTEGER_IMAGINARY: case YP_TOKEN_INTEGER_RATIONAL: \ + case YP_TOKEN_INTEGER_RATIONAL_IMAGINARY: case YP_TOKEN_FLOAT: case YP_TOKEN_FLOAT_IMAGINARY: \ + case YP_TOKEN_FLOAT_RATIONAL: case YP_TOKEN_FLOAT_RATIONAL_IMAGINARY: case YP_TOKEN_SYMBOL_BEGIN: \ + case YP_TOKEN_REGEXP_BEGIN: case YP_TOKEN_BACKTICK: case YP_TOKEN_PERCENT_LOWER_X: case YP_TOKEN_PERCENT_LOWER_I: \ + case YP_TOKEN_PERCENT_LOWER_W: case YP_TOKEN_PERCENT_UPPER_I: case YP_TOKEN_PERCENT_UPPER_W: \ + case YP_TOKEN_STRING_BEGIN: case YP_TOKEN_KEYWORD_NIL: case YP_TOKEN_KEYWORD_SELF: case YP_TOKEN_KEYWORD_TRUE: \ + case YP_TOKEN_KEYWORD_FALSE: case YP_TOKEN_KEYWORD___FILE__: case YP_TOKEN_KEYWORD___LINE__: \ + case YP_TOKEN_KEYWORD___ENCODING__: case YP_TOKEN_MINUS_GREATER: case YP_TOKEN_HEREDOC_START: \ + case YP_TOKEN_UMINUS_NUM: case YP_TOKEN_CHARACTER_LITERAL // This macro allows you to define a case statement for all of the token types // that could begin a parameter. @@ -10305,7 +10326,16 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } case YP_TOKEN_FLOAT: parser_lex(parser); - return (yp_node_t *)yp_float_node_create(parser, &parser->previous); + return (yp_node_t *) yp_float_node_create(parser, &parser->previous); + case YP_TOKEN_FLOAT_IMAGINARY: + parser_lex(parser); + return (yp_node_t *) yp_float_node_imaginary_create(parser, &parser->previous); + case YP_TOKEN_FLOAT_RATIONAL: + parser_lex(parser); + return (yp_node_t *) yp_float_node_rational_create(parser, &parser->previous); + case YP_TOKEN_FLOAT_RATIONAL_IMAGINARY: + parser_lex(parser); + return (yp_node_t *) yp_float_node_rational_imaginary_create(parser, &parser->previous); case YP_TOKEN_NUMBERED_REFERENCE: { parser_lex(parser); yp_node_t *node = (yp_node_t *) yp_numbered_reference_read_node_create(parser, &parser->previous); @@ -10442,9 +10472,6 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { return node; } } - case YP_TOKEN_IMAGINARY_NUMBER: - parser_lex(parser); - return (yp_node_t *) yp_imaginary_node_create(parser, &parser->previous); case YP_TOKEN_INSTANCE_VARIABLE: { parser_lex(parser); yp_node_t *node = (yp_node_t *) yp_instance_variable_read_node_create(parser, &parser->previous); @@ -10458,6 +10485,15 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { case YP_TOKEN_INTEGER: parser_lex(parser); return (yp_node_t *) yp_integer_node_create(parser, &parser->previous); + case YP_TOKEN_INTEGER_IMAGINARY: + parser_lex(parser); + return (yp_node_t *) yp_integer_node_imaginary_create(parser, &parser->previous); + case YP_TOKEN_INTEGER_RATIONAL: + parser_lex(parser); + return (yp_node_t *) yp_integer_node_rational_create(parser, &parser->previous); + case YP_TOKEN_INTEGER_RATIONAL_IMAGINARY: + parser_lex(parser); + return (yp_node_t *) yp_integer_node_rational_imaginary_create(parser, &parser->previous); case YP_TOKEN_KEYWORD___ENCODING__: parser_lex(parser); return (yp_node_t *) yp_source_encoding_node_create(parser, &parser->previous); @@ -11617,9 +11653,6 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { return (yp_node_t *) array; } - case YP_TOKEN_RATIONAL_NUMBER: - parser_lex(parser); - return (yp_node_t *) yp_rational_node_create(parser, &parser->previous); case YP_TOKEN_REGEXP_BEGIN: { yp_token_t opening = parser->current; parser_lex(parser); From 9c61e0c831c8890bdfac5bf537bea21d4ae84e05 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 2 Aug 2023 10:01:45 -0400 Subject: [PATCH 105/158] [ruby/yarp] Ensure token cannot begin an expression https://github.com/ruby/yarp/commit/837522217c --- yarp/yarp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/yarp/yarp.c b/yarp/yarp.c index 1ad624a9a93536..3d7fcd4595f4bf 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -7476,6 +7476,7 @@ token_begins_expression_p(yp_token_type_t type) { case YP_TOKEN_KEYWORD_END: case YP_TOKEN_KEYWORD_ELSE: case YP_TOKEN_KEYWORD_ELSIF: + case YP_TOKEN_KEYWORD_ENSURE: case YP_TOKEN_KEYWORD_THEN: case YP_TOKEN_KEYWORD_RESCUE: case YP_TOKEN_KEYWORD_WHEN: From 7a1c497426c38c301e65c74a77b5eead98887eba Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 2 Aug 2023 10:08:59 -0400 Subject: [PATCH 106/158] [ruby/yarp] Add constant write node https://github.com/ruby/yarp/commit/a62f2f0153 --- test/yarp/snapshots/constants.txt | 6 +---- test/yarp/snapshots/methods.txt | 8 +++---- .../unparser/corpus/literal/assignment.txt | 8 +++---- test/yarp/snapshots/variables.txt | 8 +++---- .../snapshots/whitequark/casgn_unscoped.txt | 6 +---- .../snapshots/whitequark/parser_bug_490.txt | 8 +++---- yarp/yarp.c | 24 ++++++++++++++++++- 7 files changed, 41 insertions(+), 27 deletions(-) diff --git a/test/yarp/snapshots/constants.txt b/test/yarp/snapshots/constants.txt index aa97e4ba89619d..438f36599c7ed0 100644 --- a/test/yarp/snapshots/constants.txt +++ b/test/yarp/snapshots/constants.txt @@ -29,11 +29,7 @@ ProgramNode(0...709)( (26...27), IntegerNode(28...29)() ), - ConstantPathWriteNode(31...36)( - ConstantReadNode(31...32)(), - (33...34), - IntegerNode(35...36)() - ), + ConstantWriteNode(31...36)((31...32), IntegerNode(35...36)(), (33...34)), ConstantReadNode(38...41)(), CallNode(43...48)( nil, diff --git a/test/yarp/snapshots/methods.txt b/test/yarp/snapshots/methods.txt index 83bc7e3c5ced23..8d1eee8a2a36dd 100644 --- a/test/yarp/snapshots/methods.txt +++ b/test/yarp/snapshots/methods.txt @@ -967,10 +967,10 @@ ProgramNode(0...1194)( nil, (872...875) ), - ConstantPathWriteNode(877...886)( - ConstantReadNode(877...882)(), - (883...884), - IntegerNode(885...886)() + ConstantWriteNode(877...886)( + (877...882), + IntegerNode(885...886)(), + (883...884) ), DefNode(888...903)( (898...899), diff --git a/test/yarp/snapshots/unparser/corpus/literal/assignment.txt b/test/yarp/snapshots/unparser/corpus/literal/assignment.txt index 1e06024e29d2fa..2083fb361b4e3e 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/assignment.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/assignment.txt @@ -300,10 +300,10 @@ ProgramNode(0...719)( IntegerNode(315...316)(), (313...314) ), - ConstantPathWriteNode(317...326)( - ConstantReadNode(317...322)(), - (323...324), - IntegerNode(325...326)() + ConstantWriteNode(317...326)( + (317...322), + IntegerNode(325...326)(), + (323...324) ), ConstantPathWriteNode(327...350)( ConstantPathNode(327...346)( diff --git a/test/yarp/snapshots/variables.txt b/test/yarp/snapshots/variables.txt index 8976f74a38c7a3..73645e4e52fffe 100644 --- a/test/yarp/snapshots/variables.txt +++ b/test/yarp/snapshots/variables.txt @@ -180,14 +180,14 @@ ProgramNode(0...293)( (260...263), (264...265) ), - ConstantPathWriteNode(272...282)( - ConstantReadNode(272...275)(), - (276...277), + ConstantWriteNode(272...282)( + (272...275), ArrayNode(278...282)( [IntegerNode(278...279)(), IntegerNode(281...282)()], nil, nil - ) + ), + (276...277) ), ParenthesesNode(284...293)( StatementsNode(285...292)( diff --git a/test/yarp/snapshots/whitequark/casgn_unscoped.txt b/test/yarp/snapshots/whitequark/casgn_unscoped.txt index 3687e3889139d8..16c6636bb4d07f 100644 --- a/test/yarp/snapshots/whitequark/casgn_unscoped.txt +++ b/test/yarp/snapshots/whitequark/casgn_unscoped.txt @@ -1,10 +1,6 @@ ProgramNode(0...8)( [], StatementsNode(0...8)( - [ConstantPathWriteNode(0...8)( - ConstantReadNode(0...3)(), - (4...5), - IntegerNode(6...8)() - )] + [ConstantWriteNode(0...8)((0...3), IntegerNode(6...8)(), (4...5))] ) ) diff --git a/test/yarp/snapshots/whitequark/parser_bug_490.txt b/test/yarp/snapshots/whitequark/parser_bug_490.txt index cd38544ea7dd85..6f4c3a8442cfc7 100644 --- a/test/yarp/snapshots/whitequark/parser_bug_490.txt +++ b/test/yarp/snapshots/whitequark/parser_bug_490.txt @@ -12,10 +12,10 @@ ProgramNode(0...132)( (13...15), SelfNode(16...20)(), StatementsNode(22...29)( - [ConstantPathWriteNode(22...29)( - ConstantReadNode(22...23)(), - (24...25), - NilNode(26...29)() + [ConstantWriteNode(22...29)( + (22...23), + NilNode(26...29)(), + (24...25) )] ), (31...34) diff --git a/yarp/yarp.c b/yarp/yarp.c index 3d7fcd4595f4bf..747e6cef4837b0 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -1699,6 +1699,27 @@ yp_constant_read_node_create(yp_parser_t *parser, const yp_token_t *name) { return node; } +// Allocate a new ConstantWriteNode node. +static yp_constant_write_node_t * +yp_constant_write_node_create(yp_parser_t *parser, yp_constant_read_node_t *target, const yp_token_t *operator, yp_node_t *value) { + yp_constant_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_write_node_t); + + *node = (yp_constant_write_node_t) { + { + .type = YP_NODE_CONSTANT_WRITE_NODE, + .location = { + .start = target->base.location.start, + .end = value != NULL ? value->location.end : target->base.location.end + }, + }, + .name_loc = YP_LOCATION_NODE_VALUE((yp_node_t *) target), + .operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(operator), + .value = value + }; + + return node; +} + // Allocate and initialize a new DefNode node. static yp_def_node_t * yp_def_node_create( @@ -7533,8 +7554,9 @@ parse_target(yp_parser_t *parser, yp_node_t *target, yp_token_t *operator, yp_no return (yp_node_t *) write_node; } case YP_NODE_CONSTANT_PATH_NODE: - case YP_NODE_CONSTANT_READ_NODE: return (yp_node_t *) yp_constant_path_write_node_create(parser, target, operator, value); + case YP_NODE_CONSTANT_READ_NODE: + return (yp_node_t *) yp_constant_write_node_create(parser, (yp_constant_read_node_t *) target, operator, value); case YP_NODE_BACK_REFERENCE_READ_NODE: case YP_NODE_NUMBERED_REFERENCE_READ_NODE: yp_diagnostic_list_append(&parser->error_list, target->location.start, target->location.end, "Can't set variable"); From e66e60cf696b7deaa6532273d18159b491a6e0b7 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 2 Aug 2023 10:20:52 -0400 Subject: [PATCH 107/158] [ruby/yarp] Handle invalid multiple parameters https://github.com/ruby/yarp/commit/2f83265653 --- yarp/yarp.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 747e6cef4837b0..125e3f91373700 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -3221,6 +3221,7 @@ yp_parameters_node_posts_append(yp_parameters_node_t *params, yp_node_t *param) // Set the rest parameter on a ParametersNode node. static void yp_parameters_node_rest_set(yp_parameters_node_t *params, yp_rest_parameter_node_t *param) { + assert(params->rest == NULL); yp_parameters_node_location_set(params, (yp_node_t *) param); params->rest = param; } @@ -3235,6 +3236,7 @@ yp_parameters_node_keywords_append(yp_parameters_node_t *params, yp_node_t *para // Set the keyword rest parameter on a ParametersNode node. static void yp_parameters_node_keyword_rest_set(yp_parameters_node_t *params, yp_node_t *param) { + assert(params->keyword_rest == NULL); yp_parameters_node_location_set(params, param); params->keyword_rest = param; } @@ -3242,6 +3244,7 @@ yp_parameters_node_keyword_rest_set(yp_parameters_node_t *params, yp_node_t *par // Set the block parameter on a ParametersNode node. static void yp_parameters_node_block_set(yp_parameters_node_t *params, yp_block_parameter_node_t *param) { + assert(params->block == NULL); yp_parameters_node_location_set(params, (yp_node_t *) param); params->block = param; } @@ -8321,7 +8324,13 @@ parse_parameters( } yp_block_parameter_node_t *param = yp_block_parameter_node_create(parser, &name, &operator); - yp_parameters_node_block_set(params, param); + if (params->block == NULL) { + yp_parameters_node_block_set(params, param); + } else { + yp_diagnostic_list_append(&parser->error_list, param->base.location.start, param->base.location.end, "Unexpected multiple block parameter"); + yp_parameters_node_posts_append(params, (yp_node_t *) param); + } + break; } case YP_TOKEN_UDOT_DOT_DOT: { @@ -8472,7 +8481,13 @@ parse_parameters( } yp_rest_parameter_node_t *param = yp_rest_parameter_node_create(parser, &operator, &name); - yp_parameters_node_rest_set(params, param); + if (params->rest == NULL) { + yp_parameters_node_rest_set(params, param); + } else { + yp_diagnostic_list_append(&parser->error_list, param->base.location.start, param->base.location.end, "Unexpected multiple splat parameters."); + yp_parameters_node_posts_append(params, (yp_node_t *) param); + } + break; } case YP_TOKEN_STAR_STAR: @@ -8500,7 +8515,13 @@ parse_parameters( param = (yp_node_t *) yp_keyword_rest_parameter_node_create(parser, &operator, &name); } - yp_parameters_node_keyword_rest_set(params, param); + if (params->keyword_rest == NULL) { + yp_parameters_node_keyword_rest_set(params, param); + } else { + yp_diagnostic_list_append(&parser->error_list, param->location.start, param->location.end, "Unexpected multiple double splat parameters."); + yp_parameters_node_posts_append(params, param); + } + break; } default: @@ -8511,7 +8532,13 @@ parse_parameters( // represent it. yp_token_t name = not_provided(parser); yp_rest_parameter_node_t *param = yp_rest_parameter_node_create(parser, &parser->previous, &name); - yp_parameters_node_rest_set(params, param); + + if (params->rest == NULL) { + yp_parameters_node_rest_set(params, param); + } else { + yp_diagnostic_list_append(&parser->error_list, param->base.location.start, param->base.location.end, "Unexpected multiple splat parameters."); + yp_parameters_node_posts_append(params, (yp_node_t *) param); + } } else { yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Unexpected ','."); } From 1ea9e444ecbd089b8216eff3cd5d05e34912736b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 2 Aug 2023 10:28:32 -0400 Subject: [PATCH 108/158] [ruby/yarp] Fix memory leak from constant write node creation https://github.com/ruby/yarp/commit/0071bee0bb --- yarp/yarp.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 125e3f91373700..2573663f26214d 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -1701,18 +1701,18 @@ yp_constant_read_node_create(yp_parser_t *parser, const yp_token_t *name) { // Allocate a new ConstantWriteNode node. static yp_constant_write_node_t * -yp_constant_write_node_create(yp_parser_t *parser, yp_constant_read_node_t *target, const yp_token_t *operator, yp_node_t *value) { +yp_constant_write_node_create(yp_parser_t *parser, yp_location_t *name_loc, const yp_token_t *operator, yp_node_t *value) { yp_constant_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_write_node_t); *node = (yp_constant_write_node_t) { { .type = YP_NODE_CONSTANT_WRITE_NODE, .location = { - .start = target->base.location.start, - .end = value != NULL ? value->location.end : target->base.location.end + .start = name_loc->start, + .end = value != NULL ? value->location.end : name_loc->end }, }, - .name_loc = YP_LOCATION_NODE_VALUE((yp_node_t *) target), + .name_loc = *name_loc, .operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(operator), .value = value }; @@ -7558,8 +7558,12 @@ parse_target(yp_parser_t *parser, yp_node_t *target, yp_token_t *operator, yp_no } case YP_NODE_CONSTANT_PATH_NODE: return (yp_node_t *) yp_constant_path_write_node_create(parser, target, operator, value); - case YP_NODE_CONSTANT_READ_NODE: - return (yp_node_t *) yp_constant_write_node_create(parser, (yp_constant_read_node_t *) target, operator, value); + case YP_NODE_CONSTANT_READ_NODE: { + yp_constant_write_node_t *node = yp_constant_write_node_create(parser, &target->location, operator, value); + yp_node_destroy(parser, target); + + return (yp_node_t *) node; + } case YP_NODE_BACK_REFERENCE_READ_NODE: case YP_NODE_NUMBERED_REFERENCE_READ_NODE: yp_diagnostic_list_append(&parser->error_list, target->location.start, target->location.end, "Can't set variable"); From 820a58c228b8dbd29915065f8e5f18a61442bb88 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 2 Aug 2023 13:17:31 -0400 Subject: [PATCH 109/158] [ruby/yarp] Hide debug methods https://github.com/ruby/yarp/commit/aa0dc2f301 --- lib/yarp.rb | 13 +++++- test/yarp/memsize_test.rb | 2 +- test/yarp/parse_test.rb | 2 +- test/yarp/regexp_test.rb | 94 ++++++++++++++++++++------------------ test/yarp/unescape_test.rb | 16 ++++--- yarp/extension.c | 13 +++--- 6 files changed, 80 insertions(+), 60 deletions(-) diff --git a/lib/yarp.rb b/lib/yarp.rb index 39ff7e3269d58e..79a0aaad5bd17e 100644 --- a/lib/yarp.rb +++ b/lib/yarp.rb @@ -230,9 +230,18 @@ def self.load(source, serialized) Serialize.load(source, serialized) end - def self.newlines(source) - YARP.parse(source).source.offsets + # This module is used for testing and debugging and is not meant to be used by + # consumers of this library. + module Debug + def self.newlines(source) + YARP.parse(source).source.offsets + end end + + # Marking this as private so that consumers don't see it. It makes it a little + # annoying for testing since you have to const_get it to access the methods, + # but at least this way it's clear it's not meant for consumers. + private_constant :Debug end require_relative "yarp/lex_compat" diff --git a/test/yarp/memsize_test.rb b/test/yarp/memsize_test.rb index 1a6c64f95e37bb..38aca6169f4aa5 100644 --- a/test/yarp/memsize_test.rb +++ b/test/yarp/memsize_test.rb @@ -4,7 +4,7 @@ class MemsizeTest < Test::Unit::TestCase def test_memsize - result = YARP.memsize("2 + 3") + result = YARP.const_get(:Debug).memsize("2 + 3") assert_equal 5, result[:length] assert_kind_of Integer, result[:memsize] diff --git a/test/yarp/parse_test.rb b/test/yarp/parse_test.rb index d0cdfe2c267d95..3e1c3cb8f08229 100644 --- a/test/yarp/parse_test.rb +++ b/test/yarp/parse_test.rb @@ -108,7 +108,7 @@ def test_parse_takes_file_path # Next, assert that the newlines are in the expected places. expected_newlines = [0] source.b.scan("\n") { expected_newlines << $~.offset(0)[0] + 1 } - assert_equal expected_newlines, YARP.newlines(source) + assert_equal expected_newlines, YARP.const_get(:Debug).newlines(source) # Finally, assert that we can lex the source and get the same tokens as # Ripper. diff --git a/test/yarp/regexp_test.rb b/test/yarp/regexp_test.rb index 4fd3e1d7cb79d4..035bead8130e62 100644 --- a/test/yarp/regexp_test.rb +++ b/test/yarp/regexp_test.rb @@ -8,27 +8,27 @@ class RegexpTest < Test::Unit::TestCase ############################################################################## def test_named_captures_with_arrows - assert_equal(["foo"], YARP.named_captures("(?bar)")) + assert_equal(["foo"], named_captures("(?bar)")) end def test_named_captures_with_single_quotes - assert_equal(["foo"], YARP.named_captures("(?'foo'bar)")) + assert_equal(["foo"], named_captures("(?'foo'bar)")) end def test_nested_named_captures_with_arrows - assert_equal(["foo", "bar"], YARP.named_captures("(?(?baz))")) + assert_equal(["foo", "bar"], named_captures("(?(?baz))")) end def test_nested_named_captures_with_single_quotes - assert_equal(["foo", "bar"], YARP.named_captures("(?'foo'(?'bar'baz))")) + assert_equal(["foo", "bar"], named_captures("(?'foo'(?'bar'baz))")) end def test_allows_duplicate_named_captures - assert_equal(["foo", "foo"], YARP.named_captures("(?bar)(?baz)")) + assert_equal(["foo", "foo"], named_captures("(?bar)(?baz)")) end def test_named_capture_inside_fake_range_quantifier - assert_equal(["foo"], YARP.named_captures("foo{1, (?2)}")) + assert_equal(["foo"], named_captures("foo{1, (?2)}")) end ############################################################################## @@ -38,154 +38,160 @@ def test_named_capture_inside_fake_range_quantifier ############################################################################## def test_alternation - refute_nil(YARP.named_captures("foo|bar")) + refute_nil(named_captures("foo|bar")) end def test_anchors - refute_nil(YARP.named_captures("^foo$")) + refute_nil(named_captures("^foo$")) end def test_any - refute_nil(YARP.named_captures(".")) + refute_nil(named_captures(".")) end def test_posix_character_classes - refute_nil(YARP.named_captures("[[:digit:]]")) + refute_nil(named_captures("[[:digit:]]")) end def test_negated_posix_character_classes - refute_nil(YARP.named_captures("[[:^digit:]]")) + refute_nil(named_captures("[[:^digit:]]")) end def test_invalid_posix_character_classes_should_fall_back_to_regular_classes - refute_nil(YARP.named_captures("[[:foo]]")) + refute_nil(named_captures("[[:foo]]")) end def test_character_sets - refute_nil(YARP.named_captures("[abc]")) + refute_nil(named_captures("[abc]")) end def test_nested_character_sets - refute_nil(YARP.named_captures("[[abc]]")) + refute_nil(named_captures("[[abc]]")) end def test_nested_character_sets_with_operators - refute_nil(YARP.named_captures("[[abc] && [def]]")) + refute_nil(named_captures("[[abc] && [def]]")) end def test_named_capture_inside_nested_character_set - assert_equal([], YARP.named_captures("[foo (?bar)]")) + assert_equal([], named_captures("[foo (?bar)]")) end def test_negated_character_sets - refute_nil(YARP.named_captures("[^abc]")) + refute_nil(named_captures("[^abc]")) end def test_character_ranges - refute_nil(YARP.named_captures("[a-z]")) + refute_nil(named_captures("[a-z]")) end def test_negated_character_ranges - refute_nil(YARP.named_captures("[^a-z]")) + refute_nil(named_captures("[^a-z]")) end def test_fake_named_captures_inside_character_sets - assert_equal([], YARP.named_captures("[a-z(?)]")) + assert_equal([], named_captures("[a-z(?)]")) end def test_fake_named_capture_inside_character_set_with_escaped_ending - assert_equal([], YARP.named_captures("[a-z\\](?)]")) + assert_equal([], named_captures("[a-z\\](?)]")) end def test_comments - refute_nil(YARP.named_captures("(?#foo)")) + refute_nil(named_captures("(?#foo)")) end def test_comments_with_escaped_parentheses - refute_nil(YARP.named_captures("(?#foo\\)\\))")) + refute_nil(named_captures("(?#foo\\)\\))")) end def test_non_capturing_groups - refute_nil(YARP.named_captures("(?:foo)")) + refute_nil(named_captures("(?:foo)")) end def test_positive_lookaheads - refute_nil(YARP.named_captures("(?=foo)")) + refute_nil(named_captures("(?=foo)")) end def test_negative_lookaheads - refute_nil(YARP.named_captures("(?!foo)")) + refute_nil(named_captures("(?!foo)")) end def test_positive_lookbehinds - refute_nil(YARP.named_captures("(?<=foo)")) + refute_nil(named_captures("(?<=foo)")) end def test_negative_lookbehinds - refute_nil(YARP.named_captures("(?foo)")) + refute_nil(named_captures("(?>foo)")) end def test_absence_operator - refute_nil(YARP.named_captures("(?~foo)")) + refute_nil(named_captures("(?~foo)")) end def test_conditional_expression_with_index - refute_nil(YARP.named_captures("(?(1)foo)")) + refute_nil(named_captures("(?(1)foo)")) end def test_conditional_expression_with_name - refute_nil(YARP.named_captures("(?(foo)bar)")) + refute_nil(named_captures("(?(foo)bar)")) end def test_conditional_expression_with_group - refute_nil(YARP.named_captures("(?()bar)")) + refute_nil(named_captures("(?()bar)")) end def test_options_on_groups - refute_nil(YARP.named_captures("(?imxdau:foo)")) + refute_nil(named_captures("(?imxdau:foo)")) end def test_options_on_groups_with_invalid_options - assert_nil(YARP.named_captures("(?z:bar)")) + assert_nil(named_captures("(?z:bar)")) end def test_options_on_groups_getting_turned_off - refute_nil(YARP.named_captures("(?-imx:foo)")) + refute_nil(named_captures("(?-imx:foo)")) end def test_options_on_groups_some_getting_turned_on_some_getting_turned_off - refute_nil(YARP.named_captures("(?im-x:foo)")) + refute_nil(named_captures("(?im-x:foo)")) end def test_star_quantifier - refute_nil(YARP.named_captures("foo*")) + refute_nil(named_captures("foo*")) end def test_plus_quantifier - refute_nil(YARP.named_captures("foo+")) + refute_nil(named_captures("foo+")) end def test_question_mark_quantifier - refute_nil(YARP.named_captures("foo?")) + refute_nil(named_captures("foo?")) end def test_endless_range_quantifier - refute_nil(YARP.named_captures("foo{1,}")) + refute_nil(named_captures("foo{1,}")) end def test_beginless_range_quantifier - refute_nil(YARP.named_captures("foo{,1}")) + refute_nil(named_captures("foo{,1}")) end def test_range_quantifier - refute_nil(YARP.named_captures("foo{1,2}")) + refute_nil(named_captures("foo{1,2}")) end def test_fake_range_quantifier_because_of_spaces - refute_nil(YARP.named_captures("foo{1, 2}")) + refute_nil(named_captures("foo{1, 2}")) + end + + private + + def named_captures(source) + YARP.const_get(:Debug).named_captures(source) end end diff --git a/test/yarp/unescape_test.rb b/test/yarp/unescape_test.rb index 314e59aa6a33e7..1288a128bdaf99 100644 --- a/test/yarp/unescape_test.rb +++ b/test/yarp/unescape_test.rb @@ -15,7 +15,7 @@ def test_single_quote private def assert_unescape_none(source) - assert_equal(source, YARP.unescape_none(source)) + assert_equal(source, YARP.const_get(:Debug).unescape_none(source)) end end @@ -35,7 +35,7 @@ def test_single_char private def assert_unescape_minimal(expected, source) - assert_equal(expected, YARP.unescape_minimal(source)) + assert_equal(expected, YARP.const_get(:Debug).unescape_minimal(source)) end end @@ -83,7 +83,7 @@ def test_unicode_codepoint assert_unescape_all("က", "\\u1000", "UTF-8") assert_unescape_all("တ", "\\u1010", "UTF-8") - assert_nil(YARP.unescape_all("\\uxxxx")) + assert_nil(unescape_all("\\uxxxx")) end def test_unicode_codepoints @@ -95,8 +95,8 @@ def test_unicode_codepoints assert_unescape_all("𐀐", "\\u{10010}", "UTF-8") assert_unescape_all("aĀကတ𐀀𐀐", "\\u{ 61\s100\n1000\t1010\r10000\v10010 }", "UTF-8") - assert_nil(YARP.unescape_all("\\u{110000}")) - assert_nil(YARP.unescape_all("\\u{110000 110001 110002}")) + assert_nil(unescape_all("\\u{110000}")) + assert_nil(unescape_all("\\u{110000 110001 110002}")) end def test_control_characters @@ -136,8 +136,12 @@ def test_escaping_normal_characters private + def unescape_all(source) + YARP.const_get(:Debug).unescape_all(source) + end + def assert_unescape_all(expected, source, forced_encoding = nil) - result = YARP.unescape_all(source) + result = unescape_all(source) result.force_encoding(forced_encoding) if forced_encoding assert_equal(expected, result) end diff --git a/yarp/extension.c b/yarp/extension.c index 1044dc3d085344..d4ce3625d82eb8 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -512,12 +512,13 @@ Init_yarp(void) { // Next, the functions that will be called by the parser to perform various // internal tasks. We expose these to make them easier to test. - rb_define_singleton_method(rb_cYARP, "named_captures", named_captures, 1); - rb_define_singleton_method(rb_cYARP, "unescape_none", unescape_none, 1); - rb_define_singleton_method(rb_cYARP, "unescape_minimal", unescape_minimal, 1); - rb_define_singleton_method(rb_cYARP, "unescape_all", unescape_all, 1); - rb_define_singleton_method(rb_cYARP, "memsize", memsize, 1); - rb_define_singleton_method(rb_cYARP, "profile_file", profile_file, 1); + VALUE rb_cYARPDebug = rb_define_module_under(rb_cYARP, "Debug"); + rb_define_singleton_method(rb_cYARPDebug, "named_captures", named_captures, 1); + rb_define_singleton_method(rb_cYARPDebug, "unescape_none", unescape_none, 1); + rb_define_singleton_method(rb_cYARPDebug, "unescape_minimal", unescape_minimal, 1); + rb_define_singleton_method(rb_cYARPDebug, "unescape_all", unescape_all, 1); + rb_define_singleton_method(rb_cYARPDebug, "memsize", memsize, 1); + rb_define_singleton_method(rb_cYARPDebug, "profile_file", profile_file, 1); // Next, initialize the pack API. Init_yarp_pack(); From 1002b777c4d8c7036759a2cd28f3fea5352f98d6 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 2 Aug 2023 21:22:20 +0200 Subject: [PATCH 110/158] [ruby/yarp] Automatically find the right line for yarp/serialize.rb newline test https://github.com/ruby/yarp/commit/5908130541 --- test/newline_test.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/newline_test.rb b/test/newline_test.rb index 5a81f52637ec81..1f6b550f30a2ff 100644 --- a/test/newline_test.rb +++ b/test/newline_test.rb @@ -35,7 +35,8 @@ def visit(node) if relative == "lib/yarp/serialize.rb" # while (b = io.getbyte) >= 128 has 2 newline flags - expected.delete_at actual.index(62) + line_number = source.lines.index { |line| line.include?('while (b = io.getbyte) >= 128') } + 1 + expected.delete_at(expected.index(line_number)) elsif relative == "lib/yarp/lex_compat.rb" # extra flag for: dedent_next =\n ((token.event: due to bytecode order actual.delete(520) From d2eb82d9692c0ad2da36e5b910dd34c77395733a Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 2 Aug 2023 21:37:34 +0200 Subject: [PATCH 111/158] [ruby/yarp] Fix test to use the new location of yarp.so https://github.com/ruby/yarp/commit/a22b204a11 --- test/yarp/library_symbols_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/yarp/library_symbols_test.rb b/test/yarp/library_symbols_test.rb index 276b42a0280b51..766adf16b77cdd 100644 --- a/test/yarp/library_symbols_test.rb +++ b/test/yarp/library_symbols_test.rb @@ -13,7 +13,7 @@ def setup @librubyparser_a = File.expand_path(File.join(__dir__, "..", "build", "librubyparser.a")) @librubyparser_so = File.expand_path(File.join(__dir__, "..", "build", "librubyparser.so")) - @yarp_so = File.expand_path(File.join(__dir__, "..", "lib", "yarp.so")) + @yarp_so = File.expand_path(File.join(__dir__, "..", "lib", "yarp", "yarp.so")) end # objdump runner and helpers From 3f64defe13b4a8712f95de009fc1f8b09e2bf779 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 3 Aug 2023 10:35:56 -0400 Subject: [PATCH 112/158] [ruby/yarp] Make sure lexing ? does not read off the end https://github.com/ruby/yarp/commit/d694e3ebf2 --- yarp/yarp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 2573663f26214d..dd27c172f42e29 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -5307,11 +5307,15 @@ lex_question_mark(yp_parser_t *parser) { return YP_TOKEN_CHARACTER_LITERAL; } else { size_t encoding_width = parser->encoding.char_width(parser->current.end); + // We only want to return a character literal if there's exactly one // alphanumeric character right after the `?` if ( !parser->encoding.alnum_char(parser->current.end) || - !parser->encoding.alnum_char(parser->current.end + encoding_width) + ( + (parser->current.end + encoding_width >= parser->end) || + !parser->encoding.alnum_char(parser->current.end + encoding_width) + ) ) { lex_state_set(parser, YP_LEX_STATE_END); parser->current.end += encoding_width; From 1ad0d198760d0f3295da86f66d099f28c9b50df7 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 5 Jul 2023 21:59:28 +0200 Subject: [PATCH 113/158] [ruby/yarp] Parse individual snippets of test/fixtures/*.txt * To ensure the parser does not try to read bytes further than the end of each snippet. https://github.com/ruby/yarp/commit/1c4438bdde --- test/yarp/fixtures/constants.txt | 3 + test/yarp/fixtures/strings.txt | 2 +- test/yarp/parse_test.rb | 25 +- test/yarp/snapshots/constants.txt | 524 +++++++++++++++--------------- test/yarp/snapshots/strings.txt | 198 +++++------ 5 files changed, 386 insertions(+), 366 deletions(-) diff --git a/test/yarp/fixtures/constants.txt b/test/yarp/fixtures/constants.txt index 8c7c6d227bcfbe..d3e7140630d83b 100644 --- a/test/yarp/fixtures/constants.txt +++ b/test/yarp/fixtures/constants.txt @@ -51,6 +51,8 @@ A::>> A::<< A::\ +# +C A::alias @@ -163,6 +165,7 @@ A::** A::~ A::_:: +C A::_.. diff --git a/test/yarp/fixtures/strings.txt b/test/yarp/fixtures/strings.txt index 9d6cc77fc76d97..947c535aed53f5 100644 --- a/test/yarp/fixtures/strings.txt +++ b/test/yarp/fixtures/strings.txt @@ -37,7 +37,7 @@ %[foo[]] "foo" + - +# "bar" %q{abc} diff --git a/test/yarp/parse_test.rb b/test/yarp/parse_test.rb index 3e1c3cb8f08229..91752cd483b475 100644 --- a/test/yarp/parse_test.rb +++ b/test/yarp/parse_test.rb @@ -45,11 +45,6 @@ def find_source_file_node(node) end end - def test_parse_dollar0 - parsed_result = YARP.parse("$0", "-e") - assert_equal 2, parsed_result.value.location.length - end - def test_parse_takes_file_path filepath = "filepath.rb" parsed_result = YARP.parse("def foo; __FILE__; end", filepath) @@ -124,6 +119,26 @@ def test_parse_takes_file_path end end + Dir["*.txt", base: base].each do |relative| + # We test every snippet (separated by \n\n) in isolation + # to ensure the parser does not try to read bytes further than the end of each snippet + define_method "test_individual_snippets_#{relative}" do + filepath = File.join(base, relative) + + # First, read the source from the filepath. Use binmode to avoid converting CRLF on Windows, + # and explicitly set the external encoding to UTF-8 to override the binmode default. + file_contents = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) + + file_contents.split(/(?<=\S)\n\n(?=\S)/).each do |snippet| + snippet = snippet.rstrip + result = YARP.parse(snippet, relative) + assert_empty result.errors + + assert_equal_nodes(result.value, YARP.load(snippet, YARP.dump(snippet, relative))) + end + end + end + private def ignore_warnings diff --git a/test/yarp/snapshots/constants.txt b/test/yarp/snapshots/constants.txt index 438f36599c7ed0..5469144be39f09 100644 --- a/test/yarp/snapshots/constants.txt +++ b/test/yarp/snapshots/constants.txt @@ -1,6 +1,6 @@ -ProgramNode(0...709)( +ProgramNode(0...715)( [], - StatementsNode(0...709)( + StatementsNode(0...715)( [ConstantPathNode(0...4)( ConstantReadNode(0...1)(), ConstantReadNode(3...4)(), @@ -235,14 +235,15 @@ ProgramNode(0...709)( 0, "<<" ), - CallNode(196...210)( - ConstantPathNode(196...203)( - ConstantReadNode(196...197)(), - ConstantReadNode(202...203)(), - (197...199) - ), - (203...205), - (205...210), + ConstantPathNode(196...204)( + ConstantReadNode(196...197)(), + ConstantReadNode(203...204)(), + (197...199) + ), + CallNode(206...214)( + ConstantReadNode(206...207)(), + (207...209), + (209...214), nil, nil, nil, @@ -250,10 +251,10 @@ ProgramNode(0...709)( 0, "alias" ), - CallNode(212...218)( - ConstantReadNode(212...213)(), - (213...215), - (215...218), + CallNode(216...222)( + ConstantReadNode(216...217)(), + (217...219), + (219...222), nil, nil, nil, @@ -261,10 +262,10 @@ ProgramNode(0...709)( 0, "and" ), - CallNode(220...228)( - ConstantReadNode(220...221)(), - (221...223), - (223...228), + CallNode(224...232)( + ConstantReadNode(224...225)(), + (225...227), + (227...232), nil, nil, nil, @@ -272,15 +273,15 @@ ProgramNode(0...709)( 0, "begin" ), - ConstantPathNode(230...238)( - ConstantReadNode(230...231)(), - ConstantReadNode(233...238)(), - (231...233) + ConstantPathNode(234...242)( + ConstantReadNode(234...235)(), + ConstantReadNode(237...242)(), + (235...237) ), - CallNode(240...248)( - ConstantReadNode(240...241)(), - (241...243), - (243...248), + CallNode(244...252)( + ConstantReadNode(244...245)(), + (245...247), + (247...252), nil, nil, nil, @@ -288,10 +289,10 @@ ProgramNode(0...709)( 0, "break" ), - CallNode(250...258)( - ConstantReadNode(250...251)(), - (251...253), - (253...258), + CallNode(254...262)( + ConstantReadNode(254...255)(), + (255...257), + (257...262), nil, nil, nil, @@ -299,10 +300,10 @@ ProgramNode(0...709)( 0, "class" ), - CallNode(260...266)( - ConstantReadNode(260...261)(), - (261...263), - (263...266), + CallNode(264...270)( + ConstantReadNode(264...265)(), + (265...267), + (267...270), nil, nil, nil, @@ -310,10 +311,10 @@ ProgramNode(0...709)( 0, "def" ), - CallNode(268...278)( - ConstantReadNode(268...269)(), - (269...271), - (271...278), + CallNode(272...282)( + ConstantReadNode(272...273)(), + (273...275), + (275...282), nil, nil, nil, @@ -321,10 +322,10 @@ ProgramNode(0...709)( 0, "defined" ), - CallNode(280...285)( - ConstantReadNode(280...281)(), - (281...283), - (283...285), + CallNode(284...289)( + ConstantReadNode(284...285)(), + (285...287), + (287...289), nil, nil, nil, @@ -332,10 +333,10 @@ ProgramNode(0...709)( 0, "do" ), - CallNode(287...294)( - ConstantReadNode(287...288)(), - (288...290), - (290...294), + CallNode(291...298)( + ConstantReadNode(291...292)(), + (292...294), + (294...298), nil, nil, nil, @@ -343,10 +344,10 @@ ProgramNode(0...709)( 0, "else" ), - CallNode(296...304)( - ConstantReadNode(296...297)(), - (297...299), - (299...304), + CallNode(300...308)( + ConstantReadNode(300...301)(), + (301...303), + (303...308), nil, nil, nil, @@ -354,10 +355,10 @@ ProgramNode(0...709)( 0, "elsif" ), - CallNode(306...312)( - ConstantReadNode(306...307)(), - (307...309), - (309...312), + CallNode(310...316)( + ConstantReadNode(310...311)(), + (311...313), + (313...316), nil, nil, nil, @@ -365,15 +366,15 @@ ProgramNode(0...709)( 0, "end" ), - ConstantPathNode(314...320)( - ConstantReadNode(314...315)(), - ConstantReadNode(317...320)(), - (315...317) + ConstantPathNode(318...324)( + ConstantReadNode(318...319)(), + ConstantReadNode(321...324)(), + (319...321) ), - CallNode(322...331)( - ConstantReadNode(322...323)(), - (323...325), - (325...331), + CallNode(326...335)( + ConstantReadNode(326...327)(), + (327...329), + (329...335), nil, nil, nil, @@ -381,10 +382,10 @@ ProgramNode(0...709)( 0, "ensure" ), - CallNode(333...341)( - ConstantReadNode(333...334)(), - (334...336), - (336...341), + CallNode(337...345)( + ConstantReadNode(337...338)(), + (338...340), + (340...345), nil, nil, nil, @@ -392,10 +393,10 @@ ProgramNode(0...709)( 0, "false" ), - CallNode(343...349)( - ConstantReadNode(343...344)(), - (344...346), - (346...349), + CallNode(347...353)( + ConstantReadNode(347...348)(), + (348...350), + (350...353), nil, nil, nil, @@ -403,10 +404,10 @@ ProgramNode(0...709)( 0, "for" ), - CallNode(351...356)( - ConstantReadNode(351...352)(), - (352...354), - (354...356), + CallNode(355...360)( + ConstantReadNode(355...356)(), + (356...358), + (358...360), nil, nil, nil, @@ -414,10 +415,10 @@ ProgramNode(0...709)( 0, "if" ), - CallNode(358...363)( - ConstantReadNode(358...359)(), - (359...361), - (361...363), + CallNode(362...367)( + ConstantReadNode(362...363)(), + (363...365), + (365...367), nil, nil, nil, @@ -425,10 +426,10 @@ ProgramNode(0...709)( 0, "in" ), - CallNode(365...372)( - ConstantReadNode(365...366)(), - (366...368), - (368...372), + CallNode(369...376)( + ConstantReadNode(369...370)(), + (370...372), + (372...376), nil, nil, nil, @@ -436,10 +437,10 @@ ProgramNode(0...709)( 0, "next" ), - CallNode(374...380)( - ConstantReadNode(374...375)(), - (375...377), - (377...380), + CallNode(378...384)( + ConstantReadNode(378...379)(), + (379...381), + (381...384), nil, nil, nil, @@ -447,10 +448,10 @@ ProgramNode(0...709)( 0, "nil" ), - CallNode(382...388)( - ConstantReadNode(382...383)(), - (383...385), - (385...388), + CallNode(386...392)( + ConstantReadNode(386...387)(), + (387...389), + (389...392), nil, nil, nil, @@ -458,10 +459,10 @@ ProgramNode(0...709)( 0, "not" ), - CallNode(390...395)( - ConstantReadNode(390...391)(), - (391...393), - (393...395), + CallNode(394...399)( + ConstantReadNode(394...395)(), + (395...397), + (397...399), nil, nil, nil, @@ -469,10 +470,10 @@ ProgramNode(0...709)( 0, "or" ), - CallNode(397...404)( - ConstantReadNode(397...398)(), - (398...400), - (400...404), + CallNode(401...408)( + ConstantReadNode(401...402)(), + (402...404), + (404...408), nil, nil, nil, @@ -480,10 +481,10 @@ ProgramNode(0...709)( 0, "redo" ), - CallNode(406...415)( - ConstantReadNode(406...407)(), - (407...409), - (409...415), + CallNode(410...419)( + ConstantReadNode(410...411)(), + (411...413), + (413...419), nil, nil, nil, @@ -491,10 +492,10 @@ ProgramNode(0...709)( 0, "rescue" ), - CallNode(417...425)( - ConstantReadNode(417...418)(), - (418...420), - (420...425), + CallNode(421...429)( + ConstantReadNode(421...422)(), + (422...424), + (424...429), nil, nil, nil, @@ -502,10 +503,10 @@ ProgramNode(0...709)( 0, "retry" ), - CallNode(427...436)( - ConstantReadNode(427...428)(), - (428...430), - (430...436), + CallNode(431...440)( + ConstantReadNode(431...432)(), + (432...434), + (434...440), nil, nil, nil, @@ -513,10 +514,10 @@ ProgramNode(0...709)( 0, "return" ), - CallNode(438...445)( - ConstantReadNode(438...439)(), - (439...441), - (441...445), + CallNode(442...449)( + ConstantReadNode(442...443)(), + (443...445), + (445...449), nil, nil, nil, @@ -524,10 +525,10 @@ ProgramNode(0...709)( 0, "self" ), - CallNode(447...455)( - ConstantReadNode(447...448)(), - (448...450), - (450...455), + CallNode(451...459)( + ConstantReadNode(451...452)(), + (452...454), + (454...459), nil, nil, nil, @@ -535,10 +536,10 @@ ProgramNode(0...709)( 0, "super" ), - CallNode(457...464)( - ConstantReadNode(457...458)(), - (458...460), - (460...464), + CallNode(461...468)( + ConstantReadNode(461...462)(), + (462...464), + (464...468), nil, nil, nil, @@ -546,10 +547,10 @@ ProgramNode(0...709)( 0, "then" ), - CallNode(466...473)( - ConstantReadNode(466...467)(), - (467...469), - (469...473), + CallNode(470...477)( + ConstantReadNode(470...471)(), + (471...473), + (473...477), nil, nil, nil, @@ -557,10 +558,10 @@ ProgramNode(0...709)( 0, "true" ), - CallNode(475...483)( - ConstantReadNode(475...476)(), - (476...478), - (478...483), + CallNode(479...487)( + ConstantReadNode(479...480)(), + (480...482), + (482...487), nil, nil, nil, @@ -568,10 +569,10 @@ ProgramNode(0...709)( 0, "undef" ), - CallNode(485...494)( - ConstantReadNode(485...486)(), - (486...488), - (488...494), + CallNode(489...498)( + ConstantReadNode(489...490)(), + (490...492), + (492...498), nil, nil, nil, @@ -579,10 +580,10 @@ ProgramNode(0...709)( 0, "unless" ), - CallNode(496...504)( - ConstantReadNode(496...497)(), - (497...499), - (499...504), + CallNode(500...508)( + ConstantReadNode(500...501)(), + (501...503), + (503...508), nil, nil, nil, @@ -590,10 +591,10 @@ ProgramNode(0...709)( 0, "until" ), - CallNode(506...513)( - ConstantReadNode(506...507)(), - (507...509), - (509...513), + CallNode(510...517)( + ConstantReadNode(510...511)(), + (511...513), + (513...517), nil, nil, nil, @@ -601,10 +602,10 @@ ProgramNode(0...709)( 0, "when" ), - CallNode(515...523)( - ConstantReadNode(515...516)(), - (516...518), - (518...523), + CallNode(519...527)( + ConstantReadNode(519...520)(), + (520...522), + (522...527), nil, nil, nil, @@ -612,10 +613,10 @@ ProgramNode(0...709)( 0, "while" ), - CallNode(525...533)( - ConstantReadNode(525...526)(), - (526...528), - (528...533), + CallNode(529...537)( + ConstantReadNode(529...530)(), + (530...532), + (532...537), nil, nil, nil, @@ -623,10 +624,10 @@ ProgramNode(0...709)( 0, "yield" ), - CallNode(535...550)( - ConstantReadNode(535...536)(), - (536...538), - (538...550), + CallNode(539...554)( + ConstantReadNode(539...540)(), + (540...542), + (542...554), nil, nil, nil, @@ -634,10 +635,10 @@ ProgramNode(0...709)( 0, "__ENCODING__" ), - CallNode(552...563)( - ConstantReadNode(552...553)(), - (553...555), - (555...563), + CallNode(556...567)( + ConstantReadNode(556...557)(), + (557...559), + (559...567), nil, nil, nil, @@ -645,10 +646,10 @@ ProgramNode(0...709)( 0, "__FILE__" ), - CallNode(565...576)( - ConstantReadNode(565...566)(), - (566...568), - (568...576), + CallNode(569...580)( + ConstantReadNode(569...570)(), + (570...572), + (572...580), nil, nil, nil, @@ -656,10 +657,10 @@ ProgramNode(0...709)( 0, "__LINE__" ), - CallNode(578...582)( - ConstantReadNode(578...579)(), - (579...581), - (581...582), + CallNode(582...586)( + ConstantReadNode(582...583)(), + (583...585), + (585...586), nil, nil, nil, @@ -667,10 +668,10 @@ ProgramNode(0...709)( 0, "<" ), - CallNode(584...590)( - ConstantReadNode(584...585)(), - (585...587), - (587...590), + CallNode(588...594)( + ConstantReadNode(588...589)(), + (589...591), + (591...594), nil, nil, nil, @@ -678,10 +679,10 @@ ProgramNode(0...709)( 0, "<=>" ), - CallNode(592...597)( - ConstantReadNode(592...593)(), - (593...595), - (595...597), + CallNode(596...601)( + ConstantReadNode(596...597)(), + (597...599), + (599...601), nil, nil, nil, @@ -689,10 +690,10 @@ ProgramNode(0...709)( 0, "<<" ), - CallNode(599...603)( - ConstantReadNode(599...600)(), - (600...602), - (602...603), + CallNode(603...607)( + ConstantReadNode(603...604)(), + (604...606), + (606...607), nil, nil, nil, @@ -700,10 +701,10 @@ ProgramNode(0...709)( 0, "-" ), - CallNode(605...609)( - ConstantReadNode(605...606)(), - (606...608), - (608...609), + CallNode(609...613)( + ConstantReadNode(609...610)(), + (610...612), + (612...613), nil, nil, nil, @@ -711,16 +712,16 @@ ProgramNode(0...709)( 0, "%" ), - CallNode(611...616)( - ConstantReadNode(611...612)(), - (612...614), - (615...616), + CallNode(615...620)( + ConstantReadNode(615...616)(), + (616...618), + (619...620), nil, - ArgumentsNode(615...616)( - [CallNode(615...616)( + ArgumentsNode(619...620)( + [CallNode(619...620)( nil, nil, - (615...616), + (619...620), nil, nil, nil, @@ -734,16 +735,16 @@ ProgramNode(0...709)( 0, "i" ), - CallNode(618...623)( - ConstantReadNode(618...619)(), - (619...621), - (622...623), + CallNode(622...627)( + ConstantReadNode(622...623)(), + (623...625), + (626...627), nil, - ArgumentsNode(622...623)( - [CallNode(622...623)( + ArgumentsNode(626...627)( + [CallNode(626...627)( nil, nil, - (622...623), + (626...627), nil, nil, nil, @@ -757,16 +758,16 @@ ProgramNode(0...709)( 0, "w" ), - CallNode(625...630)( - ConstantReadNode(625...626)(), - (626...628), - (629...630), + CallNode(629...634)( + ConstantReadNode(629...630)(), + (630...632), + (633...634), nil, - ArgumentsNode(629...630)( - [CallNode(629...630)( + ArgumentsNode(633...634)( + [CallNode(633...634)( nil, nil, - (629...630), + (633...634), nil, nil, nil, @@ -780,32 +781,32 @@ ProgramNode(0...709)( 0, "x" ), - CallNode(632...637)( - ConstantReadNode(632...633)(), - (633...635), - (636...637), + CallNode(636...641)( + ConstantReadNode(636...637)(), + (637...639), + (640...641), nil, - ArgumentsNode(636...637)([ConstantReadNode(636...637)()]), + ArgumentsNode(640...641)([ConstantReadNode(640...641)()]), nil, nil, 0, "I" ), - CallNode(639...644)( - ConstantReadNode(639...640)(), - (640...642), - (643...644), + CallNode(643...648)( + ConstantReadNode(643...644)(), + (644...646), + (647...648), nil, - ArgumentsNode(643...644)([ConstantReadNode(643...644)()]), + ArgumentsNode(647...648)([ConstantReadNode(647...648)()]), nil, nil, 0, "W" ), - CallNode(646...650)( - ConstantReadNode(646...647)(), - (647...649), - (649...650), + CallNode(650...654)( + ConstantReadNode(650...651)(), + (651...653), + (653...654), nil, nil, nil, @@ -813,10 +814,10 @@ ProgramNode(0...709)( 0, "|" ), - CallNode(652...656)( - ConstantReadNode(652...653)(), - (653...655), - (655...656), + CallNode(656...660)( + ConstantReadNode(656...657)(), + (657...659), + (659...660), nil, nil, nil, @@ -824,10 +825,10 @@ ProgramNode(0...709)( 0, "+" ), - CallNode(658...662)( - ConstantReadNode(658...659)(), - (659...661), - (661...662), + CallNode(662...666)( + ConstantReadNode(662...663)(), + (663...665), + (665...666), nil, nil, nil, @@ -835,10 +836,10 @@ ProgramNode(0...709)( 0, "/" ), - CallNode(664...668)( - ConstantReadNode(664...665)(), - (665...667), - (667...668), + CallNode(668...672)( + ConstantReadNode(668...669)(), + (669...671), + (671...672), nil, nil, nil, @@ -846,10 +847,10 @@ ProgramNode(0...709)( 0, "*" ), - CallNode(670...675)( - ConstantReadNode(670...671)(), - (671...673), - (673...675), + CallNode(674...679)( + ConstantReadNode(674...675)(), + (675...677), + (677...679), nil, nil, nil, @@ -857,10 +858,10 @@ ProgramNode(0...709)( 0, "**" ), - CallNode(677...681)( - ConstantReadNode(677...678)(), - (678...680), - (680...681), + CallNode(681...685)( + ConstantReadNode(681...682)(), + (682...684), + (684...685), nil, nil, nil, @@ -868,25 +869,26 @@ ProgramNode(0...709)( 0, "~" ), - RangeNode(683...709)( - CallNode(683...695)( - ConstantPathNode(683...692)( - CallNode(683...687)( - ConstantReadNode(683...684)(), - (684...686), - (686...687), - nil, - nil, - nil, - nil, - 0, - "_" - ), - ConstantReadNode(691...692)(), - (687...689) - ), - (692...694), - (694...695), + ConstantPathNode(687...695)( + CallNode(687...691)( + ConstantReadNode(687...688)(), + (688...690), + (690...691), + nil, + nil, + nil, + nil, + 0, + "_" + ), + ConstantReadNode(694...695)(), + (691...693) + ), + RangeNode(697...715)( + CallNode(697...701)( + ConstantReadNode(697...698)(), + (698...700), + (700...701), nil, nil, nil, @@ -894,10 +896,10 @@ ProgramNode(0...709)( 0, "_" ), - CallNode(699...709)( - ConstantReadNode(699...700)(), - (700...702), - (702...709), + CallNode(705...715)( + ConstantReadNode(705...706)(), + (706...708), + (708...715), nil, nil, nil, @@ -905,7 +907,7 @@ ProgramNode(0...709)( 0, "__END__" ), - (695...697), + (701...703), 0 )] ) diff --git a/test/yarp/snapshots/strings.txt b/test/yarp/snapshots/strings.txt index 9b2821a0fd3d48..5f3e5d29331c78 100644 --- a/test/yarp/snapshots/strings.txt +++ b/test/yarp/snapshots/strings.txt @@ -1,6 +1,6 @@ -ProgramNode(0...497)( +ProgramNode(0...498)( [], - StatementsNode(0...497)( + StatementsNode(0...498)( [StringNode(0...6)((0...2), (2...5), (5...6), "abc"), StringNode(8...14)((8...10), (10...13), (13...14), "abc"), StringNode(16...22)((16...18), (18...21), (21...22), "abc"), @@ -49,35 +49,35 @@ ProgramNode(0...497)( (156...157) ), StringNode(159...167)((159...161), (161...166), (166...167), "foo[]"), - CallNode(169...183)( + CallNode(169...184)( StringNode(169...174)((169...170), (170...173), (173...174), "foo"), nil, (175...176), nil, - ArgumentsNode(178...183)( - [StringNode(178...183)((178...179), (179...182), (182...183), "bar")] + ArgumentsNode(179...184)( + [StringNode(179...184)((179...180), (180...183), (183...184), "bar")] ), nil, nil, 0, "+" ), - StringNode(185...192)((185...188), (188...191), (191...192), "abc"), - SymbolNode(194...201)((194...197), (197...200), (200...201), "abc"), - StringNode(203...209)((203...205), (205...208), (208...209), "abc"), - StringNode(211...213)((211...212), (212...212), (212...213), ""), - StringNode(215...220)((215...216), (216...219), (219...220), "abc"), - StringNode(222...229)((222...223), (223...228), (228...229), "\#@---"), - InterpolatedStringNode(231...247)( - (231...232), - [StringNode(232...236)(nil, (232...236), nil, "aaa "), - EmbeddedStatementsNode(236...242)( - (236...238), - StatementsNode(238...241)( - [CallNode(238...241)( + StringNode(186...193)((186...189), (189...192), (192...193), "abc"), + SymbolNode(195...202)((195...198), (198...201), (201...202), "abc"), + StringNode(204...210)((204...206), (206...209), (209...210), "abc"), + StringNode(212...214)((212...213), (213...213), (213...214), ""), + StringNode(216...221)((216...217), (217...220), (220...221), "abc"), + StringNode(223...230)((223...224), (224...229), (229...230), "\#@---"), + InterpolatedStringNode(232...248)( + (232...233), + [StringNode(233...237)(nil, (233...237), nil, "aaa "), + EmbeddedStatementsNode(237...243)( + (237...239), + StatementsNode(239...242)( + [CallNode(239...242)( nil, nil, - (238...241), + (239...242), nil, nil, nil, @@ -86,50 +86,50 @@ ProgramNode(0...497)( "bbb" )] ), - (241...242) + (242...243) ), - StringNode(242...246)(nil, (242...246), nil, " ccc")], - (246...247) + StringNode(243...247)(nil, (243...247), nil, " ccc")], + (247...248) ), - StringNode(249...254)((249...250), (250...253), (253...254), "abc"), - ArrayNode(256...265)( - [StringNode(259...260)(nil, (259...260), nil, "a"), - StringNode(261...262)(nil, (261...262), nil, "b"), - StringNode(263...264)(nil, (263...264), nil, "c")], - (256...259), - (264...265) + StringNode(250...255)((250...251), (251...254), (254...255), "abc"), + ArrayNode(257...266)( + [StringNode(260...261)(nil, (260...261), nil, "a"), + StringNode(262...263)(nil, (262...263), nil, "b"), + StringNode(264...265)(nil, (264...265), nil, "c")], + (257...260), + (265...266) ), - ArrayNode(267...284)( - [StringNode(270...273)(nil, (270...273), nil, "a[]"), - StringNode(274...279)(nil, (274...279), nil, "b[[]]"), - StringNode(280...283)(nil, (280...283), nil, "c[]")], - (267...270), - (283...284) + ArrayNode(268...285)( + [StringNode(271...274)(nil, (271...274), nil, "a[]"), + StringNode(275...280)(nil, (275...280), nil, "b[[]]"), + StringNode(281...284)(nil, (281...284), nil, "c[]")], + (268...271), + (284...285) ), - ArrayNode(286...304)( - [StringNode(289...297)(nil, (289...297), nil, "foo\\ bar"), - StringNode(298...303)(nil, (298...303), nil, "\\\#{1}")], - (286...289), - (303...304) + ArrayNode(287...305)( + [StringNode(290...298)(nil, (290...298), nil, "foo\\ bar"), + StringNode(299...304)(nil, (299...304), nil, "\\\#{1}")], + (287...290), + (304...305) ), - ArrayNode(306...322)( - [StringNode(309...317)(nil, (309...317), nil, "foo\\ bar"), - StringNode(318...321)(nil, (318...321), nil, "baz")], - (306...309), - (321...322) + ArrayNode(307...323)( + [StringNode(310...318)(nil, (310...318), nil, "foo\\ bar"), + StringNode(319...322)(nil, (319...322), nil, "baz")], + (307...310), + (322...323) ), - ArrayNode(324...338)( - [StringNode(327...328)(nil, (327...328), nil, "a"), - InterpolatedStringNode(0...335)( + ArrayNode(325...339)( + [StringNode(328...329)(nil, (328...329), nil, "a"), + InterpolatedStringNode(0...336)( nil, - [StringNode(329...330)(nil, (329...330), nil, "b"), - EmbeddedStatementsNode(330...334)( - (330...332), - StatementsNode(332...333)( - [CallNode(332...333)( + [StringNode(330...331)(nil, (330...331), nil, "b"), + EmbeddedStatementsNode(331...335)( + (331...333), + StatementsNode(333...334)( + [CallNode(333...334)( nil, nil, - (332...333), + (333...334), nil, nil, nil, @@ -138,64 +138,64 @@ ProgramNode(0...497)( "c" )] ), - (333...334) + (334...335) ), - StringNode(334...335)(nil, (334...335), nil, "d")], + StringNode(335...336)(nil, (335...336), nil, "d")], nil ), - StringNode(336...337)(nil, (336...337), nil, "e")], - (324...327), - (337...338) + StringNode(337...338)(nil, (337...338), nil, "e")], + (325...328), + (338...339) ), - ArrayNode(340...349)( - [StringNode(343...344)(nil, (343...344), nil, "a"), - StringNode(345...346)(nil, (345...346), nil, "b"), - StringNode(347...348)(nil, (347...348), nil, "c")], - (340...343), - (348...349) + ArrayNode(341...350)( + [StringNode(344...345)(nil, (344...345), nil, "a"), + StringNode(346...347)(nil, (346...347), nil, "b"), + StringNode(348...349)(nil, (348...349), nil, "c")], + (341...344), + (349...350) ), - ArrayNode(351...368)( - [StringNode(357...358)(nil, (357...358), nil, "a"), - StringNode(361...362)(nil, (361...362), nil, "b"), - StringNode(365...366)(nil, (365...366), nil, "c")], - (351...354), - (367...368) + ArrayNode(352...369)( + [StringNode(358...359)(nil, (358...359), nil, "a"), + StringNode(362...363)(nil, (362...363), nil, "b"), + StringNode(366...367)(nil, (366...367), nil, "c")], + (352...355), + (368...369) ), - StringNode(370...385)( - (370...371), - (371...384), - (384...385), + StringNode(371...386)( + (371...372), + (372...385), + (385...386), "' foo ' bar" ), - StringNode(387...402)( - (387...388), - (388...401), - (401...402), + StringNode(388...403)( + (388...389), + (389...402), + (402...403), "\\ foo \\ bar" ), - InterpolatedStringNode(404...411)( - (404...405), - [EmbeddedVariableNode(405...410)( - (405...406), - GlobalVariableReadNode(406...410)() + InterpolatedStringNode(405...412)( + (405...406), + [EmbeddedVariableNode(406...411)( + (406...407), + GlobalVariableReadNode(407...411)() )], - (410...411) + (411...412) ), - InterpolatedStringNode(413...420)( - (413...414), - [EmbeddedVariableNode(414...419)( - (414...415), - InstanceVariableReadNode(415...419)() + InterpolatedStringNode(414...421)( + (414...415), + [EmbeddedVariableNode(415...420)( + (415...416), + InstanceVariableReadNode(416...420)() )], - (419...420) + (420...421) ), - StringNode(422...437)((422...423), (423...436), (436...437), "\a # a"), - StringNode(439...452)((439...440), (440...451), (451...452), "\a # a"), - StringNode(454...460)((454...456), (456...459), (459...460), "abc"), - StringNode(462...468)((462...464), (464...467), (467...468), "abc"), - StringNode(470...476)((470...472), (472...475), (475...476), "abc"), - StringNode(478...484)((478...480), (480...483), (483...484), "abc"), - StringNode(486...488)((486...487), (487...488), nil, "a"), - StringNode(490...497)((490...493), (493...496), (496...497), "abc")] + StringNode(423...438)((423...424), (424...437), (437...438), "\a # a"), + StringNode(440...453)((440...441), (441...452), (452...453), "\a # a"), + StringNode(455...461)((455...457), (457...460), (460...461), "abc"), + StringNode(463...469)((463...465), (465...468), (468...469), "abc"), + StringNode(471...477)((471...473), (473...476), (476...477), "abc"), + StringNode(479...485)((479...481), (481...484), (484...485), "abc"), + StringNode(487...489)((487...488), (488...489), nil, "a"), + StringNode(491...498)((491...494), (494...497), (497...498), "abc")] ) ) From 0004565a919fde84def202432ef04cee0f7b689e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 3 Aug 2023 13:25:38 -0400 Subject: [PATCH 114/158] [ruby/yarp] Use yp_memchr in regexp parsing https://github.com/ruby/yarp/commit/08081dd24f --- yarp/extension.c | 2 +- yarp/regexp.c | 15 ++++++++++----- yarp/regexp.h | 4 +++- yarp/yarp.c | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/yarp/extension.c b/yarp/extension.c index d4ce3625d82eb8..4f2065a81bac82 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -379,7 +379,7 @@ named_captures(VALUE self, VALUE source) { yp_string_list_t string_list; yp_string_list_init(&string_list); - if (!yp_regexp_named_capture_group_names(RSTRING_PTR(source), RSTRING_LEN(source), &string_list)) { + if (!yp_regexp_named_capture_group_names(RSTRING_PTR(source), RSTRING_LEN(source), &string_list, false, &yp_encoding_utf_8)) { yp_string_list_free(&string_list); return Qnil; } diff --git a/yarp/regexp.c b/yarp/regexp.c index 4855859442fba6..40d85c5227cdcc 100644 --- a/yarp/regexp.c +++ b/yarp/regexp.c @@ -6,16 +6,20 @@ typedef struct { const char *cursor; const char *end; yp_string_list_t *named_captures; + bool encoding_changed; + yp_encoding_t *encoding; } yp_regexp_parser_t; // This initializes a new parser with the given source. static void -yp_regexp_parser_init(yp_regexp_parser_t *parser, const char *start, const char *end, yp_string_list_t *named_captures) { +yp_regexp_parser_init(yp_regexp_parser_t *parser, const char *start, const char *end, yp_string_list_t *named_captures, bool encoding_changed, yp_encoding_t *encoding) { *parser = (yp_regexp_parser_t) { .start = start, .cursor = start, .end = end, - .named_captures = named_captures + .named_captures = named_captures, + .encoding_changed = encoding_changed, + .encoding = encoding }; } @@ -60,7 +64,8 @@ yp_regexp_char_find(yp_regexp_parser_t *parser, char value) { if (yp_regexp_char_is_eof(parser)) { return false; } - const char *end = (const char *) memchr(parser->cursor, value, (size_t) (parser->end - parser->cursor)); + + const char *end = (const char *) yp_memchr(parser->cursor, value, (size_t) (parser->end - parser->cursor), parser->encoding_changed, parser->encoding); if (end == NULL) { return false; } @@ -542,8 +547,8 @@ yp_regexp_parse_pattern(yp_regexp_parser_t *parser) { // Parse a regular expression and extract the names of all of the named capture // groups. YP_EXPORTED_FUNCTION bool -yp_regexp_named_capture_group_names(const char *source, size_t size, yp_string_list_t *named_captures) { +yp_regexp_named_capture_group_names(const char *source, size_t size, yp_string_list_t *named_captures, bool encoding_changed, yp_encoding_t *encoding) { yp_regexp_parser_t parser; - yp_regexp_parser_init(&parser, source, source + size, named_captures); + yp_regexp_parser_init(&parser, source, source + size, named_captures, encoding_changed, encoding); return yp_regexp_parse_pattern(&parser); } diff --git a/yarp/regexp.h b/yarp/regexp.h index cf624db6b84376..5a2f13047e552f 100644 --- a/yarp/regexp.h +++ b/yarp/regexp.h @@ -3,6 +3,8 @@ #include "yarp/defines.h" #include "yarp/parser.h" +#include "yarp/enc/yp_encoding.h" +#include "yarp/util/yp_memchr.h" #include "yarp/util/yp_string_list.h" #include "yarp/util/yp_string.h" @@ -12,6 +14,6 @@ // Parse a regular expression and extract the names of all of the named capture // groups. -YP_EXPORTED_FUNCTION bool yp_regexp_named_capture_group_names(const char *source, size_t size, yp_string_list_t *named_captures); +YP_EXPORTED_FUNCTION bool yp_regexp_named_capture_group_names(const char *source, size_t size, yp_string_list_t *named_captures, bool encoding_changed, yp_encoding_t *encoding); #endif diff --git a/yarp/yarp.c b/yarp/yarp.c index dd27c172f42e29..a8ff6c3859b587 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12535,7 +12535,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t yp_location_t *content_loc = &((yp_regular_expression_node_t *) node)->content_loc; - if (yp_regexp_named_capture_group_names(content_loc->start, (size_t) (content_loc->end - content_loc->start), &named_captures)) { + if (yp_regexp_named_capture_group_names(content_loc->start, (size_t) (content_loc->end - content_loc->start), &named_captures, parser->encoding_changed, &parser->encoding)) { for (size_t index = 0; index < named_captures.length; index++) { yp_string_t *name = &named_captures.strings[index]; assert(name->type == YP_STRING_SHARED); From 0b6a26abff1a15103f4a3080619ea28b40774324 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 3 Aug 2023 13:38:54 -0400 Subject: [PATCH 115/158] [ruby/yarp] Provide slow path for finding ) in regexp when encoding changes https://github.com/ruby/yarp/commit/c1064a65e3 --- yarp/regexp.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/yarp/regexp.c b/yarp/regexp.c index 40d85c5227cdcc..ce148c82f2f3c0 100644 --- a/yarp/regexp.c +++ b/yarp/regexp.c @@ -379,12 +379,35 @@ yp_regexp_parse_group(yp_regexp_parser_t *parser) { switch (*parser->cursor) { case '#': { // inline comments - bool found = yp_regexp_char_find(parser, ')'); - // the close paren we found is escaped, we need to find another - while (found && (parser->start <= parser->cursor - 2) && (*(parser->cursor - 2) == '\\')) { - found = yp_regexp_char_find(parser, ')'); + if (parser->encoding_changed && parser->encoding->multibyte) { + // Here we're going to take a slow path and iterate through + // each multibyte character to find the close paren. We do + // this because \ can be a trailing byte in some encodings. + while (parser->cursor < parser->end) { + if (*parser->cursor == ')') { + parser->cursor++; + return true; + } + + size_t width = parser->encoding->char_width(parser->cursor, (ptrdiff_t) (parser->end - parser->cursor)); + if (width == 0) return false; + + parser->cursor += width; + } + + return false; + } else { + // Here we can take the fast path and use memchr to find the + // next ) because we are safe checking backward for \ since + // it cannot be a trailing character. + bool found = yp_regexp_char_find(parser, ')'); + + while (found && (parser->start <= parser->cursor - 2) && (*(parser->cursor - 2) == '\\')) { + found = yp_regexp_char_find(parser, ')'); + } + + return found; } - return found; } case ':': // non-capturing group case '=': // positive lookahead From 1e0749e0328ebb7a670450d0375626b7adc789fb Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Thu, 3 Aug 2023 14:15:26 -0400 Subject: [PATCH 116/158] [ruby/yarp] Addressed review comments. Missing any tests and in fact this is untested so still a WIP. https://github.com/ruby/yarp/commit/5411abd651 --- yarp/extension.c | 10 ++++---- yarp/yarp.c | 60 +++++++++++++++++++++++++++++------------------- yarp/yarp.h | 2 +- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/yarp/extension.c b/yarp/extension.c index 4f2065a81bac82..e6ef3f7648b649 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -62,7 +62,7 @@ dump_input(yp_string_t *input, const char *filepath) { yp_parser_t parser; yp_parser_init(&parser, yp_string_source(input), yp_string_length(input), filepath); - yp_node_t *node = yp_parse(&parser, false); + yp_node_t *node = yp_parse(&parser); yp_serialize(&parser, node, &buffer); VALUE result = rb_str_new(buffer.value, buffer.length); @@ -246,7 +246,7 @@ lex_input(yp_string_t *input, const char *filepath) { }; parser.lex_callback = &lex_callback; - yp_node_t *node = yp_parse(&parser, false); + yp_node_t *node = yp_parse(&parser); // Here we need to update the source range to have the correct newline // offsets. We do it here because we've already created the object and given @@ -307,7 +307,7 @@ parse_input(yp_string_t *input, const char *filepath) { yp_parser_t parser; yp_parser_init(&parser, yp_string_source(input), yp_string_length(input), filepath); - yp_node_t *node = yp_parse(&parser, false); + yp_node_t *node = yp_parse(&parser); rb_encoding *encoding = rb_enc_find(parser.encoding.name); VALUE source = yp_source_new(&parser); @@ -437,7 +437,7 @@ memsize(VALUE self, VALUE string) { size_t length = RSTRING_LEN(string); yp_parser_init(&parser, RSTRING_PTR(string), length, NULL); - yp_node_t *node = yp_parse(&parser, false); + yp_node_t *node = yp_parse(&parser); yp_memsize_t memsize; yp_node_memsize(node, &memsize); @@ -463,7 +463,7 @@ profile_file(VALUE self, VALUE filepath) { yp_parser_t parser; yp_parser_init(&parser, yp_string_source(&input), yp_string_length(&input), checked); - yp_node_t *node = yp_parse(&parser, false); + yp_node_t *node = yp_parse(&parser); yp_node_destroy(&parser, node); yp_parser_free(&parser); diff --git a/yarp/yarp.c b/yarp/yarp.c index a8ff6c3859b587..92f1312e2bb188 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12870,8 +12870,8 @@ parse_expression(yp_parser_t *parser, yp_binding_power_t binding_power, const ch } static yp_node_t * -parse_program(yp_parser_t *parser, bool eval) { - yp_parser_scope_push(parser, !eval); +parse_program(yp_parser_t *parser) { + yp_parser_scope_push(parser, !parser->current_scope); parser_lex(parser); yp_statements_node_t *statements = parse_statements(parser, YP_CONTEXT_MAIN); @@ -12891,30 +12891,45 @@ parse_program(yp_parser_t *parser, bool eval) { return (yp_node_t *) yp_program_node_create(parser, &locals, statements); } -// Assume always a valid string since it is from trusted source (Ruby impl internals). -// Format: [num_scopes, (num_vars1, (var_char1*, 0)*)*] +// Process any additional metadata being passed into a parse. Since the source +// of these calls will be from Ruby implementation internals we assume it is from +// a trusted source. +// +// Currently, this is only passing in variable scoping surrounding an eval, but +// eventually it will be extended to hold any additional metadata. This data +// is serialized to reduce the calling complexity for a foreign function call +// vs a foreign runtime making a bindable in-memory version of a C structure. +// +// *Format* +// +// No metadata should just be NULL. For variable scopes it should be: +// +// ```text +// [number_of_variable_scopes: uint32_t, +// [number_of_variables: uint32_t, +// [data_length: uint32_t, data: char*]* +// ]* +// ] +// ``` static void -yp_populate_eval_scopes(yp_parser_t *parser, const char *data) { - const char *p = data; - size_t number_of_scopes = (size_t) *p; +yp_process_metadata(yp_parser_t *parser, const char *metadata) { + const char *p = metadata; + uint32_t number_of_scopes = (uint32_t) *p; + p += 4; - p++; for (size_t scope_index = 0; scope_index < number_of_scopes; scope_index++) { - size_t number_of_variables = (size_t) *p++; + uint32_t number_of_variables = (uint32_t) *p; + p += 4; yp_parser_scope_push(parser, scope_index == 0); for (size_t variable_index = 0; variable_index < number_of_variables; variable_index++) { - char *eos = strchr(p, 0); + int32_t length = (uint32_t) *p; + p += 4; - yp_token_t lvar = (yp_token_t) { - .type = YP_TOKEN_IDENTIFIER, - .start = p, - .end = eos - }; - yp_parser_local_add_token(parser, &lvar); + yp_parser_local_add_location(parser, p, p + length); - p = ++eos; + p += length; } } } @@ -13055,8 +13070,8 @@ yp_parser_free(yp_parser_t *parser) { // Parse the Ruby source associated with the given parser and return the tree. YP_EXPORTED_FUNCTION yp_node_t * -yp_parse(yp_parser_t *parser, bool eval) { - return parse_program(parser, eval); +yp_parse(yp_parser_t *parser) { + return parse_program(parser); } YP_EXPORTED_FUNCTION void @@ -13073,13 +13088,12 @@ yp_serialize(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { // Parse and serialize the AST represented by the given source to the given // buffer. YP_EXPORTED_FUNCTION void -yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *parent_scopes) { - bool eval = parent_scopes != NULL; +yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *metadata) { yp_parser_t parser; yp_parser_init(&parser, source, size, NULL); - if (eval) yp_populate_eval_scopes(&parser, parent_scopes); + if (metadata) yp_process_metadata(&parser, metadata); - yp_node_t *node = yp_parse(&parser, eval); + yp_node_t *node = yp_parse(&parser); yp_serialize(&parser, node, buffer); yp_node_destroy(&parser, node); diff --git a/yarp/yarp.h b/yarp/yarp.h index 492038a6e287dd..410f739fb25ae4 100644 --- a/yarp/yarp.h +++ b/yarp/yarp.h @@ -51,7 +51,7 @@ YP_EXPORTED_FUNCTION void yp_parser_register_encoding_decode_callback(yp_parser_ YP_EXPORTED_FUNCTION void yp_parser_free(yp_parser_t *parser); // Parse the Ruby source associated with the given parser and return the tree. -YP_EXPORTED_FUNCTION yp_node_t * yp_parse(yp_parser_t *parser, bool eval); +YP_EXPORTED_FUNCTION yp_node_t * yp_parse(yp_parser_t *parser); // Pretty-prints the AST represented by the given node to the given buffer. YP_EXPORTED_FUNCTION void yp_prettyprint(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer); From 72571453204a0e91e474233b619183be8834edba Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Thu, 3 Aug 2023 14:19:49 -0400 Subject: [PATCH 117/158] [ruby/yarp] Clang beats gcc in pedantry Accidentally declared int32_t and not uint32_t and it was caught on macos. https://github.com/ruby/yarp/commit/6581520793 --- yarp/yarp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 92f1312e2bb188..d193139e56dc95 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12924,7 +12924,7 @@ yp_process_metadata(yp_parser_t *parser, const char *metadata) { yp_parser_scope_push(parser, scope_index == 0); for (size_t variable_index = 0; variable_index < number_of_variables; variable_index++) { - int32_t length = (uint32_t) *p; + uint32_t length = (uint32_t) *p; p += 4; yp_parser_local_add_location(parser, p, p + length); From 5e9397279bbadb7d5cb08298e23e9fa76198b90e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 3 Aug 2023 15:49:29 -0400 Subject: [PATCH 118/158] [ruby/yarp] Handle escaping in regexp slow path https://github.com/ruby/yarp/commit/8dd0a1b281 --- yarp/regexp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yarp/regexp.c b/yarp/regexp.c index ce148c82f2f3c0..4d6b67ebe633a4 100644 --- a/yarp/regexp.c +++ b/yarp/regexp.c @@ -380,11 +380,13 @@ yp_regexp_parse_group(yp_regexp_parser_t *parser) { switch (*parser->cursor) { case '#': { // inline comments if (parser->encoding_changed && parser->encoding->multibyte) { + bool escaped = false; + // Here we're going to take a slow path and iterate through // each multibyte character to find the close paren. We do // this because \ can be a trailing byte in some encodings. while (parser->cursor < parser->end) { - if (*parser->cursor == ')') { + if (!escaped && *parser->cursor == ')') { parser->cursor++; return true; } @@ -392,6 +394,7 @@ yp_regexp_parse_group(yp_regexp_parser_t *parser) { size_t width = parser->encoding->char_width(parser->cursor, (ptrdiff_t) (parser->end - parser->cursor)); if (width == 0) return false; + escaped = (width == 1) && (*parser->cursor == '\\'); parser->cursor += width; } From 2ef54d38556c1c6bc95704fcb0dfa6a99041404d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 3 Aug 2023 16:27:21 -0400 Subject: [PATCH 119/158] [ruby/yarp] Rework the list lexer to check terminators properly https://github.com/ruby/yarp/commit/60315d0f13 --- yarp/yarp.c | 145 ++++++++++++++++++++++++---------------------------- 1 file changed, 67 insertions(+), 78 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index d193139e56dc95..e45c43a11eb1b1 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -6623,99 +6623,88 @@ parser_lex(yp_parser_t *parser) { // Here we'll get a list of the places where strpbrk should break, // and then find the first one. - const char *breakpoints = parser->lex_modes.current->as.list.breakpoints; + yp_lex_mode_t *lex_mode = parser->lex_modes.current; + const char *breakpoints = lex_mode->as.list.breakpoints; const char *breakpoint = yp_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); while (breakpoint != NULL) { - switch (*breakpoint) { - case '\0': - // If we hit a null byte, skip directly past it. - breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - break; - case '\\': { - // If we hit escapes, then we need to treat the next token - // literally. In this case we'll skip past the next character and - // find the next breakpoint. - - yp_unescape_type_t unescape_type; - if (parser->lex_modes.current->as.list.interpolation) { - unescape_type = YP_UNESCAPE_ALL; - } else { - unescape_type = YP_UNESCAPE_MINIMAL; - } - size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, unescape_type, false, &parser->error_list); + // If we hit a null byte, skip directly past it. + if (*breakpoint == '\0') { + breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); + continue; + } - // If the result is an escaped newline, then we need to - // track that newline. - if (breakpoint[difference - 1] == '\n') { - yp_newline_list_append(&parser->newline_list, breakpoint + difference - 1); - } + // If we hit whitespace, then we must have received content by + // now, so we can return an element of the list. + if (yp_char_is_whitespace(*breakpoint)) { + parser->current.end = breakpoint; + LEX(YP_TOKEN_STRING_CONTENT); + } - breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference)); - break; + //If we hit the terminator, we need to check which token to + // return. + if (*breakpoint == lex_mode->as.list.terminator) { + // If this terminator doesn't actually close the list, then + // we need to continue on past it. + if (lex_mode->as.list.nesting > 0) { + breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); + lex_mode->as.list.nesting--; + continue; } - case ' ': - case '\t': - case '\f': - case '\r': - case '\v': - case '\n': - // If we've hit whitespace, then we must have received content by - // now, so we can return an element of the list. + + // If we've hit the terminator and we've already skipped + // past content, then we can return a list node. + if (breakpoint > parser->current.start) { parser->current.end = breakpoint; LEX(YP_TOKEN_STRING_CONTENT); - case '#': { - // if # is the terminator, we need to fall into the default case - if (parser->lex_modes.current->as.list.terminator != '#') { - yp_token_type_t type = lex_interpolation(parser, breakpoint); - if (type != YP_TOKEN_NOT_PROVIDED) { - LEX(type); - } - - // If we haven't returned at this point then we had something - // that looked like an interpolated class or instance variable - // like "#@" but wasn't actually. In this case we'll just skip - // to the next breakpoint. - breakpoint = yp_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); - break; - } } - /* fallthrough */ - default: - if (*breakpoint == parser->lex_modes.current->as.list.incrementor) { - // If we've hit the incrementor, then we need to skip past it and - // find the next breakpoint. - breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - parser->lex_modes.current->as.list.nesting++; - break; - } - // In this case we've hit the terminator. - assert(*breakpoint == parser->lex_modes.current->as.list.terminator); + // Otherwise, switch back to the default state and return + // the end of the list. + parser->current.end = breakpoint + 1; + lex_mode_pop(parser); + lex_state_set(parser, YP_LEX_STATE_END); + LEX(YP_TOKEN_STRING_END); + } - // If this terminator doesn't actually close the list, then we need - // to continue on past it. - if (parser->lex_modes.current->as.list.nesting > 0) { - breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - parser->lex_modes.current->as.list.nesting--; - break; - } + // If we hit escapes, then we need to treat the next token + // literally. In this case we'll skip past the next character + // and find the next breakpoint. + if (*breakpoint == '\\') { + yp_unescape_type_t unescape_type = lex_mode->as.list.interpolation ? YP_UNESCAPE_ALL : YP_UNESCAPE_MINIMAL; + size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, unescape_type, false, &parser->error_list); - // If we've hit the terminator and we've already skipped past - // content, then we can return a list node. - if (breakpoint > parser->current.start) { - parser->current.end = breakpoint; - LEX(YP_TOKEN_STRING_CONTENT); - } + // If the result is an escaped newline, then we need to + // track that newline. + if (breakpoint[difference - 1] == '\n') { + yp_newline_list_append(&parser->newline_list, breakpoint + difference - 1); + } - // Otherwise, switch back to the default state and return the end of - // the list. - parser->current.end = breakpoint + 1; - lex_mode_pop(parser); + breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference)); + continue; + } - lex_state_set(parser, YP_LEX_STATE_END); - LEX(YP_TOKEN_STRING_END); + // If we hit a #, then we will attempt to lex interpolation. + if (*breakpoint == '#') { + yp_token_type_t type = lex_interpolation(parser, breakpoint); + if (type != YP_TOKEN_NOT_PROVIDED) { + LEX(type); + } + + // If we haven't returned at this point then we had something + // that looked like an interpolated class or instance variable + // like "#@" but wasn't actually. In this case we'll just skip + // to the next breakpoint. + breakpoint = yp_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); + continue; } + + // If we've hit the incrementor, then we need to skip past it + // and find the next breakpoint. + assert(*breakpoint == lex_mode->as.list.incrementor); + breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); + lex_mode->as.list.nesting++; + continue; } // If we were unable to find a breakpoint, then this token hits the end of From a793260c159e991998efb6975b0fdff92d22c806 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 3 Aug 2023 16:43:36 -0400 Subject: [PATCH 120/158] [ruby/yarp] Also rework regexp lexer to check terminators properly https://github.com/ruby/yarp/commit/4b157a8352 --- yarp/yarp.c | 149 +++++++++++++++++++++++++--------------------------- 1 file changed, 71 insertions(+), 78 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index e45c43a11eb1b1..bb4db37d7f135c 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -6722,105 +6722,98 @@ parser_lex(yp_parser_t *parser) { } // Get a reference to the current mode. - yp_lex_mode_t *mode = parser->lex_modes.current; + yp_lex_mode_t *lex_mode = parser->lex_modes.current; // These are the places where we need to split up the content of the // regular expression. We'll use strpbrk to find the first of these // characters. - const char *breakpoints = mode->as.regexp.breakpoints; + const char *breakpoints = lex_mode->as.regexp.breakpoints; const char *breakpoint = yp_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); while (breakpoint != NULL) { - switch (*breakpoint) { - case '\0': - // If we hit a null byte, skip directly past it. - breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - break; - case '\\': { - // If we hit escapes, then we need to treat the next token - // literally. In this case we'll skip past the next character and - // find the next breakpoint. - size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, YP_UNESCAPE_ALL, false, &parser->error_list); + // If we hit a null byte, skip directly past it. + if (*breakpoint == '\0') { + breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); + continue; + } - // If the result is an escaped newline, then we need to - // track that newline. - if (breakpoint[difference - 1] == '\n') { - yp_newline_list_append(&parser->newline_list, breakpoint + difference - 1); - } + // If we've hit a newline, then we need to track that in the + // list of newlines. + if (*breakpoint == '\n') { + yp_newline_list_append(&parser->newline_list, breakpoint); - breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference)); - break; + if (lex_mode->as.regexp.terminator != '\n') { + // If the terminator is not a newline, then we can set + // the next breakpoint and continue. + breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); + continue; } - case '#': { - // If the terminator is #, then we need to fall into the - // default case. Otherwise we'll attempt to lex - // interpolation. - if (mode->as.regexp.terminator != '#') { - yp_token_type_t type = lex_interpolation(parser, breakpoint); - if (type != YP_TOKEN_NOT_PROVIDED) { - LEX(type); - } + } - // If we haven't returned at this point then we had something - // that looked like an interpolated class or instance variable - // like "#@" but wasn't actually. In this case we'll just skip - // to the next breakpoint. - breakpoint = yp_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); - break; - } + // If we hit the terminator, we need to determine what kind of + // token to return. + if (*breakpoint == lex_mode->as.regexp.terminator) { + if (lex_mode->as.regexp.nesting > 0) { + breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); + lex_mode->as.regexp.nesting--; + continue; } - /* fallthrough */ - default: { - if (*breakpoint == mode->as.regexp.incrementor) { - // If we've hit the incrementor, then we need to skip past it and - // find the next breakpoint. - breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - mode->as.regexp.nesting++; - break; - } - - if (*breakpoint == '\n') { - // If we've hit a newline, then we need to track - // that in the list of newlines. - yp_newline_list_append(&parser->newline_list, breakpoint); - if (mode->as.regexp.terminator != '\n') { - // If the terminator is not a newline, then we - // can set the next breakpoint and continue. - breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - break; - } + // Here we've hit the terminator. If we have already consumed + // content then we need to return that content as string content + // first. + if (breakpoint > parser->current.start) { + parser->current.end = breakpoint; + LEX(YP_TOKEN_STRING_CONTENT); + } - // Otherwise, the newline character is the - // terminator so we need to continue on. - } + // Since we've hit the terminator of the regular expression, we now + // need to parse the options. + parser->current.end = breakpoint + 1; + parser->current.end += yp_strspn_regexp_option(parser->current.end, parser->end - parser->current.end); - assert(*breakpoint == mode->as.regexp.terminator); + lex_mode_pop(parser); + lex_state_set(parser, YP_LEX_STATE_END); + LEX(YP_TOKEN_REGEXP_END); + } - if (mode->as.regexp.nesting > 0) { - breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); - mode->as.regexp.nesting--; - break; - } + // If we hit escapes, then we need to treat the next token + // literally. In this case we'll skip past the next character + // and find the next breakpoint. + if (*breakpoint == '\\') { + size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, YP_UNESCAPE_ALL, false, &parser->error_list); - // Here we've hit the terminator. If we have already consumed - // content then we need to return that content as string content - // first. - if (breakpoint > parser->current.start) { - parser->current.end = breakpoint; - LEX(YP_TOKEN_STRING_CONTENT); - } + // If the result is an escaped newline, then we need to + // track that newline. + if (breakpoint[difference - 1] == '\n') { + yp_newline_list_append(&parser->newline_list, breakpoint + difference - 1); + } - // Since we've hit the terminator of the regular expression, we now - // need to parse the options. - parser->current.end = breakpoint + 1; - parser->current.end += yp_strspn_regexp_option(parser->current.end, parser->end - parser->current.end); + breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference)); + continue; + } - lex_mode_pop(parser); - lex_state_set(parser, YP_LEX_STATE_END); - LEX(YP_TOKEN_REGEXP_END); + // If we hit a #, then we will attempt to lex interpolation. + if (*breakpoint == '#') { + yp_token_type_t type = lex_interpolation(parser, breakpoint); + if (type != YP_TOKEN_NOT_PROVIDED) { + LEX(type); } + + // If we haven't returned at this point then we had + // something that looked like an interpolated class or + // instance variable like "#@" but wasn't actually. In this + // case we'll just skip to the next breakpoint. + breakpoint = yp_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end); + continue; } + + // If we've hit the incrementor, then we need to skip past it + // and find the next breakpoint. + assert(*breakpoint == lex_mode->as.regexp.incrementor); + breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); + lex_mode->as.regexp.nesting++; + continue; } // At this point, the breakpoint is NULL which means we were unable to From d6f9f3e498212eea18652028266d6c12b9ec429a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 4 Aug 2023 10:01:43 -0400 Subject: [PATCH 121/158] [ruby/yarp] Rename RescueNode#exception to RescueNode#reference https://github.com/ruby/yarp/commit/ad0eb4b2c3 --- yarp/yarp.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index bb4db37d7f135c..021fc7c6687667 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -3522,7 +3522,7 @@ yp_rescue_node_create(yp_parser_t *parser, const yp_token_t *keyword) { }, .keyword_loc = YP_LOCATION_TOKEN_VALUE(keyword), .operator_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, - .exception = NULL, + .reference = NULL, .statements = NULL, .consequent = NULL, .exceptions = YP_EMPTY_NODE_LIST @@ -3536,11 +3536,11 @@ yp_rescue_node_operator_set(yp_rescue_node_t *node, const yp_token_t *operator) node->operator_loc = YP_OPTIONAL_LOCATION_TOKEN_VALUE(operator); } -// Set the exception of a rescue node, and update the location of the node. +// Set the reference of a rescue node, and update the location of the node. static void -yp_rescue_node_exception_set(yp_rescue_node_t *node, yp_node_t *exception) { - node->exception = exception; - node->base.location.end = exception->location.end; +yp_rescue_node_reference_set(yp_rescue_node_t *node, yp_node_t *reference) { + node->reference = reference; + node->base.location.end = reference->location.end; } // Set the statements of a rescue node, and update the location of the node. @@ -8571,11 +8571,11 @@ parse_rescues(yp_parser_t *parser, yp_begin_node_t *parent_node) { parser_lex(parser); yp_rescue_node_operator_set(rescue, &parser->previous); - yp_node_t *node = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected an exception variable after `=>` in rescue statement."); + yp_node_t *reference = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected an exception variable after `=>` in rescue statement."); yp_token_t operator = not_provided(parser); - node = parse_target(parser, node, &operator, NULL); + reference = parse_target(parser, reference, &operator, NULL); - rescue->exception = node; + yp_rescue_node_reference_set(rescue, reference); break; } case YP_TOKEN_NEWLINE: @@ -8602,11 +8602,11 @@ parse_rescues(yp_parser_t *parser, yp_begin_node_t *parent_node) { if (accept(parser, YP_TOKEN_EQUAL_GREATER)) { yp_rescue_node_operator_set(rescue, &parser->previous); - yp_node_t *node = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected an exception variable after `=>` in rescue statement."); + yp_node_t *reference = parse_expression(parser, YP_BINDING_POWER_INDEX, "Expected an exception variable after `=>` in rescue statement."); yp_token_t operator = not_provided(parser); - node = parse_target(parser, node, &operator, NULL); + reference = parse_target(parser, reference, &operator, NULL); - yp_rescue_node_exception_set(rescue, node); + yp_rescue_node_reference_set(rescue, reference); break; } } while (accept(parser, YP_TOKEN_COMMA)); From 96aebb42652c8a2dde0e33d45316da64d26be566 Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Fri, 4 Aug 2023 11:02:29 -0400 Subject: [PATCH 122/158] [ruby/yarp] Address PR comments - odd whitespace - a couple of name changes - properly read uint32_t when not properly aligned https://github.com/ruby/yarp/commit/3208ee3983 --- yarp/yarp.c | 23 +++++++++++++++++------ yarp/yarp.h | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 021fc7c6687667..b1305f120927d7 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -12873,6 +12873,17 @@ parse_program(yp_parser_t *parser) { return (yp_node_t *) yp_program_node_create(parser, &locals, statements); } +static uint32_t +yp_read_u32(const char *ptr) { + if (((uintptr_t) ptr) % sizeof(uint32_t) == 0) { + return *((uint32_t *) ptr); + } else { + uint32_t value; + memcpy(&value, ptr, sizeof(uint32_t)); + return value; + } +} + // Process any additional metadata being passed into a parse. Since the source // of these calls will be from Ruby implementation internals we assume it is from // a trusted source. @@ -12894,19 +12905,19 @@ parse_program(yp_parser_t *parser) { // ] // ``` static void -yp_process_metadata(yp_parser_t *parser, const char *metadata) { +yp_parser_metadata(yp_parser_t *parser, const char *metadata) { const char *p = metadata; - uint32_t number_of_scopes = (uint32_t) *p; + uint32_t number_of_scopes = yp_read_u32(p); p += 4; for (size_t scope_index = 0; scope_index < number_of_scopes; scope_index++) { - uint32_t number_of_variables = (uint32_t) *p; + uint32_t number_of_variables = yp_read_u32(p); p += 4; yp_parser_scope_push(parser, scope_index == 0); for (size_t variable_index = 0; variable_index < number_of_variables; variable_index++) { - uint32_t length = (uint32_t) *p; + uint32_t length = yp_read_u32(p); p += 4; yp_parser_local_add_location(parser, p, p + length); @@ -13053,7 +13064,7 @@ yp_parser_free(yp_parser_t *parser) { // Parse the Ruby source associated with the given parser and return the tree. YP_EXPORTED_FUNCTION yp_node_t * yp_parse(yp_parser_t *parser) { - return parse_program(parser); + return parse_program(parser); } YP_EXPORTED_FUNCTION void @@ -13073,7 +13084,7 @@ YP_EXPORTED_FUNCTION void yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *metadata) { yp_parser_t parser; yp_parser_init(&parser, source, size, NULL); - if (metadata) yp_process_metadata(&parser, metadata); + if (metadata) yp_parser_metadata(&parser, metadata); yp_node_t *node = yp_parse(&parser); yp_serialize(&parser, node, buffer); diff --git a/yarp/yarp.h b/yarp/yarp.h index 410f739fb25ae4..1c6652a3021ebc 100644 --- a/yarp/yarp.h +++ b/yarp/yarp.h @@ -61,7 +61,7 @@ YP_EXPORTED_FUNCTION void yp_serialize(yp_parser_t *parser, yp_node_t *node, yp_ // Parse and serialize the AST represented by the given source to the given // buffer. -YP_EXPORTED_FUNCTION void yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *parent_scopes); +YP_EXPORTED_FUNCTION void yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *metadata); // Returns a string representation of the given token type. YP_EXPORTED_FUNCTION const char * yp_token_type_to_str(yp_token_type_t token_type); From 9b952670bb4945ea227a72dd9b74ef5972a69757 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 7 Aug 2023 13:11:59 -0400 Subject: [PATCH 123/158] [ruby/yarp] Less const_get Right now whenever you go to create a Ruby object from a C struct we dynamically look up the constants. This is not great for performance. Now instead we template out a constant for each VALUE that holds the classes, and then directly reference it. https://github.com/ruby/yarp/commit/f4756cda77 --- yarp/extension.c | 5 ++++- yarp/extension.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/yarp/extension.c b/yarp/extension.c index e6ef3f7648b649..2aa4dca3960777 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -4,6 +4,7 @@ // All non-trivial logic should be in librubyparser so it can be shared its the various callers. VALUE rb_cYARP; +VALUE rb_cYARPNode; VALUE rb_cYARPSource; VALUE rb_cYARPToken; VALUE rb_cYARPLocation; @@ -490,6 +491,7 @@ Init_yarp(void) { // Grab up references to all of the constants that we're going to need to // reference throughout this extension. rb_cYARP = rb_define_module("YARP"); + rb_cYARPNode = rb_define_class_under(rb_cYARP, "Node", rb_cObject); rb_cYARPSource = rb_define_class_under(rb_cYARP, "Source", rb_cObject); rb_cYARPToken = rb_define_class_under(rb_cYARP, "Token", rb_cObject); rb_cYARPLocation = rb_define_class_under(rb_cYARP, "Location", rb_cObject); @@ -520,6 +522,7 @@ Init_yarp(void) { rb_define_singleton_method(rb_cYARPDebug, "memsize", memsize, 1); rb_define_singleton_method(rb_cYARPDebug, "profile_file", profile_file, 1); - // Next, initialize the pack API. + // Next, initialize the other APIs. + Init_yarp_api_node(); Init_yarp_pack(); } diff --git a/yarp/extension.h b/yarp/extension.h index 1f281240c2d061..c8f950c2d2f6cc 100644 --- a/yarp/extension.h +++ b/yarp/extension.h @@ -11,6 +11,7 @@ VALUE yp_source_new(yp_parser_t *parser); VALUE yp_token_new(yp_parser_t *parser, yp_token_t *token, rb_encoding *encoding, VALUE source); VALUE yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding); +void Init_yarp_api_node(void); void Init_yarp_pack(void); YP_EXPORTED_FUNCTION void Init_yarp(void); From 77e52735f09411a94ce5ae8bdbac381bc0a49a44 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 7 Aug 2023 17:19:55 -0400 Subject: [PATCH 124/158] [ruby/yarp] Fix warnings found from gcc-analyzer and clang-analyzer https://github.com/ruby/yarp/commit/1f9a6e05c4 --- yarp/util/yp_string.c | 5 ++++- yarp/yarp.c | 15 ++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/yarp/util/yp_string.c b/yarp/util/yp_string.c index 45822635924438..ada42e27795a40 100644 --- a/yarp/util/yp_string.c +++ b/yarp/util/yp_string.c @@ -69,7 +69,10 @@ yp_string_ensure_owned(yp_string_t *string) { size_t length = yp_string_length(string); const char *source = yp_string_source(string); - yp_string_owned_init(string, malloc(length), length); + char *memory = malloc(length); + if (!memory) return; + + yp_string_owned_init(string, memory, length); memcpy(string->source, source, length); } diff --git a/yarp/yarp.c b/yarp/yarp.c index b1305f120927d7..6573a8ef403a54 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -505,10 +505,15 @@ yp_statements_node_body_append(yp_statements_node_t *node, yp_node_t *statement) // implement our own arena allocation. static inline void * yp_alloc_node(YP_ATTRIBUTE_UNUSED yp_parser_t *parser, size_t size) { - return malloc(size); + void *memory = malloc(size); + if (memory == NULL) { + fprintf(stderr, "Failed to allocate %zu bytes\n", size); + abort(); + } + return memory; } -#define YP_ALLOC_NODE(parser, type) (type *) yp_alloc_node(parser, sizeof(type)); if (node == NULL) return NULL +#define YP_ALLOC_NODE(parser, type) (type *) yp_alloc_node(parser, sizeof(type)) // Allocate a new MissingNode node. static yp_missing_node_t * @@ -12206,7 +12211,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t node = parse_target(parser, node, &operator, NULL); yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after &&="); - return (yp_node_t *) yp_call_operator_and_write_node_create(parser, call_node, &token, value); + return (yp_node_t *) yp_call_operator_and_write_node_create(parser, (yp_call_node_t *) node, &token, value); } case YP_NODE_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); @@ -12311,7 +12316,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t node = parse_target(parser, node, &operator, NULL); yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after ||="); - return (yp_node_t *) yp_call_operator_or_write_node_create(parser, call_node, &token, value); + return (yp_node_t *) yp_call_operator_or_write_node_create(parser, (yp_call_node_t *) node, &token, value); } case YP_NODE_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); @@ -12425,7 +12430,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t parser_lex(parser); yp_node_t *value = parse_expression(parser, binding_power, "Expected a value after the operator."); - return (yp_node_t *) yp_call_operator_write_node_create(parser, call_node, &token, value); + return (yp_node_t *) yp_call_operator_write_node_create(parser, (yp_call_node_t *) node, &token, value); } case YP_NODE_CLASS_VARIABLE_READ_NODE: { parser_lex(parser); From ee885237f6e39af4505b850f49637a2d274bc175 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 7 Aug 2023 16:55:02 -0400 Subject: [PATCH 125/158] [ruby/yarp] Fix string concat parsing https://github.com/ruby/yarp/commit/58f839a3eb --- .../unparser/corpus/semantic/dstr.txt | 10 +- yarp/yarp.c | 230 ++++++++++-------- 2 files changed, 128 insertions(+), 112 deletions(-) diff --git a/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt b/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt index b3ea49149c2721..10345e1db54db4 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt @@ -198,11 +198,11 @@ ProgramNode(0...608)( ) ), StringConcatNode(552...560)( - StringNode(552...554)((552...553), (553...553), (553...554), ""), - StringConcatNode(555...560)( - StringNode(555...557)((555...556), (556...556), (556...557), ""), - StringNode(558...560)((558...559), (559...559), (559...560), "") - ) + StringConcatNode(552...557)( + StringNode(552...554)((552...553), (553...553), (553...554), ""), + StringNode(555...557)((555...556), (556...556), (556...557), "") + ), + StringNode(558...560)((558...559), (559...559), (559...560), "") ), StringConcatNode(562...574)( InterpolatedStringNode(562...570)( diff --git a/yarp/yarp.c b/yarp/yarp.c index 6573a8ef403a54..22b1f9ab480bfb 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -11950,95 +11950,115 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { return (yp_node_t *) node; } case YP_TOKEN_STRING_BEGIN: { - assert(parser->lex_modes.current->mode == YP_LEX_STRING); - bool lex_interpolation = parser->lex_modes.current->as.string.interpolation; + yp_node_t *result = NULL; - yp_token_t opening = parser->current; - parser_lex(parser); - - yp_node_t *node; + while (match_type_p(parser, YP_TOKEN_STRING_BEGIN)) { + assert(parser->lex_modes.current->mode == YP_LEX_STRING); + bool lex_interpolation = parser->lex_modes.current->as.string.interpolation; - if (accept(parser, YP_TOKEN_STRING_END)) { - // If we get here, then we have an end immediately after a start. In - // that case we'll create an empty content token and return an - // uninterpolated string. - yp_token_t content = (yp_token_t) { - .type = YP_TOKEN_STRING_CONTENT, - .start = parser->previous.start, - .end = parser->previous.start - }; + yp_node_t *node = NULL; + yp_token_t opening = parser->current; + parser_lex(parser); - node = (yp_node_t *) yp_string_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_NONE); - } else if (accept(parser, YP_TOKEN_LABEL_END)) { - // If we get here, then we have an end of a label immediately after a - // start. In that case we'll create an empty symbol node. - yp_token_t opening = not_provided(parser); - yp_token_t content = (yp_token_t) { - .type = YP_TOKEN_STRING_CONTENT, - .start = parser->previous.start, - .end = parser->previous.start - }; + if (accept(parser, YP_TOKEN_STRING_END)) { + // If we get here, then we have an end immediately after a + // start. In that case we'll create an empty content token + // and return an uninterpolated string. + yp_token_t content = (yp_token_t) { + .type = YP_TOKEN_STRING_CONTENT, + .start = parser->previous.start, + .end = parser->previous.start + }; + + node = (yp_node_t *) yp_string_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_NONE); + } else if (accept(parser, YP_TOKEN_LABEL_END)) { + // If we get here, then we have an end of a label + // immediately after a start. In that case we'll create an + // empty symbol node. + yp_token_t opening = not_provided(parser); + yp_token_t content = (yp_token_t) { + .type = YP_TOKEN_STRING_CONTENT, + .start = parser->previous.start, + .end = parser->previous.start + }; + + node = (yp_node_t *) yp_symbol_node_create(parser, &opening, &content, &parser->previous); + } else if (!lex_interpolation) { + // If we don't accept interpolation then we expect the + // string to start with a single string content node. + expect(parser, YP_TOKEN_STRING_CONTENT, "Expected string content after opening delimiter."); + yp_token_t content = parser->previous; + + // It is unfortunately possible to have multiple string + // content nodes in a row in the case that there's heredoc + // content in the middle of the string, like this cursed + // example: + // + // <<-END+'b + // a + // END + // c'+'d' + // + // In that case we need to switch to an interpolated string + // to be able to contain all of the parts. + if (match_type_p(parser, YP_TOKEN_STRING_CONTENT)) { + yp_node_list_t parts = YP_EMPTY_NODE_LIST; - return (yp_node_t *) yp_symbol_node_create(parser, &opening, &content, &parser->previous); - } else if (!lex_interpolation) { - // If we don't accept interpolation then we expect the string to start - // with a single string content node. - expect(parser, YP_TOKEN_STRING_CONTENT, "Expected string content after opening delimiter."); - yp_token_t content = parser->previous; + yp_token_t delimiters = not_provided(parser); + yp_node_t *part = (yp_node_t *) yp_string_node_create_and_unescape(parser, &delimiters, &content, &delimiters, YP_UNESCAPE_MINIMAL); + yp_node_list_append(&parts, part); - // It is unfortunately possible to have multiple string content nodes in - // a row in the case that there's heredoc content in the middle of the - // string, like this cursed example: - // - // <<-END+'b - // a - // END - // c'+'d' - // - // In that case we need to switch to an interpolated string to be able - // to contain all of the parts. - if (match_type_p(parser, YP_TOKEN_STRING_CONTENT)) { - yp_node_list_t parts = YP_EMPTY_NODE_LIST; + while (accept(parser, YP_TOKEN_STRING_CONTENT)) { + part = (yp_node_t *) yp_string_node_create_and_unescape(parser, &delimiters, &parser->previous, &delimiters, YP_UNESCAPE_MINIMAL); + yp_node_list_append(&parts, part); + } - yp_token_t delimiters = not_provided(parser); - yp_node_t *part = (yp_node_t *) yp_string_node_create_and_unescape(parser, &delimiters, &content, &delimiters, YP_UNESCAPE_MINIMAL); - yp_node_list_append(&parts, part); + expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for a string literal."); + node = (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); + } else if (accept(parser, YP_TOKEN_LABEL_END)) { + node = (yp_node_t *) yp_symbol_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_ALL); + } else { + expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for a string literal."); + node = (yp_node_t *) yp_string_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_MINIMAL); + } + } else if (match_type_p(parser, YP_TOKEN_STRING_CONTENT)) { + // In this case we've hit string content so we know the string at + // least has something in it. We'll need to check if the following + // token is the end (in which case we can return a plain string) or if + // it's not then it has interpolation. + yp_token_t content = parser->current; + parser_lex(parser); - while (accept(parser, YP_TOKEN_STRING_CONTENT)) { - part = (yp_node_t *) yp_string_node_create_and_unescape(parser, &delimiters, &parser->previous, &delimiters, YP_UNESCAPE_MINIMAL); + if (accept(parser, YP_TOKEN_STRING_END)) { + node = (yp_node_t *) yp_string_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_ALL); + } else if (accept(parser, YP_TOKEN_LABEL_END)) { + node = (yp_node_t *) yp_symbol_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_ALL); + } else { + // If we get here, then we have interpolation so we'll need to create + // a string or symbol node with interpolation. + yp_node_list_t parts = YP_EMPTY_NODE_LIST; + yp_token_t string_opening = not_provided(parser); + yp_token_t string_closing = not_provided(parser); + yp_node_t *part = (yp_node_t *) yp_string_node_create_and_unescape(parser, &string_opening, &parser->previous, &string_closing, YP_UNESCAPE_ALL); yp_node_list_append(&parts, part); - } - - expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for a string literal."); - return (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); - } - if (accept(parser, YP_TOKEN_LABEL_END)) { - return (yp_node_t *) yp_symbol_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_ALL); - } - - expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for a string literal."); - node = (yp_node_t *) yp_string_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_MINIMAL); - } else if (match_type_p(parser, YP_TOKEN_STRING_CONTENT)) { - // In this case we've hit string content so we know the string at - // least has something in it. We'll need to check if the following - // token is the end (in which case we can return a plain string) or if - // it's not then it has interpolation. - yp_token_t content = parser->current; - parser_lex(parser); + while (!match_any_type_p(parser, 3, YP_TOKEN_STRING_END, YP_TOKEN_LABEL_END, YP_TOKEN_EOF)) { + yp_node_t *part = parse_string_part(parser); + if (part != NULL) yp_node_list_append(&parts, part); + } - if (accept(parser, YP_TOKEN_STRING_END)) { - node = (yp_node_t *) yp_string_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_ALL); - } else if (accept(parser, YP_TOKEN_LABEL_END)) { - return (yp_node_t *) yp_symbol_node_create_and_unescape(parser, &opening, &content, &parser->previous, YP_UNESCAPE_ALL); + if (accept(parser, YP_TOKEN_LABEL_END)) { + node = (yp_node_t *) yp_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); + } else { + expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for an interpolated string."); + node = (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); + } + } } else { - // If we get here, then we have interpolation so we'll need to create - // a string or symbol node with interpolation. + // If we get here, then the first part of the string is not plain string + // content, in which case we need to parse the string as an interpolated + // string. yp_node_list_t parts = YP_EMPTY_NODE_LIST; - yp_token_t string_opening = not_provided(parser); - yp_token_t string_closing = not_provided(parser); - yp_node_t *part = (yp_node_t *) yp_string_node_create_and_unescape(parser, &string_opening, &parser->previous, &string_closing, YP_UNESCAPE_ALL); - yp_node_list_append(&parts, part); while (!match_any_type_p(parser, 3, YP_TOKEN_STRING_END, YP_TOKEN_LABEL_END, YP_TOKEN_EOF)) { yp_node_t *part = parse_string_part(parser); @@ -12046,43 +12066,39 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } if (accept(parser, YP_TOKEN_LABEL_END)) { - return (yp_node_t *) yp_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); + node = (yp_node_t *) yp_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); + } else { + expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for an interpolated string."); + node = (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); } - - expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for an interpolated string."); - node = (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); } - } else { - // If we get here, then the first part of the string is not plain string - // content, in which case we need to parse the string as an interpolated - // string. - yp_node_list_t parts = YP_EMPTY_NODE_LIST; - while (!match_any_type_p(parser, 3, YP_TOKEN_STRING_END, YP_TOKEN_LABEL_END, YP_TOKEN_EOF)) { - yp_node_t *part = parse_string_part(parser); - if (part != NULL) yp_node_list_append(&parts, part); - } + if (result == NULL) { + // If the node we just parsed is a symbol node, then we + // can't concatenate it with anything else, so we can now + // return that node. + if (YP_NODE_TYPE_P(node, YP_NODE_SYMBOL_NODE) || YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_SYMBOL_NODE)) { + return node; + } - if (accept(parser, YP_TOKEN_LABEL_END)) { - return (yp_node_t *) yp_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous); - } + // If we don't already have a node, then it's fine and we + // can just set the result to be the node we just parsed. + result = node; + } else { + // Otherwise we need to check the type of the node we just + // parsed. If it cannot be concatenated with the previous + // node, then we'll need to add a syntax error. + if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE) && !YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_STRING_NODE)) { + yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Unexpected string concatenation."); + } - expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for an interpolated string."); - node = (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); + // Either way we will create a concat node to hold the + // strings together. + result = (yp_node_t *) yp_string_concat_node_create(parser, result, node); + } } - // If there's a string immediately following this string, then it's a - // concatenatation. In this case we'll parse the next string and create a - // node in the tree that concatenates the two strings. - if (parser->current.type == YP_TOKEN_STRING_BEGIN) { - return (yp_node_t *) yp_string_concat_node_create( - parser, - node, - parse_expression(parser, YP_BINDING_POWER_CALL, "Expected string on the right side of concatenation.") - ); - } else { - return node; - } + return result; } case YP_TOKEN_SYMBOL_BEGIN: { yp_lex_mode_t lex_mode = *parser->lex_modes.current; From 89de544442c8cd5db08a0fe4b582ba24e67f062e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 8 Aug 2023 14:11:23 -0400 Subject: [PATCH 126/158] [ruby/yarp] Set constant path write node target type https://github.com/ruby/yarp/commit/771f7ed789 --- yarp/yarp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 22b1f9ab480bfb..4cf58cbc3a88b3 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -1607,15 +1607,15 @@ yp_constant_path_node_create(yp_parser_t *parser, yp_node_t *parent, const yp_to // Allocate a new ConstantPathWriteNode node. static yp_constant_path_write_node_t * -yp_constant_path_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { +yp_constant_path_write_node_create(yp_parser_t *parser, yp_constant_path_node_t *target, const yp_token_t *operator, yp_node_t *value) { yp_constant_path_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_path_write_node_t); *node = (yp_constant_path_write_node_t) { { .type = YP_NODE_CONSTANT_PATH_WRITE_NODE, .location = { - .start = target->location.start, - .end = (value == NULL ? target->location.end : value->location.end) + .start = target->base.location.start, + .end = (value == NULL ? target->base.location.end : value->location.end) }, }, .target = target, @@ -7548,7 +7548,7 @@ parse_target(yp_parser_t *parser, yp_node_t *target, yp_token_t *operator, yp_no return (yp_node_t *) write_node; } case YP_NODE_CONSTANT_PATH_NODE: - return (yp_node_t *) yp_constant_path_write_node_create(parser, target, operator, value); + return (yp_node_t *) yp_constant_path_write_node_create(parser, (yp_constant_path_node_t *) target, operator, value); case YP_NODE_CONSTANT_READ_NODE: { yp_constant_write_node_t *node = yp_constant_write_node_create(parser, &target->location, operator, value); yp_node_destroy(parser, target); From 383c47f538974f57a1a5c7d1b174ce365fdd8698 Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Tue, 8 Aug 2023 16:55:58 -0400 Subject: [PATCH 127/158] [ruby/yarp] Separate yp_node_flags_t from yp_node_type_t Prior to this commit, we folded the flags into the type. This created extra overhead when calculating the type and setting the flags. This commit separates them. https://github.com/ruby/yarp/commit/b783a5678c --- yarp/yarp.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 4cf58cbc3a88b3..71b7e2f895c324 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -505,7 +505,7 @@ yp_statements_node_body_append(yp_statements_node_t *node, yp_node_t *statement) // implement our own arena allocation. static inline void * yp_alloc_node(YP_ATTRIBUTE_UNUSED yp_parser_t *parser, size_t size) { - void *memory = malloc(size); + void *memory = calloc(1, size); if (memory == NULL) { fprintf(stderr, "Failed to allocate %zu bytes\n", size); abort(); @@ -2289,7 +2289,8 @@ yp_if_node_create(yp_parser_t *parser, *node = (yp_if_node_t) { { - .type = YP_NODE_IF_NODE | YP_NODE_FLAG_NEWLINE, + .flags = YP_NODE_FLAG_NEWLINE, + .type = YP_NODE_IF_NODE, .location = { .start = if_keyword->start, .end = end @@ -2315,7 +2316,8 @@ yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_t *node = (yp_if_node_t) { { - .type = YP_NODE_IF_NODE | YP_NODE_FLAG_NEWLINE, + .flags = YP_NODE_FLAG_NEWLINE, + .type = YP_NODE_IF_NODE, .location = { .start = statement->location.start, .end = predicate->location.end @@ -2347,7 +2349,8 @@ yp_if_node_ternary_create(yp_parser_t *parser, yp_node_t *predicate, yp_node_t * *node = (yp_if_node_t) { { - .type = YP_NODE_IF_NODE | YP_NODE_FLAG_NEWLINE, + .flags = YP_NODE_FLAG_NEWLINE, + .type = YP_NODE_IF_NODE, .location = { .start = predicate->location.start, .end = false_expression->location.end, @@ -3751,7 +3754,7 @@ yp_statements_node_body_append(yp_statements_node_t *node, yp_node_t *statement) node->base.location.end = statement->location.end; // Every statement gets marked as a place where a newline can occur. - statement->type |= YP_NODE_FLAG_NEWLINE; + statement->flags = YP_NODE_FLAG_NEWLINE; } // Allocate a new StringConcatNode node. @@ -3982,7 +3985,8 @@ yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *node = (yp_unless_node_t) { { - .type = YP_NODE_UNLESS_NODE | YP_NODE_FLAG_NEWLINE, + .flags = YP_NODE_FLAG_NEWLINE, + .type = YP_NODE_UNLESS_NODE, .location = { .start = keyword->start, .end = end @@ -4008,7 +4012,8 @@ yp_unless_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const *node = (yp_unless_node_t) { { - .type = YP_NODE_UNLESS_NODE | YP_NODE_FLAG_NEWLINE, + .flags = YP_NODE_FLAG_NEWLINE, + .type = YP_NODE_UNLESS_NODE, .location = { .start = statement->location.start, .end = predicate->location.end From 86cc82a1ab339914ed7ebe787cb76f954a19120d Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Wed, 9 Aug 2023 10:17:25 -0400 Subject: [PATCH 128/158] [ruby/yarp] Improved comments, moved flags after type https://github.com/ruby/yarp/commit/4815d77e82 --- yarp/yarp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarp/yarp.c b/yarp/yarp.c index 71b7e2f895c324..6f3d8758605b87 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -2289,8 +2289,8 @@ yp_if_node_create(yp_parser_t *parser, *node = (yp_if_node_t) { { - .flags = YP_NODE_FLAG_NEWLINE, .type = YP_NODE_IF_NODE, + .flags = YP_NODE_FLAG_NEWLINE, .location = { .start = if_keyword->start, .end = end @@ -2316,8 +2316,8 @@ yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_t *node = (yp_if_node_t) { { - .flags = YP_NODE_FLAG_NEWLINE, .type = YP_NODE_IF_NODE, + .flags = YP_NODE_FLAG_NEWLINE, .location = { .start = statement->location.start, .end = predicate->location.end @@ -2349,8 +2349,8 @@ yp_if_node_ternary_create(yp_parser_t *parser, yp_node_t *predicate, yp_node_t * *node = (yp_if_node_t) { { - .flags = YP_NODE_FLAG_NEWLINE, .type = YP_NODE_IF_NODE, + .flags = YP_NODE_FLAG_NEWLINE, .location = { .start = predicate->location.start, .end = false_expression->location.end, @@ -3985,8 +3985,8 @@ yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *node = (yp_unless_node_t) { { - .flags = YP_NODE_FLAG_NEWLINE, .type = YP_NODE_UNLESS_NODE, + .flags = YP_NODE_FLAG_NEWLINE, .location = { .start = keyword->start, .end = end @@ -4012,8 +4012,8 @@ yp_unless_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const *node = (yp_unless_node_t) { { - .flags = YP_NODE_FLAG_NEWLINE, .type = YP_NODE_UNLESS_NODE, + .flags = YP_NODE_FLAG_NEWLINE, .location = { .start = statement->location.start, .end = predicate->location.end From ecf2e84c05903cc7cdbc78310eae3cca794164d1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 9 Aug 2023 10:57:00 -0400 Subject: [PATCH 129/158] [ruby/yarp] Add a CHANGELOG https://github.com/ruby/yarp/commit/b490ff0919 --- lib/yarp/yarp.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/yarp/yarp.gemspec b/lib/yarp/yarp.gemspec index 2d6a75596aabcc..c018e96f96c6bd 100644 --- a/lib/yarp/yarp.gemspec +++ b/lib/yarp/yarp.gemspec @@ -12,6 +12,7 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.files = [ + "CHANGELOG.md", "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", "LICENSE.md", From fb287fa425514ee26a156e9792e1e6380c0318b5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 10 Aug 2023 10:46:12 -0400 Subject: [PATCH 130/158] [ruby/yarp] Support the flipflop flag https://github.com/ruby/yarp/commit/6315890390 --- .../snapshots/seattlerb/flip2_env_lvar.txt | 2 +- .../unparser/corpus/semantic/and.txt | 8 ++--- .../snapshots/whitequark/cond_eflipflop.txt | 2 +- .../snapshots/whitequark/cond_iflipflop.txt | 2 +- yarp/yarp.c | 32 +++++++++++++++++++ 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt b/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt index 623be4987e7344..ffb6ee684b84eb 100644 --- a/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt +++ b/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt @@ -7,7 +7,7 @@ ProgramNode(0...16)( CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "a"), CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b"), (4...6), - 0 + 2 ), nil, nil, diff --git a/test/yarp/snapshots/unparser/corpus/semantic/and.txt b/test/yarp/snapshots/unparser/corpus/semantic/and.txt index 470615af51c8c8..b082d308f777d2 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/and.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/and.txt @@ -38,13 +38,13 @@ ProgramNode(0...77)( CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 0, "a"), CallNode(39...40)(nil, nil, (39...40), nil, nil, nil, nil, 0, "b"), (36...39), - 1 + 3 ), RangeNode(44...49)( CallNode(44...45)(nil, nil, (44...45), nil, nil, nil, nil, 0, "c"), CallNode(48...49)(nil, nil, (48...49), nil, nil, nil, nil, 0, "d"), (45...48), - 1 + 3 ), (41...43) ), @@ -59,13 +59,13 @@ ProgramNode(0...77)( CallNode(58...59)(nil, nil, (58...59), nil, nil, nil, nil, 0, "a"), CallNode(62...63)(nil, nil, (62...63), nil, nil, nil, nil, 0, "b"), (59...62), - 1 + 3 ), RangeNode(68...73)( CallNode(68...69)(nil, nil, (68...69), nil, nil, nil, nil, 0, "c"), CallNode(72...73)(nil, nil, (72...73), nil, nil, nil, nil, 0, "d"), (69...72), - 1 + 3 ), (64...67) ), diff --git a/test/yarp/snapshots/whitequark/cond_eflipflop.txt b/test/yarp/snapshots/whitequark/cond_eflipflop.txt index 6e1e6718d50ce7..dd44ace9a40456 100644 --- a/test/yarp/snapshots/whitequark/cond_eflipflop.txt +++ b/test/yarp/snapshots/whitequark/cond_eflipflop.txt @@ -39,7 +39,7 @@ ProgramNode(0...31)( CallNode(17...20)(nil, nil, (17...20), nil, nil, nil, nil, 0, "foo"), CallNode(23...26)(nil, nil, (23...26), nil, nil, nil, nil, 0, "bar"), (20...23), - 1 + 3 ), nil, nil, diff --git a/test/yarp/snapshots/whitequark/cond_iflipflop.txt b/test/yarp/snapshots/whitequark/cond_iflipflop.txt index e45eec8922e86a..594d1a9c60608f 100644 --- a/test/yarp/snapshots/whitequark/cond_iflipflop.txt +++ b/test/yarp/snapshots/whitequark/cond_iflipflop.txt @@ -39,7 +39,7 @@ ProgramNode(0...29)( CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "foo"), CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "bar"), (19...21), - 0 + 2 ), nil, nil, diff --git a/yarp/yarp.c b/yarp/yarp.c index 6f3d8758605b87..9de67f7c62a880 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -431,6 +431,32 @@ yp_parser_constant_id_token(yp_parser_t *parser, const yp_token_t *token) { return yp_parser_constant_id_location(parser, token->start, token->end); } +// Mark any range nodes in this subtree as flipflops. +static void +yp_flip_flop(yp_node_t *node) { + switch (YP_NODE_TYPE(node)) { + case YP_NODE_AND_NODE: { + yp_and_node_t *cast = (yp_and_node_t *) node; + yp_flip_flop(cast->left); + yp_flip_flop(cast->right); + break; + } + case YP_NODE_OR_NODE: { + yp_or_node_t *cast = (yp_or_node_t *) node; + yp_flip_flop(cast->left); + yp_flip_flop(cast->right); + break; + } + case YP_NODE_RANGE_NODE: { + yp_range_node_t *cast = (yp_range_node_t *) node; + cast->flags |= YP_RANGE_NODE_FLAGS_FLIP_FLOP; + break; + } + default: + break; + } +} + // In a lot of places in the tree you can have tokens that are not provided but // that do not cause an error. For example, in a method call without // parentheses. In these cases we set the token to the "not provided" type. For @@ -2274,6 +2300,7 @@ yp_if_node_create(yp_parser_t *parser, yp_node_t *consequent, const yp_token_t *end_keyword ) { + yp_flip_flop(predicate); yp_if_node_t *node = YP_ALLOC_NODE(parser, yp_if_node_t); const char *end; @@ -2309,6 +2336,7 @@ yp_if_node_create(yp_parser_t *parser, // Allocate and initialize new IfNode node in the modifier form. static yp_if_node_t * yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_token_t *if_keyword, yp_node_t *predicate) { + yp_flip_flop(predicate); yp_if_node_t *node = YP_ALLOC_NODE(parser, yp_if_node_t); yp_statements_node_t *statements = yp_statements_node_create(parser); @@ -2336,6 +2364,8 @@ yp_if_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_t // Allocate and initialize an if node from a ternary expression. static yp_if_node_t * yp_if_node_ternary_create(yp_parser_t *parser, yp_node_t *predicate, yp_node_t *true_expression, const yp_token_t *colon, yp_node_t *false_expression) { + yp_flip_flop(predicate); + yp_statements_node_t *if_statements = yp_statements_node_create(parser); yp_statements_node_body_append(if_statements, true_expression); @@ -3974,6 +4004,7 @@ yp_undef_node_append(yp_undef_node_t *node, yp_node_t *name) { // Allocate a new UnlessNode node. static yp_unless_node_t * yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements) { + yp_flip_flop(predicate); yp_unless_node_t *node = YP_ALLOC_NODE(parser, yp_unless_node_t); const char *end; @@ -4005,6 +4036,7 @@ yp_unless_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t // Allocate and initialize new UnlessNode node in the modifier form. static yp_unless_node_t * yp_unless_node_modifier_create(yp_parser_t *parser, yp_node_t *statement, const yp_token_t *unless_keyword, yp_node_t *predicate) { + yp_flip_flop(predicate); yp_unless_node_t *node = YP_ALLOC_NODE(parser, yp_unless_node_t); yp_statements_node_t *statements = yp_statements_node_create(parser); From bf723b21ccd9d019bca5e33364a21f0219326547 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 10 Aug 2023 14:16:56 -0400 Subject: [PATCH 131/158] [ruby/yarp] More flip flop flags Whenever you see a `not` or a `!`, the receiver of that method should potentially be marked as a flip-flop. https://github.com/ruby/yarp/commit/ba5977a40a --- test/yarp/fixtures/not.txt | 4 + test/yarp/snapshots/not.txt | 82 ++++++++++++++++++- .../unparser/corpus/literal/flipflop.txt | 4 +- .../snapshots/whitequark/cond_eflipflop.txt | 2 +- .../snapshots/whitequark/cond_iflipflop.txt | 2 +- yarp/yarp.c | 13 +++ 6 files changed, 101 insertions(+), 6 deletions(-) diff --git a/test/yarp/fixtures/not.txt b/test/yarp/fixtures/not.txt index a623553613eb6b..520b34fa37aafd 100644 --- a/test/yarp/fixtures/not.txt +++ b/test/yarp/fixtures/not.txt @@ -31,3 +31,7 @@ foo ) + +not foo .. bar + +not (foo .. bar) diff --git a/test/yarp/snapshots/not.txt b/test/yarp/snapshots/not.txt index a4be66de262ba5..7bec91e7e73520 100644 --- a/test/yarp/snapshots/not.txt +++ b/test/yarp/snapshots/not.txt @@ -1,6 +1,6 @@ -ProgramNode(0...156)( +ProgramNode(0...190)( [], - StatementsNode(0...156)( + StatementsNode(0...190)( [AndNode(0...19)( CallNode(0...7)( CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "foo"), @@ -188,6 +188,84 @@ ProgramNode(0...156)( nil, 0, "!" + ), + CallNode(158...172)( + RangeNode(162...172)( + CallNode(162...165)( + nil, + nil, + (162...165), + nil, + nil, + nil, + nil, + 2, + "foo" + ), + CallNode(169...172)( + nil, + nil, + (169...172), + nil, + nil, + nil, + nil, + 2, + "bar" + ), + (166...168), + 2 + ), + nil, + (158...161), + nil, + nil, + nil, + nil, + 0, + "!" + ), + CallNode(174...190)( + ParenthesesNode(178...190)( + StatementsNode(179...189)( + [RangeNode(179...189)( + CallNode(179...182)( + nil, + nil, + (179...182), + nil, + nil, + nil, + nil, + 2, + "foo" + ), + CallNode(186...189)( + nil, + nil, + (186...189), + nil, + nil, + nil, + nil, + 2, + "bar" + ), + (183...185), + 2 + )] + ), + (178...179), + (189...190) + ), + nil, + (174...177), + nil, + nil, + nil, + nil, + 0, + "!" )] ) ) diff --git a/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt b/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt index b4837b7dc83df7..ea875e159a0fce 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt @@ -61,7 +61,7 @@ ProgramNode(0...68)( (21...22) ), (12...14), - 0 + 2 )] ), (3...4), @@ -133,7 +133,7 @@ ProgramNode(0...68)( (56...57) ), (46...49), - 1 + 3 )] ), (37...38), diff --git a/test/yarp/snapshots/whitequark/cond_eflipflop.txt b/test/yarp/snapshots/whitequark/cond_eflipflop.txt index dd44ace9a40456..889d14d8f370f0 100644 --- a/test/yarp/snapshots/whitequark/cond_eflipflop.txt +++ b/test/yarp/snapshots/whitequark/cond_eflipflop.txt @@ -18,7 +18,7 @@ ProgramNode(0...31)( "bar" ), (5...8), - 1 + 3 )] ), (1...2), diff --git a/test/yarp/snapshots/whitequark/cond_iflipflop.txt b/test/yarp/snapshots/whitequark/cond_iflipflop.txt index 594d1a9c60608f..5dee6f321c2bb7 100644 --- a/test/yarp/snapshots/whitequark/cond_iflipflop.txt +++ b/test/yarp/snapshots/whitequark/cond_iflipflop.txt @@ -18,7 +18,7 @@ ProgramNode(0...29)( "bar" ), (5...7), - 0 + 2 )] ), (1...2), diff --git a/yarp/yarp.c b/yarp/yarp.c index 9de67f7c62a880..dcfde47d01e133 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -447,6 +447,16 @@ yp_flip_flop(yp_node_t *node) { yp_flip_flop(cast->right); break; } + case YP_NODE_PARENTHESES_NODE: { + yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node; + + if ((cast->statements != NULL) && YP_NODE_TYPE_P(cast->statements, YP_NODE_STATEMENTS_NODE)) { + yp_statements_node_t *statements = (yp_statements_node_t *) cast->statements; + if (statements->body.size == 1) yp_flip_flop(statements->body.nodes[0]); + } + + break; + } case YP_NODE_RANGE_NODE: { yp_range_node_t *cast = (yp_range_node_t *) node; cast->flags |= YP_RANGE_NODE_FLAGS_FLIP_FLOP; @@ -11303,6 +11313,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { arguments.closing_loc = ((yp_location_t) { .start = parser->previous.start, .end = parser->previous.end }); } else { receiver = parse_expression(parser, YP_BINDING_POWER_COMPOSITION, "Expected expression after `not`."); + yp_flip_flop(receiver); if (!parser->recovering) { accept(parser, YP_TOKEN_NEWLINE); @@ -11312,6 +11323,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } } else { receiver = parse_expression(parser, YP_BINDING_POWER_DEFINED, "Expected expression after `not`."); + yp_flip_flop(receiver); } return (yp_node_t *) yp_call_node_not_create(parser, receiver, &message, &arguments); @@ -11889,6 +11901,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_node_t *receiver = parse_expression(parser, yp_binding_powers[parser->previous.type].right, "Expected a receiver after unary !."); yp_call_node_t *node = yp_call_node_unary_create(parser, &operator, receiver, "!"); + yp_flip_flop(receiver); return (yp_node_t *) node; } case YP_TOKEN_TILDE: { From a8c70ed2b42013158c1d5ebe11b8ed5aeed8eb45 Mon Sep 17 00:00:00 2001 From: HParker Date: Thu, 10 Aug 2023 10:17:43 -0700 Subject: [PATCH 132/158] [ruby/yarp] add a diagnostic for *rest in order after optional state https://github.com/ruby/yarp/commit/908244ba12 --- test/yarp/errors_test.rb | 16 ++++++++++++++++ yarp/yarp.c | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/test/yarp/errors_test.rb b/test/yarp/errors_test.rb index e705a6423c3bba..0777efe47ab413 100644 --- a/test/yarp/errors_test.rb +++ b/test/yarp/errors_test.rb @@ -1076,6 +1076,22 @@ def test_duplicated_parameter_names assert_errors expected, "def foo(a,b,&a);end", [ ["Duplicated parameter name.", 13..14] ] + + expected = DefNode( + Location(), + nil, + ParametersNode([], [OptionalParameterNode(:a, Location(), Location(), IntegerNode())], [RequiredParameterNode(:b)], RestParameterNode(Location(), Location()), [], nil, nil), + nil, + [:a, :b, :c], + Location(), + nil, + Location(), + Location(), + nil, + Location() + ) + + assert_errors expected, "def foo(a = 1,b,*c);end", [["Unexpected parameter *", 16..17]] end private diff --git a/yarp/yarp.c b/yarp/yarp.c index dcfde47d01e133..59ec35a03d5e9a 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -8312,6 +8312,10 @@ update_parameter_state(yp_parser_t *parser, yp_token_t *token, yp_parameters_ord return; } + if (token->type == YP_TOKEN_USTAR && *current == YP_PARAMETERS_ORDER_AFTER_OPTIONAL) { + yp_diagnostic_list_append(&parser->error_list, token->start, token->end, "Unexpected parameter *"); + } + if (*current == YP_PARAMETERS_ORDER_NOTHING_AFTER || state > *current) { // We know what transition we failed on, so we can provide a better error here. yp_diagnostic_list_append(&parser->error_list, token->start, token->end, "Unexpected parameter order"); From 958ac8d58680782cd839b657f290fe698c044f20 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sun, 13 Aug 2023 12:44:32 +0200 Subject: [PATCH 133/158] [ruby/yarp] Test all methods of the YARP Ruby API https://github.com/ruby/yarp/commit/a723f40baf --- test/ruby_api_test.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/ruby_api_test.rb diff --git a/test/ruby_api_test.rb b/test/ruby_api_test.rb new file mode 100644 index 00000000000000..ea18fbb35a49b4 --- /dev/null +++ b/test/ruby_api_test.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require "yarp_test_helper" + +class YARPRubyAPITest < Test::Unit::TestCase + def test_ruby_api + filepath = __FILE__ + source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) + + assert_equal YARP.lex(source, filepath).value, YARP.lex_file(filepath).value + + assert_equal YARP.dump(source, filepath), YARP.dump_file(filepath) + + serialized = YARP.dump(source, filepath) + ast1 = YARP.load(source, serialized).value + ast2 = YARP.parse(source, filepath).value + ast3 = YARP.parse_file(filepath).value + + assert_equal_nodes ast1, ast2 + assert_equal_nodes ast2, ast3 + end +end From 3536cad9022e1f4fc6e6fd3d629de005e7c3342a Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 12 Aug 2023 19:21:35 +0200 Subject: [PATCH 134/158] [ruby/yarp] Fixes so `bundle exec rake` can run on JRuby and TruffleRuby https://github.com/ruby/yarp/commit/e6cea4fa08 --- lib/yarp/ripper_compat.rb | 6 +++--- test/yarp/comments_test.rb | 2 +- test/yarp/errors_test.rb | 8 ++++---- test/yarp/location_test.rb | 6 ++++-- test/yarp/parse_test.rb | 7 +++++-- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/yarp/ripper_compat.rb b/lib/yarp/ripper_compat.rb index f29f7a1bf143e1..c76f3fd07ad153 100644 --- a/lib/yarp/ripper_compat.rb +++ b/lib/yarp/ripper_compat.rb @@ -47,9 +47,9 @@ def _dispatch_event_push(list, item) Ripper::PARSER_EVENT_TABLE.each do |event, arity| case event when /_new\z/ - alias :"on_#{event}" :_dispatch_event_new if arity == 0 + alias_method :"on_#{event}", :_dispatch_event_new if arity == 0 when /_add\z/ - alias :"on_#{event}" :_dispatch_event_push + alias_method :"on_#{event}", :_dispatch_event_push end end end @@ -168,7 +168,7 @@ def _dispatch5(_, _, _, _, _); end def _dispatch7(_, _, _, _, _, _, _); end (Ripper::SCANNER_EVENT_TABLE.merge(Ripper::PARSER_EVENT_TABLE)).each do |event, arity| - alias :"on_#{event}" :"_dispatch#{arity}" + alias_method :"on_#{event}", :"_dispatch#{arity}" end end end diff --git a/test/yarp/comments_test.rb b/test/yarp/comments_test.rb index e22dffd46dbbba..5c49f7b86e7b5b 100644 --- a/test/yarp/comments_test.rb +++ b/test/yarp/comments_test.rb @@ -52,7 +52,7 @@ def test_comment_embedded_document_with_content_on_same_line def assert_comment(source, type, location) result = YARP.parse(source) assert result.errors.empty?, result.errors.map(&:message).join("\n") - result => YARP::ParseResult[comments: [YARP::Comment[type: type]]] + assert_equal result.comments.first.type, type assert_equal result.comments.first.location.start_offset, location.begin assert_equal result.comments.first.location.end_offset, location.end end diff --git a/test/yarp/errors_test.rb b/test/yarp/errors_test.rb index 0777efe47ab413..e89ade0ba5e903 100644 --- a/test/yarp/errors_test.rb +++ b/test/yarp/errors_test.rb @@ -1097,10 +1097,11 @@ def test_duplicated_parameter_names private def assert_errors(expected, source, errors) - assert_nil Ripper.sexp_raw(source) + # Ripper behaves differently on JRuby/TruffleRuby, so only check this on CRuby + assert_nil Ripper.sexp_raw(source) if RUBY_ENGINE == "ruby" result = YARP.parse(source) - result => YARP::ParseResult[value: YARP::ProgramNode[statements: YARP::StatementsNode[body: [*, node]]]] + node = result.value.statements.body.last assert_equal_nodes(expected, node, compare_location: false) assert_equal(errors, result.errors.map { |e| [e.message, e.location.start_offset..e.location.end_offset] }) @@ -1113,7 +1114,6 @@ def assert_error_messages(source, errors) end def expression(source) - YARP.parse(source) => YARP::ParseResult[value: YARP::ProgramNode[statements: YARP::StatementsNode[body: [*, node]]]] - node + YARP.parse(source).value.statements.body.last end end diff --git a/test/yarp/location_test.rb b/test/yarp/location_test.rb index 2f551949e5b6cf..2aaaa7aa761aa5 100644 --- a/test/yarp/location_test.rb +++ b/test/yarp/location_test.rb @@ -753,9 +753,11 @@ def test_YieldNode private def assert_location(kind, source, expected = 0...source.length) - YARP.parse(source) => ParseResult[comments: [], errors: [], value: node] + result = YARP.parse(source) + assert_equal [], result.comments + assert_equal [], result.errors - node => ProgramNode[statements: [*, node]] + node = result.value.statements.body.last node = yield node if block_given? assert_kind_of kind, node diff --git a/test/yarp/parse_test.rb b/test/yarp/parse_test.rb index 91752cd483b475..43a1deb8fb1ade 100644 --- a/test/yarp/parse_test.rb +++ b/test/yarp/parse_test.rb @@ -23,7 +23,8 @@ def test_Ruby_3_2_plus end def test_empty_string - YARP.parse("") => YARP::ParseResult[value: YARP::ProgramNode[statements: YARP::StatementsNode[body: []]]] + result = YARP.parse("") + assert_equal [], result.value.statements.body end known_failures = %w[ @@ -107,7 +108,9 @@ def test_parse_takes_file_path # Finally, assert that we can lex the source and get the same tokens as # Ripper. - YARP.lex_compat(source) => { errors: [], value: tokens } + lex_result = YARP.lex_compat(source) + assert_equal [], lex_result.errors + tokens = lex_result.value begin YARP.lex_ripper(source).zip(tokens).each do |(ripper, yarp)| From 957cd369fa38915241e0b66e852f66ac516de664 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 14 Aug 2023 13:58:24 -0400 Subject: [PATCH 135/158] [ruby/yarp] Add test for empty heredoc https://github.com/ruby/yarp/commit/e49b63a79e --- test/yarp/fixtures/dash_heredocs.txt | 3 +++ test/yarp/snapshots/dash_heredocs.txt | 13 +++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test/yarp/fixtures/dash_heredocs.txt b/test/yarp/fixtures/dash_heredocs.txt index a05df93023a754..aba782c99ad163 100644 --- a/test/yarp/fixtures/dash_heredocs.txt +++ b/test/yarp/fixtures/dash_heredocs.txt @@ -39,6 +39,9 @@ EOF b EOF +<<-'' + + <<-'EOF' a #{1} EOF diff --git a/test/yarp/snapshots/dash_heredocs.txt b/test/yarp/snapshots/dash_heredocs.txt index bc4c90a76f7c54..ad79c4625173f2 100644 --- a/test/yarp/snapshots/dash_heredocs.txt +++ b/test/yarp/snapshots/dash_heredocs.txt @@ -1,6 +1,6 @@ -ProgramNode(0...223)( +ProgramNode(0...231)( [], - StatementsNode(0...223)( + StatementsNode(0...231)( [InterpolatedStringNode(0...15)( (0...6), [StringNode(7...11)(nil, (7...11), nil, " a\n")], @@ -112,10 +112,11 @@ ProgramNode(0...223)( [StringNode(188...196)(nil, (188...196), nil, " a\n" + " b\n")], (196...200) ), - InterpolatedStringNode(201...223)( - (201...209), - [StringNode(210...219)(nil, (210...219), nil, " a \#{1}\n")], - (219...223) + InterpolatedStringNode(201...208)((201...206), [], (207...208)), + InterpolatedStringNode(209...231)( + (209...217), + [StringNode(218...227)(nil, (218...227), nil, " a \#{1}\n")], + (227...231) )] ) ) From 3873b1eb39a2070937dc62ac47f8b96df54a72fc Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 15 Aug 2023 10:00:54 -0700 Subject: [PATCH 136/158] Resync YARP --- lib/yarp.rb | 240 +- lib/yarp/ffi.rb | 211 + lib/yarp/lex_compat.rb | 19 +- lib/yarp/node.rb | 358 +- lib/yarp/serialize.rb | 413 +- lib/yarp/yarp.gemspec | 44 +- test/newline_test.rb | 78 - test/yarp/encoding_test.rb | 1 + test/yarp/errors_test.rb | 85 +- test/yarp/fixtures/method_calls.txt | 8 + test/yarp/fixtures/ternary_operator.txt | 2 + test/yarp/locals_test.rb | 86 + test/yarp/memsize_test.rb | 2 + test/yarp/newline_test.rb | 100 + test/yarp/parse_serialize_test.rb | 26 + test/yarp/parse_test.rb | 69 +- test/yarp/regexp_test.rb | 2 + test/{ => yarp}/ruby_api_test.rb | 0 test/yarp/snapshots/arithmetic.txt | 12 +- test/yarp/snapshots/arrays.txt | 74 +- test/yarp/snapshots/begin_ensure.txt | 16 +- test/yarp/snapshots/begin_rescue.txt | 70 +- test/yarp/snapshots/blocks.txt | 28 +- test/yarp/snapshots/boolean_operators.txt | 6 +- test/yarp/snapshots/case.txt | 12 +- test/yarp/snapshots/classes.txt | 6 +- test/yarp/snapshots/comments.txt | 18 +- test/yarp/snapshots/constants.txt | 28 +- test/yarp/snapshots/dash_heredocs.txt | 6 +- test/yarp/snapshots/defined.txt | 4 +- test/yarp/snapshots/hashes.txt | 26 +- test/yarp/snapshots/if.txt | 16 +- test/yarp/snapshots/lambda.txt | 4 +- test/yarp/snapshots/method_calls.txt | 1310 ++-- test/yarp/snapshots/methods.txt | 18 +- test/yarp/snapshots/modules.txt | 4 +- .../snapshots/non_alphanumeric_methods.txt | 2 +- test/yarp/snapshots/not.txt | 34 +- test/yarp/snapshots/numbers.txt | 40 +- test/yarp/snapshots/patterns.txt | 376 +- test/yarp/snapshots/procs.txt | 4 +- test/yarp/snapshots/ranges.txt | 6 +- test/yarp/snapshots/regex.txt | 4 +- test/yarp/snapshots/rescue.txt | 18 +- .../seattlerb/attrasgn_array_arg.txt | 2 +- .../seattlerb/attrasgn_array_lhs.txt | 4 +- .../attrasgn_primary_dot_constant.txt | 2 +- .../backticks_interpolation_line.txt | 2 +- test/yarp/snapshots/seattlerb/bdot2.txt | 4 +- test/yarp/snapshots/seattlerb/bdot3.txt | 4 +- test/yarp/snapshots/seattlerb/block_break.txt | 2 +- .../block_call_defn_call_block_call.txt | 4 +- .../block_call_dot_op2_brace_block.txt | 6 +- .../block_call_dot_op2_cmd_args_do_block.txt | 8 +- .../seattlerb/block_call_operation_colon.txt | 4 +- .../seattlerb/block_call_operation_dot.txt | 4 +- .../block_call_paren_call_block_call.txt | 4 +- .../block_command_operation_colon.txt | 4 +- test/yarp/snapshots/seattlerb/block_next.txt | 2 +- .../yarp/snapshots/seattlerb/block_return.txt | 2 +- test/yarp/snapshots/seattlerb/bug191.txt | 8 +- test/yarp/snapshots/seattlerb/bug290.txt | 2 +- test/yarp/snapshots/seattlerb/bug_187.txt | 2 +- .../yarp/snapshots/seattlerb/bug_args__19.txt | 2 +- test/yarp/snapshots/seattlerb/bug_comma.txt | 2 +- .../snapshots/seattlerb/bug_not_parens.txt | 2 +- .../seattlerb/bug_op_asgn_rescue.txt | 2 +- .../snapshots/seattlerb/call_arg_kwsplat.txt | 2 +- .../seattlerb/call_args_assoc_quoted.txt | 2 +- .../snapshots/seattlerb/call_args_command.txt | 4 +- .../seattlerb/call_bang_command_call.txt | 2 +- .../seattlerb/call_begin_call_block_call.txt | 2 +- .../seattlerb/call_block_arg_named.txt | 2 +- test/yarp/snapshots/seattlerb/call_env.txt | 2 +- .../snapshots/seattlerb/call_leading_dots.txt | 2 +- .../seattlerb/call_leading_dots_comment.txt | 2 +- .../seattlerb/call_trailing_dots.txt | 2 +- test/yarp/snapshots/seattlerb/case_in.txt | 2 +- .../snapshots/seattlerb/cond_unary_minus.txt | 18 +- .../seattlerb/defn_oneliner_noargs.txt | 2 +- .../defn_oneliner_noargs_parentheses.txt | 2 +- .../defs_as_arg_with_do_block_inside.txt | 2 +- .../seattlerb/defs_endless_command.txt | 2 +- .../seattlerb/defs_endless_command_rescue.txt | 2 +- test/yarp/snapshots/seattlerb/do_bug.txt | 2 +- .../yarp/snapshots/seattlerb/dot2_nil__26.txt | 2 +- .../yarp/snapshots/seattlerb/dot3_nil__26.txt | 2 +- test/yarp/snapshots/seattlerb/dstr_evstr.txt | 2 +- .../seattlerb/dstr_evstr_empty_end.txt | 2 +- .../snapshots/seattlerb/dsym_esc_to_sym.txt | 8 +- test/yarp/snapshots/seattlerb/dsym_to_sym.txt | 12 +- ...gin_why_wont_people_use_their_spacebar.txt | 4 +- test/yarp/snapshots/seattlerb/evstr_evstr.txt | 4 +- test/yarp/snapshots/seattlerb/evstr_str.txt | 2 +- .../snapshots/seattlerb/expr_not_bang.txt | 2 +- .../snapshots/seattlerb/flip2_env_lvar.txt | 8 +- .../snapshots/seattlerb/heredoc_nested.txt | 27 + ...squiggly_blank_line_plus_interpolation.txt | 2 +- .../seattlerb/i_fucking_hate_line_numbers.txt | 16 +- .../i_fucking_hate_line_numbers2.txt | 2 +- test/yarp/snapshots/seattlerb/index_0.txt | 4 +- .../snapshots/seattlerb/index_0_opasgn.txt | 4 +- test/yarp/snapshots/seattlerb/kill_me4.txt | 2 +- .../snapshots/seattlerb/label_vs_string.txt | 2 +- .../snapshots/seattlerb/lasgn_command.txt | 2 +- .../seattlerb/lasgn_middle_splat.txt | 6 +- .../seattlerb/masgn_anon_splat_arg.txt | 2 +- .../seattlerb/masgn_arg_colon_arg.txt | 4 +- .../snapshots/seattlerb/masgn_arg_ident.txt | 4 +- .../seattlerb/masgn_arg_splat_arg.txt | 2 +- .../yarp/snapshots/seattlerb/masgn_colon2.txt | 2 +- .../seattlerb/masgn_command_call.txt | 2 +- .../seattlerb/masgn_double_paren.txt | 2 +- test/yarp/snapshots/seattlerb/masgn_paren.txt | 2 +- .../snapshots/seattlerb/masgn_splat_arg.txt | 2 +- .../seattlerb/masgn_splat_arg_arg.txt | 2 +- .../seattlerb/masgn_var_star_var.txt | 2 +- .../seattlerb/messy_op_asgn_lineno.txt | 2 +- .../method_call_assoc_trailing_comma.txt | 2 +- .../seattlerb/method_call_trailing_comma.txt | 2 +- .../seattlerb/mlhs_back_anonsplat.txt | 2 +- .../snapshots/seattlerb/mlhs_back_splat.txt | 2 +- .../seattlerb/mlhs_front_anonsplat.txt | 2 +- .../snapshots/seattlerb/mlhs_front_splat.txt | 2 +- .../yarp/snapshots/seattlerb/mlhs_keyword.txt | 2 +- .../seattlerb/mlhs_mid_anonsplat.txt | 2 +- .../snapshots/seattlerb/mlhs_mid_splat.txt | 2 +- test/yarp/snapshots/seattlerb/mlhs_rescue.txt | 2 +- .../seattlerb/motherfuckin_leading_dots.txt | 2 +- .../seattlerb/op_asgn_command_call.txt | 2 +- .../seattlerb/op_asgn_index_command_call.txt | 2 +- ..._asgn_primary_colon_const_command_call.txt | 2 +- ..._primary_colon_identifier_command_call.txt | 2 +- .../op_asgn_val_dot_ident_command_call.txt | 2 +- .../seattlerb/parse_if_not_canonical.txt | 2 +- .../seattlerb/parse_if_not_noncanonical.txt | 2 +- .../parse_line_block_inline_comment.txt | 6 +- ..._block_inline_comment_leading_newlines.txt | 6 +- ...se_line_block_inline_multiline_comment.txt | 6 +- .../snapshots/seattlerb/parse_line_dot2.txt | 6 +- .../seattlerb/parse_line_dot2_open.txt | 4 +- .../snapshots/seattlerb/parse_line_dot3.txt | 6 +- .../seattlerb/parse_line_dot3_open.txt | 4 +- .../parse_line_evstr_after_break.txt | 2 +- .../seattlerb/parse_line_heredoc_evstr.txt | 2 +- .../parse_line_iter_call_no_parens.txt | 2 +- .../seattlerb/parse_line_iter_call_parens.txt | 2 +- .../seattlerb/parse_line_op_asgn.txt | 4 +- .../seattlerb/parse_line_postexe.txt | 2 +- .../snapshots/seattlerb/parse_line_preexe.txt | 2 +- .../snapshots/seattlerb/parse_line_rescue.txt | 6 +- .../snapshots/seattlerb/parse_line_to_ary.txt | 4 +- .../parse_line_trailing_newlines.txt | 4 +- .../snapshots/seattlerb/parse_pattern_019.txt | 12 +- .../snapshots/seattlerb/parse_pattern_044.txt | 2 +- .../seattlerb/parse_until_not_canonical.txt | 5 +- .../parse_until_not_noncanonical.txt | 5 +- .../seattlerb/parse_while_not_canonical.txt | 5 +- .../parse_while_not_noncanonical.txt | 5 +- .../snapshots/seattlerb/pipe_semicolon.txt | 2 +- test/yarp/snapshots/seattlerb/pipe_space.txt | 2 +- .../seattlerb/rescue_do_end_raised.txt | 2 +- .../seattlerb/rescue_do_end_rescued.txt | 2 +- .../snapshots/seattlerb/rescue_in_block.txt | 2 +- .../snapshots/seattlerb/rescue_parens.txt | 4 +- .../seattlerb/return_call_assocs.txt | 2 +- .../snapshots/seattlerb/safe_attrasgn.txt | 2 +- .../seattlerb/safe_attrasgn_constant.txt | 2 +- test/yarp/snapshots/seattlerb/safe_call.txt | 2 +- .../seattlerb/safe_call_after_newline.txt | 2 +- .../seattlerb/safe_call_dot_parens.txt | 2 +- .../snapshots/seattlerb/safe_call_newline.txt | 2 +- .../seattlerb/safe_call_operator.txt | 2 +- .../seattlerb/safe_call_rhs_newline.txt | 2 +- test/yarp/snapshots/seattlerb/safe_calls.txt | 2 +- .../yarp/snapshots/seattlerb/safe_op_asgn.txt | 2 +- .../snapshots/seattlerb/safe_op_asgn2.txt | 4 +- .../slashy_newlines_within_string.txt | 4 +- .../seattlerb/stabby_block_iter_call.txt | 2 +- .../str_double_double_escaped_newline.txt | 2 +- .../seattlerb/str_double_escaped_newline.txt | 2 +- .../seattlerb/str_double_newline.txt | 2 +- test/yarp/snapshots/seattlerb/str_evstr.txt | 2 +- .../snapshots/seattlerb/str_evstr_escape.txt | 2 +- .../seattlerb/str_heredoc_interp.txt | 2 +- .../seattlerb/str_interp_ternary_or_label.txt | 4 +- .../snapshots/seattlerb/str_pct_Q_nested.txt | 2 +- .../str_single_double_escaped_newline.txt | 2 +- .../seattlerb/str_single_escaped_newline.txt | 2 +- .../seattlerb/str_single_newline.txt | 2 +- test/yarp/snapshots/seattlerb/symbol_list.txt | 4 +- test/yarp/snapshots/seattlerb/thingy.txt | 4 +- .../yarp/snapshots/seattlerb/uminus_float.txt | 17 +- test/yarp/snapshots/seattlerb/unary_minus.txt | 2 +- test/yarp/snapshots/seattlerb/unary_plus.txt | 2 +- test/yarp/snapshots/seattlerb/unary_tilde.txt | 2 +- test/yarp/snapshots/seattlerb/when_splat.txt | 4 +- test/yarp/snapshots/seattlerb/wtf_7.txt | 4 +- test/yarp/snapshots/seattlerb/wtf_8.txt | 8 +- .../snapshots/seattlerb/yield_call_assocs.txt | 2 +- .../zomg_sometimes_i_hate_this_project.txt | 4 +- test/yarp/snapshots/strings.txt | 6 +- test/yarp/snapshots/symbols.txt | 2 +- test/yarp/snapshots/ternary_operator.txt | 53 +- .../unparser/corpus/literal/assignment.txt | 18 +- .../unparser/corpus/literal/block.txt | 70 +- .../unparser/corpus/literal/case.txt | 52 +- .../unparser/corpus/literal/class.txt | 6 +- .../snapshots/unparser/corpus/literal/def.txt | 50 +- .../unparser/corpus/literal/defs.txt | 22 +- .../unparser/corpus/literal/dstr.txt | 6 +- .../unparser/corpus/literal/flipflop.txt | 20 +- .../snapshots/unparser/corpus/literal/for.txt | 16 +- .../unparser/corpus/literal/hookexe.txt | 6 +- .../snapshots/unparser/corpus/literal/if.txt | 12 +- .../unparser/corpus/literal/kwbegin.txt | 30 +- .../unparser/corpus/literal/literal.txt | 80 +- .../unparser/corpus/literal/opasgn.txt | 26 +- .../unparser/corpus/literal/pattern.txt | 8 +- .../unparser/corpus/literal/pragma.txt | 2 +- .../unparser/corpus/literal/rescue.txt | 12 +- .../unparser/corpus/literal/send.txt | 172 +- .../unparser/corpus/literal/since/27.txt | 4 +- .../unparser/corpus/literal/super.txt | 28 +- .../unparser/corpus/literal/unary.txt | 12 +- .../unparser/corpus/literal/variables.txt | 2 +- .../unparser/corpus/literal/while.txt | 89 +- .../unparser/corpus/literal/yield.txt | 6 +- .../unparser/corpus/semantic/and.txt | 48 +- .../unparser/corpus/semantic/block.txt | 2 +- .../unparser/corpus/semantic/def.txt | 6 +- .../unparser/corpus/semantic/kwbegin.txt | 20 +- .../unparser/corpus/semantic/literal.txt | 38 +- .../unparser/corpus/semantic/send.txt | 14 +- .../unparser/corpus/semantic/while.txt | 39 +- test/yarp/snapshots/until.txt | 18 +- test/yarp/snapshots/variables.txt | 18 +- test/yarp/snapshots/while.txt | 30 +- ...iuous_quoted_label_in_ternary_operator.txt | 4 +- test/yarp/snapshots/whitequark/and.txt | 8 +- test/yarp/snapshots/whitequark/and_asgn.txt | 4 +- .../snapshots/whitequark/and_or_masgn.txt | 8 +- test/yarp/snapshots/whitequark/args.txt | 12 +- .../snapshots/whitequark/args_args_assocs.txt | 6 +- .../whitequark/args_args_assocs_comma.txt | 4 +- .../snapshots/whitequark/args_args_comma.txt | 4 +- .../snapshots/whitequark/args_args_star.txt | 10 +- .../yarp/snapshots/whitequark/args_assocs.txt | 4 +- .../whitequark/args_assocs_comma.txt | 2 +- .../whitequark/args_assocs_legacy.txt | 4 +- .../snapshots/whitequark/args_block_pass.txt | 2 +- test/yarp/snapshots/whitequark/args_cmd.txt | 2 +- test/yarp/snapshots/whitequark/args_star.txt | 6 +- .../yarp/snapshots/whitequark/array_splat.txt | 6 +- .../whitequark/array_symbols_interp.txt | 4 +- .../whitequark/array_words_interp.txt | 4 +- test/yarp/snapshots/whitequark/asgn_mrhs.txt | 16 +- test/yarp/snapshots/whitequark/bang.txt | 2 +- test/yarp/snapshots/whitequark/bang_cmd.txt | 2 +- .../beginless_erange_after_newline.txt | 2 +- .../beginless_irange_after_newline.txt | 2 +- test/yarp/snapshots/whitequark/break.txt | 4 +- .../yarp/snapshots/whitequark/break_block.txt | 2 +- test/yarp/snapshots/whitequark/bug_452.txt | 2 +- test/yarp/snapshots/whitequark/bug_cmdarg.txt | 2 +- .../whitequark/bug_lambda_leakage.txt | 2 +- .../whitequark/bug_while_not_parens_do.txt | 3 +- test/yarp/snapshots/whitequark/case_cond.txt | 2 +- .../snapshots/whitequark/case_cond_else.txt | 2 +- test/yarp/snapshots/whitequark/case_expr.txt | 4 +- .../snapshots/whitequark/case_expr_else.txt | 6 +- .../class_definition_in_while_cond.txt | 12 +- .../comments_before_leading_dot__27.txt | 8 +- test/yarp/snapshots/whitequark/cond_begin.txt | 4 +- .../snapshots/whitequark/cond_begin_masgn.txt | 4 +- .../snapshots/whitequark/cond_eflipflop.txt | 16 +- .../snapshots/whitequark/cond_iflipflop.txt | 16 +- .../whitequark/dedenting_heredoc.txt | 4 +- test/yarp/snapshots/whitequark/defined.txt | 4 +- test/yarp/snapshots/whitequark/defs.txt | 2 +- .../whitequark/endless_comparison_method.txt | 12 +- .../snapshots/whitequark/endless_method.txt | 4 +- .../endless_method_command_syntax.txt | 6 +- test/yarp/snapshots/whitequark/ensure.txt | 4 +- test/yarp/snapshots/whitequark/float.txt | 15 +- test/yarp/snapshots/whitequark/for.txt | 4 +- test/yarp/snapshots/whitequark/for_mlhs.txt | 2 +- .../snapshots/whitequark/hash_kwsplat.txt | 2 +- .../snapshots/whitequark/hash_label_end.txt | 2 +- test/yarp/snapshots/whitequark/if.txt | 8 +- test/yarp/snapshots/whitequark/if_else.txt | 12 +- test/yarp/snapshots/whitequark/if_elsif.txt | 6 +- .../snapshots/whitequark/if_masgn__24.txt | 2 +- test/yarp/snapshots/whitequark/if_mod.txt | 4 +- test/yarp/snapshots/whitequark/if_nl_then.txt | 4 +- .../if_while_after_class__since_32.txt | 6 +- test/yarp/snapshots/whitequark/int.txt | 14 +- .../snapshots/whitequark/interp_digit_var.txt | 12 +- .../lparenarg_after_lvar__since_25.txt | 28 +- test/yarp/snapshots/whitequark/lvar.txt | 2 +- .../snapshots/whitequark/masgn_nested.txt | 4 +- .../yarp/snapshots/whitequark/masgn_splat.txt | 40 +- .../method_definition_in_while_cond.txt | 12 +- .../whitequark/newline_in_hash_argument.txt | 6 +- test/yarp/snapshots/whitequark/next.txt | 4 +- test/yarp/snapshots/whitequark/next_block.txt | 2 +- test/yarp/snapshots/whitequark/not.txt | 4 +- test/yarp/snapshots/whitequark/not_cmd.txt | 2 +- .../snapshots/whitequark/not_masgn__24.txt | 2 +- .../whitequark/numbered_args_after_27.txt | 16 +- .../whitequark/numparam_outside_block.txt | 12 +- test/yarp/snapshots/whitequark/op_asgn.txt | 6 +- .../yarp/snapshots/whitequark/op_asgn_cmd.txt | 16 +- .../snapshots/whitequark/op_asgn_index.txt | 2 +- .../whitequark/op_asgn_index_cmd.txt | 4 +- test/yarp/snapshots/whitequark/or.txt | 8 +- test/yarp/snapshots/whitequark/or_asgn.txt | 4 +- .../snapshots/whitequark/parser_bug_525.txt | 2 +- .../snapshots/whitequark/parser_bug_604.txt | 4 +- ...ser_slash_slash_n_escaping_in_literals.txt | 6 +- .../snapshots/whitequark/regex_interp.txt | 2 +- .../snapshots/whitequark/resbody_list.txt | 4 +- .../whitequark/resbody_list_mrhs.txt | 6 +- .../snapshots/whitequark/resbody_list_var.txt | 6 +- .../yarp/snapshots/whitequark/resbody_var.txt | 8 +- test/yarp/snapshots/whitequark/rescue.txt | 4 +- .../yarp/snapshots/whitequark/rescue_else.txt | 6 +- .../whitequark/rescue_else_ensure.txt | 8 +- .../snapshots/whitequark/rescue_ensure.txt | 6 +- test/yarp/snapshots/whitequark/rescue_mod.txt | 4 +- .../snapshots/whitequark/rescue_mod_asgn.txt | 4 +- .../snapshots/whitequark/rescue_mod_masgn.txt | 2 +- .../whitequark/rescue_mod_op_assign.txt | 4 +- .../whitequark/rescue_without_begin_end.txt | 4 +- test/yarp/snapshots/whitequark/return.txt | 4 +- .../snapshots/whitequark/return_block.txt | 2 +- .../snapshots/whitequark/ruby_bug_11873.txt | 24 +- .../snapshots/whitequark/ruby_bug_11873_a.txt | 40 +- .../snapshots/whitequark/ruby_bug_11873_b.txt | 6 +- .../snapshots/whitequark/ruby_bug_12402.txt | 28 +- .../snapshots/whitequark/ruby_bug_12686.txt | 2 +- .../snapshots/whitequark/ruby_bug_13547.txt | 2 +- .../snapshots/whitequark/ruby_bug_14690.txt | 2 +- .../snapshots/whitequark/ruby_bug_15789.txt | 4 +- test/yarp/snapshots/whitequark/sclass.txt | 2 +- .../snapshots/whitequark/send_attr_asgn.txt | 8 +- .../whitequark/send_attr_asgn_conditional.txt | 2 +- .../snapshots/whitequark/send_binary_op.txt | 42 +- .../whitequark/send_block_chain_cmd.txt | 20 +- .../whitequark/send_block_conditional.txt | 2 +- test/yarp/snapshots/whitequark/send_call.txt | 4 +- .../snapshots/whitequark/send_conditional.txt | 2 +- test/yarp/snapshots/whitequark/send_index.txt | 2 +- .../snapshots/whitequark/send_index_asgn.txt | 2 +- .../whitequark/send_index_asgn_legacy.txt | 2 +- .../snapshots/whitequark/send_index_cmd.txt | 4 +- .../whitequark/send_index_legacy.txt | 2 +- .../whitequark/send_op_asgn_conditional.txt | 2 +- test/yarp/snapshots/whitequark/send_plain.txt | 6 +- .../snapshots/whitequark/send_plain_cmd.txt | 16 +- test/yarp/snapshots/whitequark/send_self.txt | 2 +- .../snapshots/whitequark/send_unary_op.txt | 6 +- .../whitequark/space_args_arg_block.txt | 8 +- .../snapshots/whitequark/space_args_cmd.txt | 2 +- .../snapshots/whitequark/string_interp.txt | 2 +- test/yarp/snapshots/whitequark/super.txt | 4 +- .../yarp/snapshots/whitequark/super_block.txt | 4 +- .../snapshots/whitequark/symbol_interp.txt | 2 +- test/yarp/snapshots/whitequark/ternary.txt | 2 +- .../whitequark/ternary_ambiguous_symbol.txt | 2 +- test/yarp/snapshots/whitequark/unless.txt | 8 +- .../yarp/snapshots/whitequark/unless_else.txt | 12 +- test/yarp/snapshots/whitequark/unless_mod.txt | 4 +- test/yarp/snapshots/whitequark/until.txt | 14 +- test/yarp/snapshots/whitequark/until_mod.txt | 7 +- test/yarp/snapshots/whitequark/until_post.txt | 7 +- test/yarp/snapshots/whitequark/when_multi.txt | 4 +- test/yarp/snapshots/whitequark/when_splat.txt | 8 +- test/yarp/snapshots/whitequark/when_then.txt | 4 +- test/yarp/snapshots/whitequark/while.txt | 14 +- test/yarp/snapshots/whitequark/while_mod.txt | 7 +- test/yarp/snapshots/whitequark/while_post.txt | 7 +- .../snapshots/whitequark/xstring_interp.txt | 2 +- test/yarp/snapshots/whitequark/yield.txt | 4 +- test/yarp/snapshots/xstring.txt | 2 +- test/yarp/unescape_test.rb | 2 + test/yarp/yarp_test_helper.rb | 2 + tool/sync_default_gems.rb | 2 +- yarp/api_node.c | 5499 ++++++++++------- yarp/ast.h | 264 +- yarp/defines.h | 15 - yarp/enc/yp_ascii.c | 65 - yarp/enc/yp_big5.c | 32 +- yarp/enc/yp_encoding.h | 37 +- yarp/enc/yp_euc_jp.c | 37 +- yarp/enc/yp_gbk.c | 43 +- yarp/enc/yp_iso_8859_1.c | 50 - yarp/enc/yp_iso_8859_10.c | 50 - yarp/enc/yp_iso_8859_11.c | 50 - yarp/enc/yp_iso_8859_13.c | 50 - yarp/enc/yp_iso_8859_14.c | 50 - yarp/enc/yp_iso_8859_15.c | 50 - yarp/enc/yp_iso_8859_16.c | 50 - yarp/enc/yp_iso_8859_2.c | 50 - yarp/enc/yp_iso_8859_3.c | 50 - yarp/enc/yp_iso_8859_4.c | 50 - yarp/enc/yp_iso_8859_5.c | 50 - yarp/enc/yp_iso_8859_6.c | 50 - yarp/enc/yp_iso_8859_7.c | 50 - yarp/enc/yp_iso_8859_8.c | 50 - yarp/enc/yp_iso_8859_9.c | 50 - yarp/enc/yp_koi8_r.c | 56 - yarp/enc/yp_shared.c | 9 - yarp/enc/yp_shift_jis.c | 31 +- yarp/enc/yp_tables.c | 509 ++ yarp/enc/yp_unicode.c | 58 +- yarp/enc/yp_windows_1251.c | 50 - yarp/enc/yp_windows_1252.c | 50 - yarp/enc/yp_windows_31j.c | 31 +- yarp/extension.c | 57 +- yarp/extension.h | 2 +- yarp/node.c | 50 +- yarp/prettyprint.c | 227 +- yarp/serialize.c | 289 +- yarp/token_type.c | 18 +- yarp/unescape.c | 4 +- yarp/util/yp_buffer.h | 1 + yarp/util/yp_list.c | 13 + yarp/util/yp_list.h | 3 + yarp/util/yp_memchr.c | 6 +- yarp/util/yp_memchr.h | 4 +- yarp/util/yp_string.c | 31 +- yarp/util/yp_string.h | 6 +- yarp/util/yp_strpbrk.c | 2 +- yarp/version.h | 5 +- yarp/yarp.c | 622 +- yarp/yarp.h | 6 +- 437 files changed, 8848 insertions(+), 6465 deletions(-) create mode 100644 lib/yarp/ffi.rb delete mode 100644 test/newline_test.rb create mode 100644 test/yarp/locals_test.rb create mode 100644 test/yarp/newline_test.rb create mode 100644 test/yarp/parse_serialize_test.rb rename test/{ => yarp}/ruby_api_test.rb (100%) create mode 100644 test/yarp/snapshots/seattlerb/heredoc_nested.txt delete mode 100644 yarp/enc/yp_ascii.c delete mode 100644 yarp/enc/yp_iso_8859_1.c delete mode 100644 yarp/enc/yp_iso_8859_10.c delete mode 100644 yarp/enc/yp_iso_8859_11.c delete mode 100644 yarp/enc/yp_iso_8859_13.c delete mode 100644 yarp/enc/yp_iso_8859_14.c delete mode 100644 yarp/enc/yp_iso_8859_15.c delete mode 100644 yarp/enc/yp_iso_8859_16.c delete mode 100644 yarp/enc/yp_iso_8859_2.c delete mode 100644 yarp/enc/yp_iso_8859_3.c delete mode 100644 yarp/enc/yp_iso_8859_4.c delete mode 100644 yarp/enc/yp_iso_8859_5.c delete mode 100644 yarp/enc/yp_iso_8859_6.c delete mode 100644 yarp/enc/yp_iso_8859_7.c delete mode 100644 yarp/enc/yp_iso_8859_8.c delete mode 100644 yarp/enc/yp_iso_8859_9.c delete mode 100644 yarp/enc/yp_koi8_r.c delete mode 100644 yarp/enc/yp_shared.c create mode 100644 yarp/enc/yp_tables.c delete mode 100644 yarp/enc/yp_windows_1251.c delete mode 100644 yarp/enc/yp_windows_1252.c diff --git a/lib/yarp.rb b/lib/yarp.rb index 79a0aaad5bd17e..30f361df074163 100644 --- a/lib/yarp.rb +++ b/lib/yarp.rb @@ -7,7 +7,7 @@ module YARP class Source attr_reader :source, :offsets - def initialize(source, offsets) + def initialize(source, offsets = compute_offsets(source)) @source = source @offsets = offsets end @@ -23,6 +23,14 @@ def line(value) def column(value) value - offsets[line(value) - 1] end + + private + + def compute_offsets(code) + offsets = [0] + code.b.scan("\n") { offsets << $~.end(0) } + offsets + end end # This represents a location in the source. @@ -101,6 +109,8 @@ def self.null # This represents a comment that was encountered during parsing. class Comment + TYPES = [:inline, :embdoc, :__END__] + attr_reader :type, :location def initialize(type, location) @@ -141,6 +151,27 @@ def deconstruct_keys(keys) 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 + # continues walking the tree, see the Visitor class. + class BasicVisitor + def visit(node) + node&.accept(self) + end + + def visit_all(nodes) + nodes.map { |node| visit(node) } + end + + def visit_child_nodes(node) + visit_all(node.child_nodes) + end + end + + class Visitor < BasicVisitor + end + # This represents the result of a call to ::parse or ::parse_file. It contains # the AST, any comments that were encounters, and any errors that were # encountered. @@ -166,6 +197,45 @@ def success? def failure? !success? end + + # Keep in sync with Java MarkNewlinesVisitor + class MarkNewlinesVisitor < YARP::Visitor + def initialize(newline_marked) + @newline_marked = newline_marked + end + + def visit_block_node(node) + old_newline_marked = @newline_marked + @newline_marked = Array.new(old_newline_marked.size, false) + begin + super(node) + ensure + @newline_marked = old_newline_marked + end + end + alias_method :visit_lambda_node, :visit_block_node + + def visit_if_node(node) + node.set_newline_flag(@newline_marked) + super(node) + end + alias_method :visit_unless_node, :visit_if_node + + def visit_statements_node(node) + node.body.each do |child| + child.set_newline_flag(@newline_marked) + end + super(node) + end + end + private_constant :MarkNewlinesVisitor + + def mark_newlines + newline_marked = Array.new(1 + @source.offsets.size, false) + visitor = MarkNewlinesVisitor.new(newline_marked) + value.accept(visitor) + value + end end # This represents a token from the Ruby source. @@ -207,10 +277,28 @@ def ==(other) class Node attr_reader :location + def newline? + @newline ? true : false + end + + def set_newline_flag(newline_marked) + line = location.start_line + unless newline_marked[line] + newline_marked[line] = true + @newline = true + end + end + + # Slice the location of the node from the source. + def slice + location.slice + end + def pretty_print(q) q.group do q.text(self.class.name.split("::").last) location.pretty_print(q) + q.text("[Li:#{location.start_line}]") if newline? q.text("(") q.nest(2) do deconstructed = deconstruct_keys([]) @@ -233,9 +321,153 @@ def self.load(source, serialized) # This module is used for testing and debugging and is not meant to be used by # consumers of this library. module Debug + class ISeq + attr_reader :parts + + def initialize(parts) + @parts = parts + end + + def type + parts[0] + end + + def local_table + parts[10] + end + + def instructions + parts[13] + end + + def each_child + instructions.each do |instruction| + # Only look at arrays. Other instructions are line numbers or + # tracepoint events. + next unless instruction.is_a?(Array) + + instruction.each do |opnd| + # Only look at arrays. Other operands are literals. + next unless opnd.is_a?(Array) + + # Only look at instruction sequences. Other operands are literals. + next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat" + + yield ISeq.new(opnd) + end + end + end + end + + # For the given source, compiles with CRuby and returns a list of all of the + # sets of local variables that were encountered. + def self.cruby_locals(source) + verbose = $VERBOSE + $VERBOSE = nil + + begin + locals = [] + stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)] + + while (iseq = stack.pop) + if iseq.type != :once + names = iseq.local_table + + # CRuby will push on a special local variable when there are keyword + # arguments. We get rid of that here. + names = names.grep_v(Integer) + + # TODO: We don't support numbered local variables yet, so we get rid + # of those here. + names = names.grep_v(/^_\d$/) + + # Now push them onto the list of locals. + locals << names + end + + iseq.each_child { |child| stack << child } + end + + locals + ensure + $VERBOSE = verbose + end + end + + # For the given source, parses with YARP and returns a list of all of the + # sets of local variables that were encountered. + def self.yarp_locals(source) + locals = [] + stack = [YARP.parse(source).value] + + while (node = stack.pop) + case node + when BlockNode, DefNode, LambdaNode + names = node.locals + + params = node.parameters + params = params&.parameters unless node.is_a?(DefNode) + + # YARP places parameters in the same order that they appear in the + # source. CRuby places them in the order that they need to appear + # according to their own internal calling convention. We mimic that + # order here so that we can compare properly. + if params + sorted = [ + *params.requireds.grep(RequiredParameterNode).map(&:constant_id), + *params.optionals.map(&:constant_id), + *((params.rest.name ? params.rest.name.to_sym : :*) if params.rest && params.rest.operator != ","), + *params.posts.grep(RequiredParameterNode).map(&:constant_id), + *params.keywords.reject(&:value).map { |param| param.name.chomp(":").to_sym }, + *params.keywords.select(&:value).map { |param| param.name.chomp(":").to_sym } + ] + + # TODO: When we get a ... parameter, we should be pushing * and & + # onto the local list. We don't do that yet, so we need to add them + # in here. + if params.keyword_rest.is_a?(ForwardingParameterNode) + sorted.push(:*, :&, :"...") + end + + # Recurse down the parameter tree to find any destructured + # parameters and add them after the other parameters. + param_stack = params.requireds.concat(params.posts).grep(RequiredDestructuredParameterNode).reverse + while (param = param_stack.pop) + case param + when RequiredDestructuredParameterNode + param_stack.concat(param.parameters.reverse) + when RequiredParameterNode + sorted << param.constant_id + when SplatNode + sorted << param.expression.constant_id if param.expression + end + end + + names = sorted.concat(names - sorted) + end + + locals << names + when ClassNode, ModuleNode, ProgramNode, SingletonClassNode + locals << node.locals + when ForNode + locals << [] + when PostExecutionNode + locals.push([], []) + end + + stack.concat(node.child_nodes.compact) + end + + locals + end + def self.newlines(source) YARP.parse(source).source.offsets end + + def self.parse_serialize_file(filepath) + parse_serialize_file_metadata(filepath, [filepath.bytesize, filepath.b, 0].pack("LA*L")) + end end # Marking this as private so that consumers don't see it. It makes it a little @@ -250,4 +482,8 @@ def self.newlines(source) require_relative "yarp/serialize" require_relative "yarp/pack" -require "yarp/yarp" +if RUBY_ENGINE == "ruby" and !ENV["YARP_FFI_BACKEND"] + require "yarp/yarp" +else + require "yarp/ffi" +end diff --git a/lib/yarp/ffi.rb b/lib/yarp/ffi.rb new file mode 100644 index 00000000000000..293958dda6d51f --- /dev/null +++ b/lib/yarp/ffi.rb @@ -0,0 +1,211 @@ +# frozen_string_literal: true + +# This file is responsible for mirroring the API provided by the C extension by +# using FFI to call into the shared library. + +require "rbconfig" +require "ffi" + +module YARP + BACKEND = :FFI + + module LibRubyParser + extend FFI::Library + + # Define the library that we will be pulling functions from. Note that this + # must align with the build shared library from make/rake. + ffi_lib File.expand_path("../../build/librubyparser.#{RbConfig::CONFIG["SOEXT"]}", __dir__) + + # Convert a native C type declaration into a symbol that FFI understands. + # For example: + # + # const char * -> :pointer + # bool -> :bool + # size_t -> :size_t + # void -> :void + # + def self.resolve_type(type) + type = type.strip.delete_prefix("const ") + type.end_with?("*") ? :pointer : type.to_sym + end + + # Read through the given header file and find the declaration of each of the + # given functions. For each one, define a function with the same name and + # signature as the C function. + def self.load_exported_functions_from(header, *functions) + File.foreach(File.expand_path("../../include/#{header}", __dir__)) do |line| + # We only want to attempt to load exported functions. + next unless line.start_with?("YP_EXPORTED_FUNCTION ") + + # We only want to load the functions that we are interested in. + next unless functions.any? { |function| line.include?(function) } + + # Parse the function declaration. + unless /^YP_EXPORTED_FUNCTION (?.+) (?\w+)\((?.+)\);$/ =~ line + raise "Could not parse #{line}" + end + + # Delete the function from the list of functions we are looking for to + # mark it as having been found. + functions.delete(name) + + # Split up the argument types into an array, ensure we handle the case + # where there are no arguments (by explicit void). + arg_types = arg_types.split(",").map(&:strip) + arg_types = [] if arg_types == %w[void] + + # Resolve the type of the argument by dropping the name of the argument + # first if it is present. + arg_types.map! { |type| resolve_type(type.sub(/\w+$/, "")) } + + # Attach the function using the FFI library. + attach_function name, arg_types, resolve_type(return_type) + end + + # If we didn't find all of the functions, raise an error. + raise "Could not find functions #{functions.inspect}" unless functions.empty? + end + + load_exported_functions_from( + "yarp.h", + "yp_version", + "yp_parse_serialize", + "yp_lex_serialize" + ) + + load_exported_functions_from( + "yarp/util/yp_buffer.h", + "yp_buffer_init", + "yp_buffer_free" + ) + + load_exported_functions_from( + "yarp/util/yp_string.h", + "yp_string_mapped_init", + "yp_string_free", + "yp_string_source", + "yp_string_length", + "yp_string_sizeof" + ) + + # This object represents a yp_buffer_t. Its structure must be kept in sync + # with the C version. + class YPBuffer < FFI::Struct + layout value: :pointer, length: :size_t, capacity: :size_t + + # Read the contents of the buffer into a String object and return it. + def to_ruby_string + self[:value].read_string(self[:length]) + end + end + + # Initialize a new buffer and yield it to the block. The buffer will be + # automatically freed when the block returns. + def self.with_buffer(&block) + buffer = YPBuffer.new + + begin + raise unless yp_buffer_init(buffer) + yield buffer + ensure + yp_buffer_free(buffer) + buffer.pointer.free + end + end + + # This object represents a yp_string_t. We only use it as an opaque pointer, + # so it doesn't have to be an FFI::Struct. + class YPString + attr_reader :pointer + + def initialize(pointer) + @pointer = pointer + end + + def source + LibRubyParser.yp_string_source(pointer) + end + + def length + LibRubyParser.yp_string_length(pointer) + end + + def read + source.read_string(length) + end + end + + # This is the size of a yp_string_t. It is returned by the yp_string_sizeof + # function which we call once to ensure we have sufficient space for the + # yp_string_t FFI pointer. + SIZEOF_YP_STRING = yp_string_sizeof + + # Yields a yp_string_t pointer to the given block. + def self.with_string(filepath, &block) + string = FFI::MemoryPointer.new(SIZEOF_YP_STRING) + + begin + raise unless yp_string_mapped_init(string, filepath) + yield YPString.new(string) + ensure + yp_string_free(string) + string.free + end + end + end + + # Mark the LibRubyParser module as private as it should only be called through + # the YARP module. + private_constant :LibRubyParser + + # The version constant is set by reading the result of calling yp_version. + VERSION = LibRubyParser.yp_version.read_string + + def self.dump_internal(source, source_size, filepath) + LibRubyParser.with_buffer do |buffer| + metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath + LibRubyParser.yp_parse_serialize(source, source_size, buffer, metadata) + buffer.to_ruby_string + end + end + private_class_method :dump_internal + + # Mirror the YARP.dump API by using the serialization API. + def self.dump(code, filepath = nil) + dump_internal(code, code.bytesize, filepath) + end + + # Mirror the YARP.dump_file API by using the serialization API. + def self.dump_file(filepath) + LibRubyParser.with_string(filepath) do |string| + dump_internal(string.source, string.length, filepath) + end + end + + # Mirror the YARP.lex API by using the serialization API. + def self.lex(code, filepath = nil) + LibRubyParser.with_buffer do |buffer| + LibRubyParser.yp_lex_serialize(code, code.bytesize, filepath, buffer) + + source = Source.new(code) + Serialize.load_tokens(source, buffer.to_ruby_string) + end + end + + # Mirror the YARP.lex_file API by using the serialization API. + def self.lex_file(filepath) + LibRubyParser.with_string(filepath) { |string| lex(string.read, filepath) } + end + + # Mirror the YARP.parse API by using the serialization API. + def self.parse(code, filepath = nil) + YARP.load(code, dump(code, filepath)) + end + + # Mirror the YARP.parse_file API by using the serialization API. This uses + # native strings instead of Ruby strings because it allows us to use mmap when + # it is available. + def self.parse_file(filepath) + LibRubyParser.with_string(filepath) { |string| parse(string.read, filepath) } + end +end diff --git a/lib/yarp/lex_compat.rb b/lib/yarp/lex_compat.rb index 984aa8185eb273..7e1d9f36573c78 100644 --- a/lib/yarp/lex_compat.rb +++ b/lib/yarp/lex_compat.rb @@ -166,6 +166,7 @@ class LexCompat STRING_END: :on_tstring_end, SYMBOL_BEGIN: :on_symbeg, TILDE: :on_op, + UAMPERSAND: :on_op, UCOLON_COLON: :on_op, UDOT_DOT: :on_op, UDOT_DOT_DOT: :on_op, @@ -646,19 +647,34 @@ def result # can shuffle around the token to match Ripper's output. case state 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 + # 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) 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 case event when :on_heredoc_beg + # If we receive a heredoc declaration while lexing the body of a + # 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)] 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 + # but need to wait for the next newline to push it into the token + # stream. state = :heredoc_closed end when :heredoc_closed @@ -733,8 +749,7 @@ def self.lex_ripper(source) when :on_sp # skip when :on_tstring_content - if previous[1] == :on_tstring_content && - (token[2].start_with?("\#$") || token[2].start_with?("\#@")) + if previous[1] == :on_tstring_content && (token[2].start_with?("\#$") || token[2].start_with?("\#@")) previous[2] << token[2] else results << token diff --git a/lib/yarp/node.rb b/lib/yarp/node.rb index e3d347b05c4517..b01d9ed24b4d5b 100644 --- a/lib/yarp/node.rb +++ b/lib/yarp/node.rb @@ -462,6 +462,10 @@ def accept(visitor) visitor.visit_begin_node(self) end + def set_newline_flag(newline_marked) + # Never mark BeginNode with a newline flag, mark children instead + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [statements, rescue_clause, else_clause, ensure_clause] @@ -834,6 +838,16 @@ def opening def closing closing_loc&.slice end + + # def safe_navigation?: () -> bool + def safe_navigation? + flags.anybits?(CallNodeFlags::SAFE_NAVIGATION) + end + + # def variable_call?: () -> bool + def variable_call? + flags.anybits?(CallNodeFlags::VARIABLE_CALL) + end end # Represents the use of the `&&=` operator on a call. @@ -1724,13 +1738,16 @@ def deconstruct_keys(keys) end end - # Represents writing to a constant. + # Represents writing to a constant path. # - # Foo = 1 - # ^^^^^^^ + # ::Foo = 1 + # ^^^^^^^^^ # # Foo::Bar = 1 # ^^^^^^^^^^^^ + # + # ::Foo::Bar = 1 + # ^^^^^^^^^^^^^^ class ConstantPathWriteNode < Node # attr_reader target: Node attr_reader :target @@ -1802,6 +1819,57 @@ def deconstruct_keys(keys) end end + # Represents writing to a constant. + # + # Foo = 1 + # ^^^^^^^ + class ConstantWriteNode < Node + # attr_reader name_loc: Location + attr_reader :name_loc + + # attr_reader value: Node? + attr_reader :value + + # attr_reader operator_loc: Location? + attr_reader :operator_loc + + # def initialize: (name_loc: Location, value: Node?, operator_loc: Location?, location: Location) -> void + def initialize(name_loc, value, operator_loc, location) + @name_loc = name_loc + @value = value + @operator_loc = operator_loc + @location = location + end + + # def accept: (visitor: Visitor) -> void + def accept(visitor) + visitor.visit_constant_write_node(self) + end + + # def child_nodes: () -> Array[nil | Node] + def child_nodes + [value] + end + + # def deconstruct: () -> Array[nil | Node] + alias deconstruct child_nodes + + # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location] + def deconstruct_keys(keys) + { name_loc: name_loc, value: value, operator_loc: operator_loc, location: location } + end + + # def name: () -> String + def name + name_loc.slice + end + + # def operator: () -> String? + def operator + operator_loc&.slice + end + end + # Represents a method definition. # # def method @@ -2268,6 +2336,61 @@ def closing end end + # Represents the use of the `..` or `...` operators to create flip flops. + # + # baz if foo .. bar + # ^^^^^^^^^^ + class FlipFlopNode < Node + # attr_reader left: Node? + attr_reader :left + + # attr_reader right: Node? + attr_reader :right + + # attr_reader operator_loc: Location + attr_reader :operator_loc + + # attr_reader flags: Integer + attr_reader :flags + + # def initialize: (left: Node?, right: Node?, operator_loc: Location, flags: Integer, location: Location) -> void + def initialize(left, right, operator_loc, flags, location) + @left = left + @right = right + @operator_loc = operator_loc + @flags = flags + @location = location + end + + # def accept: (visitor: Visitor) -> void + def accept(visitor) + visitor.visit_flip_flop_node(self) + end + + # def child_nodes: () -> Array[nil | Node] + def child_nodes + [left, right] + end + + # def deconstruct: () -> Array[nil | Node] + alias deconstruct child_nodes + + # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location] + def deconstruct_keys(keys) + { left: left, right: right, operator_loc: operator_loc, flags: flags, location: location } + end + + # def operator: () -> String + def operator + operator_loc.slice + end + + # def exclude_end?: () -> bool + def exclude_end? + flags.anybits?(RangeFlags::EXCLUDE_END) + end + end + # Represents a floating point number literal. # # 1.0 @@ -2851,6 +2974,10 @@ def accept(visitor) visitor.visit_if_node(self) end + def set_newline_flag(newline_marked) + predicate.set_newline_flag(newline_marked) + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [predicate, statements, consequent] @@ -3255,6 +3382,11 @@ def accept(visitor) visitor.visit_interpolated_regular_expression_node(self) end + def set_newline_flag(newline_marked) + first = parts.first + first.set_newline_flag(newline_marked) if first + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [*parts] @@ -3277,6 +3409,46 @@ def opening def closing closing_loc.slice end + + # def ignore_case?: () -> bool + def ignore_case? + flags.anybits?(RegularExpressionFlags::IGNORE_CASE) + end + + # def multi_line?: () -> bool + def multi_line? + flags.anybits?(RegularExpressionFlags::MULTI_LINE) + end + + # def extended?: () -> bool + def extended? + flags.anybits?(RegularExpressionFlags::EXTENDED) + end + + # def euc_jp?: () -> bool + def euc_jp? + flags.anybits?(RegularExpressionFlags::EUC_JP) + end + + # def ascii_8bit?: () -> bool + def ascii_8bit? + flags.anybits?(RegularExpressionFlags::ASCII_8BIT) + end + + # def windows_31j?: () -> bool + def windows_31j? + flags.anybits?(RegularExpressionFlags::WINDOWS_31J) + end + + # def utf_8?: () -> bool + def utf_8? + flags.anybits?(RegularExpressionFlags::UTF_8) + end + + # def once?: () -> bool + def once? + flags.anybits?(RegularExpressionFlags::ONCE) + end end # Represents a string literal that contains interpolation. @@ -3306,6 +3478,11 @@ def accept(visitor) visitor.visit_interpolated_string_node(self) end + def set_newline_flag(newline_marked) + first = parts.first + first.set_newline_flag(newline_marked) if first + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [*parts] @@ -3357,6 +3534,11 @@ def accept(visitor) visitor.visit_interpolated_symbol_node(self) end + def set_newline_flag(newline_marked) + first = parts.first + first.set_newline_flag(newline_marked) if first + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [*parts] @@ -3408,6 +3590,11 @@ def accept(visitor) visitor.visit_interpolated_x_string_node(self) end + def set_newline_flag(newline_marked) + first = parts.first + first.set_newline_flag(newline_marked) if first + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [*parts] @@ -4454,6 +4641,10 @@ def accept(visitor) visitor.visit_parentheses_node(self) end + def set_newline_flag(newline_marked) + # Never mark ParenthesesNode with a newline flag, mark children instead + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [statements] @@ -4787,6 +4978,11 @@ def deconstruct_keys(keys) def operator operator_loc.slice end + + # def exclude_end?: () -> bool + def exclude_end? + flags.anybits?(RangeFlags::EXCLUDE_END) + end end # Represents a rational number literal. @@ -4913,6 +5109,46 @@ def content def closing closing_loc.slice end + + # def ignore_case?: () -> bool + def ignore_case? + flags.anybits?(RegularExpressionFlags::IGNORE_CASE) + end + + # def multi_line?: () -> bool + def multi_line? + flags.anybits?(RegularExpressionFlags::MULTI_LINE) + end + + # def extended?: () -> bool + def extended? + flags.anybits?(RegularExpressionFlags::EXTENDED) + end + + # def euc_jp?: () -> bool + def euc_jp? + flags.anybits?(RegularExpressionFlags::EUC_JP) + end + + # def ascii_8bit?: () -> bool + def ascii_8bit? + flags.anybits?(RegularExpressionFlags::ASCII_8BIT) + end + + # def windows_31j?: () -> bool + def windows_31j? + flags.anybits?(RegularExpressionFlags::WINDOWS_31J) + end + + # def utf_8?: () -> bool + def utf_8? + flags.anybits?(RegularExpressionFlags::UTF_8) + end + + # def once?: () -> bool + def once? + flags.anybits?(RegularExpressionFlags::ONCE) + end end # Represents a destructured required parameter node. @@ -5028,6 +5264,10 @@ def accept(visitor) visitor.visit_rescue_modifier_node(self) end + def set_newline_flag(newline_marked) + expression.set_newline_flag(newline_marked) + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [expression, rescue_expression] @@ -5067,8 +5307,8 @@ class RescueNode < Node # attr_reader operator_loc: Location? attr_reader :operator_loc - # attr_reader exception: Node? - attr_reader :exception + # attr_reader reference: Node? + attr_reader :reference # attr_reader statements: Node? attr_reader :statements @@ -5076,12 +5316,12 @@ class RescueNode < Node # attr_reader consequent: Node? attr_reader :consequent - # def initialize: (keyword_loc: Location, exceptions: Array[Node], operator_loc: Location?, exception: Node?, statements: Node?, consequent: Node?, location: Location) -> void - def initialize(keyword_loc, exceptions, operator_loc, exception, statements, consequent, location) + # def initialize: (keyword_loc: Location, exceptions: Array[Node], operator_loc: Location?, reference: Node?, statements: Node?, consequent: Node?, location: Location) -> void + def initialize(keyword_loc, exceptions, operator_loc, reference, statements, consequent, location) @keyword_loc = keyword_loc @exceptions = exceptions @operator_loc = operator_loc - @exception = exception + @reference = reference @statements = statements @consequent = consequent @location = location @@ -5094,7 +5334,7 @@ def accept(visitor) # def child_nodes: () -> Array[nil | Node] def child_nodes - [*exceptions, exception, statements, consequent] + [*exceptions, reference, statements, consequent] end # def deconstruct: () -> Array[nil | Node] @@ -5102,7 +5342,7 @@ def child_nodes # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location] def deconstruct_keys(keys) - { keyword_loc: keyword_loc, exceptions: exceptions, operator_loc: operator_loc, exception: exception, statements: statements, consequent: consequent, location: location } + { keyword_loc: keyword_loc, exceptions: exceptions, operator_loc: operator_loc, reference: reference, statements: statements, consequent: consequent, location: location } end # def keyword: () -> String @@ -5841,6 +6081,10 @@ def accept(visitor) visitor.visit_unless_node(self) end + def set_newline_flag(newline_marked) + predicate.set_newline_flag(newline_marked) + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [predicate, statements, consequent] @@ -5882,11 +6126,15 @@ class UntilNode < Node # attr_reader statements: Node? attr_reader :statements - # def initialize: (keyword_loc: Location, predicate: Node, statements: Node?, location: Location) -> void - def initialize(keyword_loc, predicate, statements, location) + # attr_reader flags: Integer + attr_reader :flags + + # def initialize: (keyword_loc: Location, predicate: Node, statements: Node?, flags: Integer, location: Location) -> void + def initialize(keyword_loc, predicate, statements, flags, location) @keyword_loc = keyword_loc @predicate = predicate @statements = statements + @flags = flags @location = location end @@ -5895,6 +6143,10 @@ def accept(visitor) visitor.visit_until_node(self) end + def set_newline_flag(newline_marked) + predicate.set_newline_flag(newline_marked) + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [predicate, statements] @@ -5905,13 +6157,18 @@ def child_nodes # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location] def deconstruct_keys(keys) - { keyword_loc: keyword_loc, predicate: predicate, statements: statements, location: location } + { keyword_loc: keyword_loc, predicate: predicate, statements: statements, flags: flags, location: location } end # def keyword: () -> String def keyword keyword_loc.slice end + + # def begin_modifier?: () -> bool + def begin_modifier? + flags.anybits?(LoopFlags::BEGIN_MODIFIER) + end end # case true @@ -5977,11 +6234,15 @@ class WhileNode < Node # attr_reader statements: Node? attr_reader :statements - # def initialize: (keyword_loc: Location, predicate: Node, statements: Node?, location: Location) -> void - def initialize(keyword_loc, predicate, statements, location) + # attr_reader flags: Integer + attr_reader :flags + + # def initialize: (keyword_loc: Location, predicate: Node, statements: Node?, flags: Integer, location: Location) -> void + def initialize(keyword_loc, predicate, statements, flags, location) @keyword_loc = keyword_loc @predicate = predicate @statements = statements + @flags = flags @location = location end @@ -5990,6 +6251,10 @@ def accept(visitor) visitor.visit_while_node(self) end + def set_newline_flag(newline_marked) + predicate.set_newline_flag(newline_marked) + end + # def child_nodes: () -> Array[nil | Node] def child_nodes [predicate, statements] @@ -6000,13 +6265,18 @@ def child_nodes # def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, nil | Node | Array[Node] | String | Token | Array[Token] | Location] def deconstruct_keys(keys) - { keyword_loc: keyword_loc, predicate: predicate, statements: statements, location: location } + { keyword_loc: keyword_loc, predicate: predicate, statements: statements, flags: flags, location: location } end # def keyword: () -> String def keyword keyword_loc.slice end + + # def begin_modifier?: () -> bool + def begin_modifier? + flags.anybits?(LoopFlags::BEGIN_MODIFIER) + end end # Represents an xstring literal with no interpolation. @@ -6132,9 +6402,17 @@ def rparen module CallNodeFlags # &. operator SAFE_NAVIGATION = 1 << 0 + + # a call that could have been a local variable + VARIABLE_CALL = 1 << 1 + end + + module LoopFlags + # a loop after a begin statement, so the body is executed first before the condition + BEGIN_MODIFIER = 1 << 0 end - module RangeNodeFlags + module RangeFlags # ... operator EXCLUDE_END = 1 << 0 end @@ -6165,24 +6443,6 @@ module RegularExpressionFlags ONCE = 1 << 7 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 - def visit(node) - node&.accept(self) - end - - def visit_all(nodes) - nodes.map { |node| visit(node) } - end - - def visit_child_nodes(node) - visit_all(node.child_nodes) - end - end - class Visitor < BasicVisitor # Visit a AliasNode node alias visit_alias_node visit_child_nodes @@ -6292,6 +6552,9 @@ class Visitor < BasicVisitor # Visit a ConstantReadNode node alias visit_constant_read_node visit_child_nodes + # Visit a ConstantWriteNode node + alias visit_constant_write_node visit_child_nodes + # Visit a DefNode node alias visit_def_node visit_child_nodes @@ -6316,6 +6579,9 @@ class Visitor < BasicVisitor # Visit a FindPatternNode node alias visit_find_pattern_node visit_child_nodes + # Visit a FlipFlopNode node + alias visit_flip_flop_node visit_child_nodes + # Visit a FloatNode node alias visit_float_node visit_child_nodes @@ -6751,6 +7017,11 @@ def ConstantReadNode(location = Location()) ConstantReadNode.new(location) end + # Create a new ConstantWriteNode node + def ConstantWriteNode(name_loc, value, operator_loc, location = Location()) + ConstantWriteNode.new(name_loc, value, operator_loc, location) + end + # Create a new DefNode node def DefNode(name_loc, receiver, parameters, statements, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc, location = Location()) DefNode.new(name_loc, receiver, parameters, statements, locals, def_keyword_loc, operator_loc, lparen_loc, rparen_loc, equal_loc, end_keyword_loc, location) @@ -6791,6 +7062,11 @@ def FindPatternNode(constant, left, requireds, right, opening_loc, closing_loc, FindPatternNode.new(constant, left, requireds, right, opening_loc, closing_loc, location) end + # Create a new FlipFlopNode node + def FlipFlopNode(left, right, operator_loc, flags, location = Location()) + FlipFlopNode.new(left, right, operator_loc, flags, location) + end + # Create a new FloatNode node def FloatNode(location = Location()) FloatNode.new(location) @@ -7087,8 +7363,8 @@ def RescueModifierNode(expression, keyword_loc, rescue_expression, location = Lo end # Create a new RescueNode node - def RescueNode(keyword_loc, exceptions, operator_loc, exception, statements, consequent, location = Location()) - RescueNode.new(keyword_loc, exceptions, operator_loc, exception, statements, consequent, location) + def RescueNode(keyword_loc, exceptions, operator_loc, reference, statements, consequent, location = Location()) + RescueNode.new(keyword_loc, exceptions, operator_loc, reference, statements, consequent, location) end # Create a new RestParameterNode node @@ -7177,8 +7453,8 @@ def UnlessNode(keyword_loc, predicate, statements, consequent, end_keyword_loc, end # Create a new UntilNode node - def UntilNode(keyword_loc, predicate, statements, location = Location()) - UntilNode.new(keyword_loc, predicate, statements, location) + def UntilNode(keyword_loc, predicate, statements, flags, location = Location()) + UntilNode.new(keyword_loc, predicate, statements, flags, location) end # Create a new WhenNode node @@ -7187,8 +7463,8 @@ def WhenNode(keyword_loc, conditions, statements, location = Location()) end # Create a new WhileNode node - def WhileNode(keyword_loc, predicate, statements, location = Location()) - WhileNode.new(keyword_loc, predicate, statements, location) + def WhileNode(keyword_loc, predicate, statements, flags, location = Location()) + WhileNode.new(keyword_loc, predicate, statements, flags, location) end # Create a new XStringNode node diff --git a/lib/yarp/serialize.rb b/lib/yarp/serialize.rb index 6295a94d8c25f1..d6f7b7a0de157c 100644 --- a/lib/yarp/serialize.rb +++ b/lib/yarp/serialize.rb @@ -7,45 +7,85 @@ require "stringio" +# Polyfill for String#unpack1 with the offset parameter. +if String.instance_method(:unpack1).parameters.none? { |_, name| name == :offset } + String.prepend( + Module.new { + def unpack1(format, offset: 0) + offset == 0 ? super(format) : self[offset..].unpack1(format) + end + } + ) +end + module YARP module Serialize + MAJOR_VERSION = 0 + MINOR_VERSION = 7 + PATCH_VERSION = 0 + def self.load(input, serialized) - io = StringIO.new(serialized) - io.set_encoding(Encoding::BINARY) + Loader.new(Source.new(input), serialized).load + end - Loader.new(input, serialized, io).load + def self.load_tokens(source, serialized) + Loader.new(source, serialized).load_tokens end class Loader attr_reader :encoding, :input, :serialized, :io attr_reader :constant_pool_offset, :constant_pool, :source - def initialize(input, serialized, io) + def initialize(source, serialized) @encoding = Encoding::UTF_8 - @input = input.dup + @input = source.source.dup @serialized = serialized - @io = io + @io = StringIO.new(serialized) + @io.set_encoding(Encoding::BINARY) @constant_pool_offset = nil @constant_pool = nil - offsets = [0] - input.b.scan("\n") { offsets << $~.end(0) } - @source = Source.new(input, offsets) + @source = source + end + + def load_tokens + tokens = [] + while type = TOKEN_TYPES.fetch(load_varint) + start = load_varint + length = load_varint + lex_state = load_varint + location = Location.new(@source, start, length) + tokens << [YARP::Token.new(type, location.slice, location), lex_state] + end + + comments = load_varint.times.map { Comment.new(Comment::TYPES.fetch(load_varint), load_location) } + errors = load_varint.times.map { ParseError.new(load_string, load_location) } + warnings = load_varint.times.map { ParseWarning.new(load_string, load_location) } + + raise "Expected to consume all bytes while deserializing" unless @io.eof? + + YARP::ParseResult.new(tokens, comments, errors, warnings, @source) end def load - io.read(4) => "YARP" - io.read(3).unpack("C3") => [0, 4, 0] + raise "Invalid serialization" if io.read(4) != "YARP" + raise "Invalid serialization" if io.read(3).unpack("C3") != [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION] @encoding = Encoding.find(io.read(load_varint)) @input = input.force_encoding(@encoding).freeze + comments = load_varint.times.map { Comment.new(Comment::TYPES.fetch(io.getbyte), load_location) } + errors = load_varint.times.map { ParseError.new(load_string, load_location) } + warnings = load_varint.times.map { ParseWarning.new(load_string, load_location) } + @constant_pool_offset = io.read(4).unpack1("L") @constant_pool = Array.new(load_varint, nil) - load_node + ast = load_node + + YARP::ParseResult.new(ast, comments, errors, warnings, @source) end private @@ -184,188 +224,359 @@ def load_node when 36 then ConstantReadNode.new(location) when 37 then + ConstantWriteNode.new(load_location, load_optional_node, load_optional_location, location) + when 38 then load_serialized_length DefNode.new(load_location, load_optional_node, load_optional_node, load_optional_node, Array.new(load_varint) { load_constant }, load_location, load_optional_location, load_optional_location, load_optional_location, load_optional_location, load_optional_location, location) - when 38 then - DefinedNode.new(load_optional_location, load_node, load_optional_location, load_location, location) when 39 then - ElseNode.new(load_location, load_optional_node, load_optional_location, location) + DefinedNode.new(load_optional_location, load_node, load_optional_location, load_location, location) when 40 then - EmbeddedStatementsNode.new(load_location, load_optional_node, load_location, location) + ElseNode.new(load_location, load_optional_node, load_optional_location, location) when 41 then - EmbeddedVariableNode.new(load_location, load_node, location) + EmbeddedStatementsNode.new(load_location, load_optional_node, load_location, location) when 42 then - EnsureNode.new(load_location, load_optional_node, load_location, location) + EmbeddedVariableNode.new(load_location, load_node, location) when 43 then - FalseNode.new(location) + EnsureNode.new(load_location, load_optional_node, load_location, location) when 44 then - FindPatternNode.new(load_optional_node, load_node, Array.new(load_varint) { load_node }, load_node, load_optional_location, load_optional_location, location) + FalseNode.new(location) when 45 then - FloatNode.new(location) + FindPatternNode.new(load_optional_node, load_node, Array.new(load_varint) { load_node }, load_node, load_optional_location, load_optional_location, location) when 46 then - ForNode.new(load_node, load_node, load_optional_node, load_location, load_location, load_optional_location, load_location, location) + FlipFlopNode.new(load_optional_node, load_optional_node, load_location, load_varint, location) when 47 then - ForwardingArgumentsNode.new(location) + FloatNode.new(location) when 48 then - ForwardingParameterNode.new(location) + ForNode.new(load_node, load_node, load_optional_node, load_location, load_location, load_optional_location, load_location, location) when 49 then - ForwardingSuperNode.new(load_optional_node, location) + ForwardingArgumentsNode.new(location) when 50 then - GlobalVariableOperatorAndWriteNode.new(load_location, load_location, load_node, location) + ForwardingParameterNode.new(location) when 51 then - GlobalVariableOperatorOrWriteNode.new(load_location, load_location, load_node, location) + ForwardingSuperNode.new(load_optional_node, location) when 52 then - GlobalVariableOperatorWriteNode.new(load_location, load_location, load_node, load_constant, location) + GlobalVariableOperatorAndWriteNode.new(load_location, load_location, load_node, location) when 53 then - GlobalVariableReadNode.new(location) + GlobalVariableOperatorOrWriteNode.new(load_location, load_location, load_node, location) when 54 then - GlobalVariableWriteNode.new(load_location, load_optional_location, load_optional_node, location) + GlobalVariableOperatorWriteNode.new(load_location, load_location, load_node, load_constant, location) when 55 then - HashNode.new(load_location, Array.new(load_varint) { load_node }, load_location, location) + GlobalVariableReadNode.new(location) when 56 then - HashPatternNode.new(load_optional_node, Array.new(load_varint) { load_node }, load_optional_node, load_optional_location, load_optional_location, location) + GlobalVariableWriteNode.new(load_location, load_optional_location, load_optional_node, location) when 57 then - IfNode.new(load_optional_location, load_node, load_optional_node, load_optional_node, load_optional_location, location) + HashNode.new(load_location, Array.new(load_varint) { load_node }, load_location, location) when 58 then - ImaginaryNode.new(load_node, location) + HashPatternNode.new(load_optional_node, Array.new(load_varint) { load_node }, load_optional_node, load_optional_location, load_optional_location, location) when 59 then - InNode.new(load_node, load_optional_node, load_location, load_optional_location, location) + IfNode.new(load_optional_location, load_node, load_optional_node, load_optional_node, load_optional_location, location) when 60 then - InstanceVariableOperatorAndWriteNode.new(load_location, load_location, load_node, location) + ImaginaryNode.new(load_node, location) when 61 then - InstanceVariableOperatorOrWriteNode.new(load_location, load_location, load_node, location) + InNode.new(load_node, load_optional_node, load_location, load_optional_location, location) when 62 then - InstanceVariableOperatorWriteNode.new(load_location, load_location, load_node, load_constant, location) + InstanceVariableOperatorAndWriteNode.new(load_location, load_location, load_node, location) when 63 then - InstanceVariableReadNode.new(location) + InstanceVariableOperatorOrWriteNode.new(load_location, load_location, load_node, location) when 64 then - InstanceVariableWriteNode.new(load_location, load_optional_node, load_optional_location, location) + InstanceVariableOperatorWriteNode.new(load_location, load_location, load_node, load_constant, location) when 65 then - IntegerNode.new(location) + InstanceVariableReadNode.new(location) when 66 then - InterpolatedRegularExpressionNode.new(load_location, Array.new(load_varint) { load_node }, load_location, load_varint, location) + InstanceVariableWriteNode.new(load_location, load_optional_node, load_optional_location, location) when 67 then - InterpolatedStringNode.new(load_optional_location, Array.new(load_varint) { load_node }, load_optional_location, location) + IntegerNode.new(location) when 68 then - InterpolatedSymbolNode.new(load_optional_location, Array.new(load_varint) { load_node }, load_optional_location, location) + InterpolatedRegularExpressionNode.new(load_location, Array.new(load_varint) { load_node }, load_location, load_varint, location) when 69 then - InterpolatedXStringNode.new(load_location, Array.new(load_varint) { load_node }, load_location, location) + InterpolatedStringNode.new(load_optional_location, Array.new(load_varint) { load_node }, load_optional_location, location) when 70 then - KeywordHashNode.new(Array.new(load_varint) { load_node }, location) + InterpolatedSymbolNode.new(load_optional_location, Array.new(load_varint) { load_node }, load_optional_location, location) when 71 then - KeywordParameterNode.new(load_location, load_optional_node, location) + InterpolatedXStringNode.new(load_location, Array.new(load_varint) { load_node }, load_location, location) when 72 then - KeywordRestParameterNode.new(load_location, load_optional_location, location) + KeywordHashNode.new(Array.new(load_varint) { load_node }, location) when 73 then - LambdaNode.new(Array.new(load_varint) { load_constant }, load_location, load_optional_node, load_optional_node, location) + KeywordParameterNode.new(load_location, load_optional_node, location) when 74 then - LocalVariableOperatorAndWriteNode.new(load_location, load_location, load_node, load_constant, location) + KeywordRestParameterNode.new(load_location, load_optional_location, location) when 75 then - LocalVariableOperatorOrWriteNode.new(load_location, load_location, load_node, load_constant, location) + LambdaNode.new(Array.new(load_varint) { load_constant }, load_location, load_optional_node, load_optional_node, location) when 76 then - LocalVariableOperatorWriteNode.new(load_location, load_location, load_node, load_constant, load_constant, location) + LocalVariableOperatorAndWriteNode.new(load_location, load_location, load_node, load_constant, location) when 77 then - LocalVariableReadNode.new(load_constant, load_varint, location) + LocalVariableOperatorOrWriteNode.new(load_location, load_location, load_node, load_constant, location) when 78 then - LocalVariableWriteNode.new(load_constant, load_varint, load_optional_node, load_location, load_optional_location, location) + LocalVariableOperatorWriteNode.new(load_location, load_location, load_node, load_constant, load_constant, location) when 79 then - MatchPredicateNode.new(load_node, load_node, load_location, location) + LocalVariableReadNode.new(load_constant, load_varint, location) when 80 then - MatchRequiredNode.new(load_node, load_node, load_location, location) + LocalVariableWriteNode.new(load_constant, load_varint, load_optional_node, load_location, load_optional_location, location) when 81 then - MissingNode.new(location) + MatchPredicateNode.new(load_node, load_node, load_location, location) when 82 then - ModuleNode.new(Array.new(load_varint) { load_constant }, load_location, load_node, load_optional_node, load_location, location) + MatchRequiredNode.new(load_node, load_node, load_location, location) when 83 then - MultiWriteNode.new(Array.new(load_varint) { load_node }, load_optional_location, load_optional_node, load_optional_location, load_optional_location, location) + MissingNode.new(location) when 84 then - NextNode.new(load_optional_node, load_location, location) + ModuleNode.new(Array.new(load_varint) { load_constant }, load_location, load_node, load_optional_node, load_location, location) when 85 then - NilNode.new(location) + MultiWriteNode.new(Array.new(load_varint) { load_node }, load_optional_location, load_optional_node, load_optional_location, load_optional_location, location) when 86 then - NoKeywordsParameterNode.new(load_location, load_location, location) + NextNode.new(load_optional_node, load_location, location) when 87 then - NumberedReferenceReadNode.new(location) + NilNode.new(location) when 88 then - OptionalParameterNode.new(load_constant, load_location, load_location, load_node, location) + NoKeywordsParameterNode.new(load_location, load_location, location) when 89 then - OrNode.new(load_node, load_node, load_location, location) + NumberedReferenceReadNode.new(location) when 90 then - ParametersNode.new(Array.new(load_varint) { load_node }, Array.new(load_varint) { load_node }, Array.new(load_varint) { load_node }, load_optional_node, Array.new(load_varint) { load_node }, load_optional_node, load_optional_node, location) + OptionalParameterNode.new(load_constant, load_location, load_location, load_node, location) when 91 then - ParenthesesNode.new(load_optional_node, load_location, load_location, location) + OrNode.new(load_node, load_node, load_location, location) when 92 then - PinnedExpressionNode.new(load_node, load_location, load_location, load_location, location) + ParametersNode.new(Array.new(load_varint) { load_node }, Array.new(load_varint) { load_node }, Array.new(load_varint) { load_node }, load_optional_node, Array.new(load_varint) { load_node }, load_optional_node, load_optional_node, location) when 93 then - PinnedVariableNode.new(load_node, load_location, location) + ParenthesesNode.new(load_optional_node, load_location, load_location, location) when 94 then - PostExecutionNode.new(load_optional_node, load_location, load_location, load_location, location) + PinnedExpressionNode.new(load_node, load_location, load_location, load_location, location) when 95 then - PreExecutionNode.new(load_optional_node, load_location, load_location, load_location, location) + PinnedVariableNode.new(load_node, load_location, location) when 96 then - ProgramNode.new(Array.new(load_varint) { load_constant }, load_node, location) + PostExecutionNode.new(load_optional_node, load_location, load_location, load_location, location) when 97 then - RangeNode.new(load_optional_node, load_optional_node, load_location, load_varint, location) + PreExecutionNode.new(load_optional_node, load_location, load_location, load_location, location) when 98 then - RationalNode.new(load_node, location) + ProgramNode.new(Array.new(load_varint) { load_constant }, load_node, location) when 99 then - RedoNode.new(location) + RangeNode.new(load_optional_node, load_optional_node, load_location, load_varint, location) when 100 then - RegularExpressionNode.new(load_location, load_location, load_location, load_string, load_varint, location) + RationalNode.new(load_node, location) when 101 then - RequiredDestructuredParameterNode.new(Array.new(load_varint) { load_node }, load_location, load_location, location) + RedoNode.new(location) when 102 then - RequiredParameterNode.new(load_constant, location) + RegularExpressionNode.new(load_location, load_location, load_location, load_string, load_varint, location) when 103 then - RescueModifierNode.new(load_node, load_location, load_node, location) + RequiredDestructuredParameterNode.new(Array.new(load_varint) { load_node }, load_location, load_location, location) when 104 then - RescueNode.new(load_location, Array.new(load_varint) { load_node }, load_optional_location, load_optional_node, load_optional_node, load_optional_node, location) + RequiredParameterNode.new(load_constant, location) when 105 then - RestParameterNode.new(load_location, load_optional_location, location) + RescueModifierNode.new(load_node, load_location, load_node, location) when 106 then - RetryNode.new(location) + RescueNode.new(load_location, Array.new(load_varint) { load_node }, load_optional_location, load_optional_node, load_optional_node, load_optional_node, location) when 107 then - ReturnNode.new(load_location, load_optional_node, location) + RestParameterNode.new(load_location, load_optional_location, location) when 108 then - SelfNode.new(location) + RetryNode.new(location) when 109 then - SingletonClassNode.new(Array.new(load_varint) { load_constant }, load_location, load_location, load_node, load_optional_node, load_location, location) + ReturnNode.new(load_location, load_optional_node, location) when 110 then - SourceEncodingNode.new(location) + SelfNode.new(location) when 111 then - SourceFileNode.new(load_string, location) + SingletonClassNode.new(Array.new(load_varint) { load_constant }, load_location, load_location, load_node, load_optional_node, load_location, location) when 112 then - SourceLineNode.new(location) + SourceEncodingNode.new(location) when 113 then - SplatNode.new(load_location, load_optional_node, location) + SourceFileNode.new(load_string, location) when 114 then - StatementsNode.new(Array.new(load_varint) { load_node }, location) + SourceLineNode.new(location) when 115 then - StringConcatNode.new(load_node, load_node, location) + SplatNode.new(load_location, load_optional_node, location) when 116 then - StringNode.new(load_optional_location, load_location, load_optional_location, load_string, location) + StatementsNode.new(Array.new(load_varint) { load_node }, location) when 117 then - SuperNode.new(load_location, load_optional_location, load_optional_node, load_optional_location, load_optional_node, location) + StringConcatNode.new(load_node, load_node, location) when 118 then - SymbolNode.new(load_optional_location, load_location, load_optional_location, load_string, location) + StringNode.new(load_optional_location, load_location, load_optional_location, load_string, location) when 119 then - TrueNode.new(location) + SuperNode.new(load_location, load_optional_location, load_optional_node, load_optional_location, load_optional_node, location) when 120 then - UndefNode.new(Array.new(load_varint) { load_node }, load_location, location) + SymbolNode.new(load_optional_location, load_location, load_optional_location, load_string, location) when 121 then - UnlessNode.new(load_location, load_node, load_optional_node, load_optional_node, load_optional_location, location) + TrueNode.new(location) when 122 then - UntilNode.new(load_location, load_node, load_optional_node, location) + UndefNode.new(Array.new(load_varint) { load_node }, load_location, location) when 123 then - WhenNode.new(load_location, Array.new(load_varint) { load_node }, load_optional_node, location) + UnlessNode.new(load_location, load_node, load_optional_node, load_optional_node, load_optional_location, location) when 124 then - WhileNode.new(load_location, load_node, load_optional_node, location) + UntilNode.new(load_location, load_node, load_optional_node, load_varint, location) when 125 then - XStringNode.new(load_location, load_location, load_location, load_string, location) + WhenNode.new(load_location, Array.new(load_varint) { load_node }, load_optional_node, location) when 126 then + WhileNode.new(load_location, load_node, load_optional_node, load_varint, location) + when 127 then + XStringNode.new(load_location, load_location, load_location, load_string, location) + when 128 then YieldNode.new(load_location, load_optional_location, load_optional_node, load_optional_location, location) end end end + + TOKEN_TYPES = [ + nil, + :EOF, + :MISSING, + :NOT_PROVIDED, + :AMPERSAND, + :AMPERSAND_AMPERSAND, + :AMPERSAND_AMPERSAND_EQUAL, + :AMPERSAND_DOT, + :AMPERSAND_EQUAL, + :BACKTICK, + :BACK_REFERENCE, + :BANG, + :BANG_EQUAL, + :BANG_TILDE, + :BRACE_LEFT, + :BRACE_RIGHT, + :BRACKET_LEFT, + :BRACKET_LEFT_ARRAY, + :BRACKET_LEFT_RIGHT, + :BRACKET_LEFT_RIGHT_EQUAL, + :BRACKET_RIGHT, + :CARET, + :CARET_EQUAL, + :CHARACTER_LITERAL, + :CLASS_VARIABLE, + :COLON, + :COLON_COLON, + :COMMA, + :COMMENT, + :CONSTANT, + :DOT, + :DOT_DOT, + :DOT_DOT_DOT, + :EMBDOC_BEGIN, + :EMBDOC_END, + :EMBDOC_LINE, + :EMBEXPR_BEGIN, + :EMBEXPR_END, + :EMBVAR, + :EQUAL, + :EQUAL_EQUAL, + :EQUAL_EQUAL_EQUAL, + :EQUAL_GREATER, + :EQUAL_TILDE, + :FLOAT, + :FLOAT_IMAGINARY, + :FLOAT_RATIONAL, + :FLOAT_RATIONAL_IMAGINARY, + :GLOBAL_VARIABLE, + :GREATER, + :GREATER_EQUAL, + :GREATER_GREATER, + :GREATER_GREATER_EQUAL, + :HEREDOC_END, + :HEREDOC_START, + :IDENTIFIER, + :IGNORED_NEWLINE, + :INSTANCE_VARIABLE, + :INTEGER, + :INTEGER_IMAGINARY, + :INTEGER_RATIONAL, + :INTEGER_RATIONAL_IMAGINARY, + :KEYWORD_ALIAS, + :KEYWORD_AND, + :KEYWORD_BEGIN, + :KEYWORD_BEGIN_UPCASE, + :KEYWORD_BREAK, + :KEYWORD_CASE, + :KEYWORD_CLASS, + :KEYWORD_DEF, + :KEYWORD_DEFINED, + :KEYWORD_DO, + :KEYWORD_DO_LOOP, + :KEYWORD_ELSE, + :KEYWORD_ELSIF, + :KEYWORD_END, + :KEYWORD_END_UPCASE, + :KEYWORD_ENSURE, + :KEYWORD_FALSE, + :KEYWORD_FOR, + :KEYWORD_IF, + :KEYWORD_IF_MODIFIER, + :KEYWORD_IN, + :KEYWORD_MODULE, + :KEYWORD_NEXT, + :KEYWORD_NIL, + :KEYWORD_NOT, + :KEYWORD_OR, + :KEYWORD_REDO, + :KEYWORD_RESCUE, + :KEYWORD_RESCUE_MODIFIER, + :KEYWORD_RETRY, + :KEYWORD_RETURN, + :KEYWORD_SELF, + :KEYWORD_SUPER, + :KEYWORD_THEN, + :KEYWORD_TRUE, + :KEYWORD_UNDEF, + :KEYWORD_UNLESS, + :KEYWORD_UNLESS_MODIFIER, + :KEYWORD_UNTIL, + :KEYWORD_UNTIL_MODIFIER, + :KEYWORD_WHEN, + :KEYWORD_WHILE, + :KEYWORD_WHILE_MODIFIER, + :KEYWORD_YIELD, + :KEYWORD___ENCODING__, + :KEYWORD___FILE__, + :KEYWORD___LINE__, + :LABEL, + :LABEL_END, + :LAMBDA_BEGIN, + :LESS, + :LESS_EQUAL, + :LESS_EQUAL_GREATER, + :LESS_LESS, + :LESS_LESS_EQUAL, + :MINUS, + :MINUS_EQUAL, + :MINUS_GREATER, + :NEWLINE, + :NUMBERED_REFERENCE, + :PARENTHESIS_LEFT, + :PARENTHESIS_LEFT_PARENTHESES, + :PARENTHESIS_RIGHT, + :PERCENT, + :PERCENT_EQUAL, + :PERCENT_LOWER_I, + :PERCENT_LOWER_W, + :PERCENT_LOWER_X, + :PERCENT_UPPER_I, + :PERCENT_UPPER_W, + :PIPE, + :PIPE_EQUAL, + :PIPE_PIPE, + :PIPE_PIPE_EQUAL, + :PLUS, + :PLUS_EQUAL, + :QUESTION_MARK, + :REGEXP_BEGIN, + :REGEXP_END, + :SEMICOLON, + :SLASH, + :SLASH_EQUAL, + :STAR, + :STAR_EQUAL, + :STAR_STAR, + :STAR_STAR_EQUAL, + :STRING_BEGIN, + :STRING_CONTENT, + :STRING_END, + :SYMBOL_BEGIN, + :TILDE, + :UAMPERSAND, + :UCOLON_COLON, + :UDOT_DOT, + :UDOT_DOT_DOT, + :UMINUS, + :UMINUS_NUM, + :UPLUS, + :USTAR, + :USTAR_STAR, + :WORDS_SEP, + :__END__, + ] end end diff --git a/lib/yarp/yarp.gemspec b/lib/yarp/yarp.gemspec index c018e96f96c6bd..f32cd4b6abbac7 100644 --- a/lib/yarp/yarp.gemspec +++ b/lib/yarp/yarp.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |spec| spec.name = "yarp" - spec.version = "0.4.0" + spec.version = "0.7.0" spec.authors = ["Shopify"] spec.email = ["ruby@shopify.com"] @@ -10,27 +10,27 @@ Gem::Specification.new do |spec| spec.homepage = "https://github.com/ruby/yarp" spec.license = "MIT" + spec.required_ruby_version = ">= 3.0.0" + spec.require_paths = ["lib"] spec.files = [ "CHANGELOG.md", "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", "LICENSE.md", - "Makefile.in", + "Makefile", "README.md", - "config.h.in", "config.yml", - "configure", "docs/build_system.md", "docs/building.md", "docs/configuration.md", "docs/design.md", "docs/encoding.md", - "docs/extension.md", "docs/fuzzing.md", "docs/heredocs.md", "docs/mapping.md", "docs/ripper.md", + "docs/ruby_api.md", "docs/serialization.md", "docs/testing.md", "ext/yarp/api_node.c", @@ -59,38 +59,20 @@ Gem::Specification.new do |spec| "include/yarp/util/yp_strpbrk.h", "include/yarp/version.h", "lib/yarp.rb", + "lib/yarp/ffi.rb", "lib/yarp/lex_compat.rb", "lib/yarp/node.rb", "lib/yarp/pack.rb", "lib/yarp/ripper_compat.rb", "lib/yarp/serialize.rb", "src/diagnostic.c", - "src/enc/ascii.c", - "src/enc/big5.c", - "src/enc/euc_jp.c", - "src/enc/gbk.c", - "src/enc/iso_8859_1.c", - "src/enc/iso_8859_10.c", - "src/enc/iso_8859_11.c", - "src/enc/iso_8859_13.c", - "src/enc/iso_8859_14.c", - "src/enc/iso_8859_15.c", - "src/enc/iso_8859_16.c", - "src/enc/iso_8859_2.c", - "src/enc/iso_8859_3.c", - "src/enc/iso_8859_4.c", - "src/enc/iso_8859_5.c", - "src/enc/iso_8859_6.c", - "src/enc/iso_8859_7.c", - "src/enc/iso_8859_8.c", - "src/enc/iso_8859_9.c", - "src/enc/koi8_r.c", - "src/enc/shared.c", - "src/enc/shift_jis.c", - "src/enc/unicode.c", - "src/enc/windows_1251.c", - "src/enc/windows_1252.c", - "src/enc/windows_31j.c", + "src/enc/yp_big5.c", + "src/enc/yp_euc_jp.c", + "src/enc/yp_gbk.c", + "src/enc/yp_shift_jis.c", + "src/enc/yp_tables.c", + "src/enc/yp_unicode.c", + "src/enc/yp_windows_31j.c", "src/node.c", "src/pack.c", "src/prettyprint.c", diff --git a/test/newline_test.rb b/test/newline_test.rb deleted file mode 100644 index 1f6b550f30a2ff..00000000000000 --- a/test/newline_test.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: true - -require "yarp_test_helper" - -class NewlineTest < Test::Unit::TestCase - class NewlineVisitor < YARP::Visitor - attr_reader :source, :newlines - - def initialize(source) - @source = source - @newlines = [] - end - - def visit(node) - newlines << source.line(node.location.start_offset) if node&.newline? - super(node) - end - end - - root = File.dirname(__dir__) - Dir["{lib,test}/**/*.rb", base: root].each do |relative| - filepath = File.join(root, relative) - - define_method "test_newline_flags_#{relative}" do - source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) - expected = rubyvm_lines(source) - - result = YARP.parse_file(filepath) - assert_empty result.errors - - result.mark_newlines - visitor = NewlineVisitor.new(result.source) - result.value.accept(visitor) - actual = visitor.newlines - - if relative == "lib/yarp/serialize.rb" - # while (b = io.getbyte) >= 128 has 2 newline flags - line_number = source.lines.index { |line| line.include?('while (b = io.getbyte) >= 128') } + 1 - expected.delete_at(expected.index(line_number)) - elsif relative == "lib/yarp/lex_compat.rb" - # extra flag for: dedent_next =\n ((token.event: due to bytecode order - actual.delete(520) - # different line for: token =\n case event: due to bytecode order - actual.delete(577) - expected.delete(578) - # extra flag for: lex_state =\n if RIPPER: due to bytecode order - actual.delete(610) - # extra flag for: (token[2].start_with?("\#$") || token[2].start_with?("\#@")) - # unclear when ParenthesesNode should allow a second flag on the same line or not - actual.delete(737) - end - - assert_equal expected, actual - end - end - - private - - def ignore_warnings - previous_verbosity = $VERBOSE - $VERBOSE = nil - yield - ensure - $VERBOSE = previous_verbosity - end - - def rubyvm_lines(source) - queue = [ignore_warnings { RubyVM::InstructionSequence.compile(source) }] - lines = [] - - while iseq = queue.shift - lines.concat(iseq.trace_points.filter_map { |line, event| line if event == :line }) - iseq.each_child { |insn| queue << insn unless insn.label.start_with?("ensure in ") } - end - - lines.sort - end -end diff --git a/test/yarp/encoding_test.rb b/test/yarp/encoding_test.rb index a39fa9b1980761..95d7bd3223b302 100644 --- a/test/yarp/encoding_test.rb +++ b/test/yarp/encoding_test.rb @@ -30,6 +30,7 @@ class EncodingTest < Test::Unit::TestCase sjis us-ascii utf-8 + utf8-mac windows-31j windows-1251 windows-1252 diff --git a/test/yarp/errors_test.rb b/test/yarp/errors_test.rb index e89ade0ba5e903..3b880eda85746a 100644 --- a/test/yarp/errors_test.rb +++ b/test/yarp/errors_test.rb @@ -294,28 +294,10 @@ def test_double_splat_followed_by_splat_argument nil, Location(), Location(), - ArgumentsNode( - [KeywordHashNode( - [AssocSplatNode( - CallNode( - nil, - nil, - Location(), - nil, - nil, - nil, - nil, - 0, - "kwargs" - ), - Location() - )] - ), - SplatNode( - Location(), - CallNode(nil, nil, Location(), nil, nil, nil, nil, 0, "args") - )] - ), + ArgumentsNode([ + KeywordHashNode([AssocSplatNode(expression("kwargs"), Location())]), + SplatNode(Location(), expression("args")) + ]), Location(), nil, 0, @@ -362,19 +344,16 @@ def test_splat_argument_after_keyword_argument nil, Location(), Location(), - ArgumentsNode( - [KeywordHashNode( - [AssocNode( - SymbolNode(nil, Location(), Location(), "foo"), - CallNode(nil, nil, Location(), nil, nil, nil, nil, 0, "bar"), - nil - )] - ), - SplatNode( - Location(), - CallNode(nil, nil, Location(), nil, nil, nil, nil, 0, "args") - )] - ), + ArgumentsNode([ + KeywordHashNode( + [AssocNode( + SymbolNode(nil, Location(), Location(), "foo"), + expression("bar"), + nil + )] + ), + SplatNode(Location(), expression("args")) + ]), Location(), nil, 0, @@ -1005,23 +984,27 @@ def test_dont_allow_setting_to_back_and_nth_reference end def test_duplicated_parameter_names - expected = DefNode( - Location(), - nil, - ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b), RequiredParameterNode(:a)], [], [], nil, [], nil, nil), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) + # For some reason, Ripper reports no error for Ruby 3.0 when you have + # duplicated parameter names for positional parameters. + unless RUBY_VERSION < "3.1.0" + expected = DefNode( + Location(), + nil, + ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b), RequiredParameterNode(:a)], [], [], nil, [], nil, nil), + nil, + [:a, :b], + Location(), + nil, + Location(), + Location(), + nil, + Location() + ) - assert_errors expected, "def foo(a,b,a);end", [ - ["Duplicated parameter name.", 12..13] - ] + assert_errors expected, "def foo(a,b,a);end", [ + ["Duplicated parameter name.", 12..13] + ] + end expected = DefNode( Location(), diff --git a/test/yarp/fixtures/method_calls.txt b/test/yarp/fixtures/method_calls.txt index 06ed1cb9ccf7f6..5d82abef2e34d6 100644 --- a/test/yarp/fixtures/method_calls.txt +++ b/test/yarp/fixtures/method_calls.txt @@ -16,6 +16,8 @@ a.(1, 2, 3) a::b +a::b c + foo.bar = 1 a? @@ -80,6 +82,8 @@ foo( b: :c, ) +foo &:block + foo a: true, b: false, &:block some_func 1, kwarg: 2 @@ -137,3 +141,7 @@ foo :a, A {} + A {} lst << A {} + +"#{ join (" ") }" + +"#{(v)}" diff --git a/test/yarp/fixtures/ternary_operator.txt b/test/yarp/fixtures/ternary_operator.txt index ca00ead321dc41..79d2d7d8373ff8 100644 --- a/test/yarp/fixtures/ternary_operator.txt +++ b/test/yarp/fixtures/ternary_operator.txt @@ -11,3 +11,5 @@ empty??nil:nil a??nil:nil a ?var1 : var2 + +nil??_a =2:1 diff --git a/test/yarp/locals_test.rb b/test/yarp/locals_test.rb new file mode 100644 index 00000000000000..18d8edacdaa309 --- /dev/null +++ b/test/yarp/locals_test.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +# This test is going to use the RubyVM::InstructionSequence class to compile +# local tables and compare against them to ensure we have the same locals in the +# same order. This is important to guarantee that we compile indices correctly +# on CRuby (in terms of compatibility). +# +# There have also been changes made in other versions of Ruby, so we only want +# to test on the most recent versions. +return if !defined?(RubyVM::InstructionSequence) || RUBY_VERSION < "3.2" + +require "yarp_test_helper" + +class LocalsTest < Test::Unit::TestCase + invalid = [] + todos = [] + + # Invalid break + invalid << "break.txt" + invalid << "if.txt" + invalid << "rescue.txt" + invalid << "seattlerb/block_break.txt" + invalid << "unless.txt" + invalid << "whitequark/break.txt" + invalid << "whitequark/break_block.txt" + + # Invalid next + invalid << "next.txt" + invalid << "seattlerb/block_next.txt" + invalid << "unparser/corpus/literal/control.txt" + invalid << "whitequark/next.txt" + invalid << "whitequark/next_block.txt" + + # Invalid redo + invalid << "keywords.txt" + invalid << "whitequark/redo.txt" + + # Invalid retry + invalid << "whitequark/retry.txt" + + # Invalid yield + invalid << "seattlerb/dasgn_icky2.txt" + invalid << "seattlerb/yield_arg.txt" + invalid << "seattlerb/yield_call_assocs.txt" + invalid << "seattlerb/yield_empty_parens.txt" + invalid << "unparser/corpus/literal/yield.txt" + invalid << "whitequark/args_assocs.txt" + invalid << "whitequark/args_assocs_legacy.txt" + invalid << "whitequark/yield.txt" + invalid << "yield.txt" + + # Dead code eliminated + invalid << "whitequark/ruby_bug_10653.txt" + + # case :a + # in Symbol(*lhs, x, *rhs) + # end + todos << "seattlerb/case_in.txt" + + # <<~HERE + # #{<<~THERE} + # THERE + # HERE + todos << "seattlerb/heredoc_nested.txt" + + base = File.join(__dir__, "fixtures") + skips = invalid | todos + + Dir["**/*.txt", base: base].each do |relative| + next if skips.include?(relative) + + filepath = File.join(base, relative) + define_method("test_#{relative}") { assert_locals(filepath) } + end + + private + + def assert_locals(filepath) + source = File.read(filepath) + + expected = YARP.const_get(:Debug).cruby_locals(source) + actual = YARP.const_get(:Debug).yarp_locals(source) + + assert_equal(expected, actual) + end +end diff --git a/test/yarp/memsize_test.rb b/test/yarp/memsize_test.rb index 38aca6169f4aa5..30de1085cf275e 100644 --- a/test/yarp/memsize_test.rb +++ b/test/yarp/memsize_test.rb @@ -2,6 +2,8 @@ require "yarp_test_helper" +return if YARP::BACKEND == :FFI + class MemsizeTest < Test::Unit::TestCase def test_memsize result = YARP.const_get(:Debug).memsize("2 + 3") diff --git a/test/yarp/newline_test.rb b/test/yarp/newline_test.rb new file mode 100644 index 00000000000000..80f6329d94d6c2 --- /dev/null +++ b/test/yarp/newline_test.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +require "yarp_test_helper" + +return unless defined?(RubyVM::InstructionSequence) + +# It is useful to have a diff even if the strings to compare are big +# However, ruby/ruby does not have a version of Test::Unit with access to +# max_diff_target_string_size +if defined?(Test::Unit::Assertions::AssertionMessage) + Test::Unit::Assertions::AssertionMessage.max_diff_target_string_size = 5000 +end + +class NewlineTest < Test::Unit::TestCase + class NewlineVisitor < YARP::Visitor + attr_reader :source, :newlines + + def initialize(source) + @source = source + @newlines = [] + end + + def visit(node) + newlines << source.line(node.location.start_offset) if node&.newline? + super(node) + end + end + + base = File.dirname(__dir__) + Dir["{lib,test}/**/*.rb", base: base].each do |relative| + define_method("test_newline_flags_#{relative}") do + assert_newlines(base, relative) + end + end + + private + + def assert_newlines(base, relative) + filepath = File.join(base, relative) + source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8) + expected = rubyvm_lines(source) + + result = YARP.parse_file(filepath) + assert_empty result.errors + + result.mark_newlines + visitor = NewlineVisitor.new(result.source) + + result.value.accept(visitor) + actual = visitor.newlines + + source.each_line.with_index(1) do |line, line_number| + # Lines like `while (foo = bar)` result in two line flags in the bytecode + # but only one newline flag in the AST. We need to remove the extra line + # flag from the bytecode to make the test pass. + if line.match?(/while \(/) + index = expected.index(line_number) + expected.delete_at(index) if index + end + + # Lines like `foo =` where the value is on the next line result in another + # line flag in the bytecode but only one newline flag in the AST. + if line.match?(/^\s+\w+ =$/) + if source.lines[line_number].match?(/^\s+case/) + actual[actual.index(line_number)] += 1 + else + actual.delete_at(actual.index(line_number)) + end + end + + if line.match?(/^\s+\w+ = \[$/) + if !expected.include?(line_number) && !expected.include?(line_number + 2) + actual[actual.index(line_number)] += 1 + end + end + end + + assert_equal expected, actual + end + + def ignore_warnings + previous_verbosity = $VERBOSE + $VERBOSE = nil + yield + ensure + $VERBOSE = previous_verbosity + end + + def rubyvm_lines(source) + queue = [ignore_warnings { RubyVM::InstructionSequence.compile(source) }] + lines = [] + + while iseq = queue.shift + lines.concat(iseq.trace_points.filter_map { |line, event| line if event == :line }) + iseq.each_child { |insn| queue << insn unless insn.label.start_with?("ensure in ") } + end + + lines.sort + end +end diff --git a/test/yarp/parse_serialize_test.rb b/test/yarp/parse_serialize_test.rb new file mode 100644 index 00000000000000..6789ba9c438499 --- /dev/null +++ b/test/yarp/parse_serialize_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "yarp_test_helper" + +return if YARP::BACKEND == :FFI + +class ParseSerializeTest < Test::Unit::TestCase + def test_parse_serialize + dumped = YARP.const_get(:Debug).parse_serialize_file(__FILE__) + result = YARP.load(File.read(__FILE__), dumped) + + assert_kind_of YARP::ParseResult, result, "Expected the return value to be a ParseResult" + assert_equal __FILE__, find_file_node(result)&.filepath, "Expected the filepath to be set correctly" + end + + private + + def find_file_node(result) + queue = [result.value] + + while (node = queue.shift) + return node if node.is_a?(YARP::SourceFileNode) + queue.concat(node.child_nodes.compact) + end + end +end diff --git a/test/yarp/parse_test.rb b/test/yarp/parse_test.rb index 43a1deb8fb1ade..cda157d56c8511 100644 --- a/test/yarp/parse_test.rb +++ b/test/yarp/parse_test.rb @@ -18,47 +18,30 @@ def teardown ignore_warnings { Encoding.default_external = @previous_default_external } end - def test_Ruby_3_2_plus - assert_operator RUBY_VERSION, :>=, "3.2.0", "ParseTest requires Ruby 3.2+" - end - def test_empty_string result = YARP.parse("") assert_equal [], result.value.statements.body end - known_failures = %w[ - seattlerb/heredoc_nested.txt - ] - - if RUBY_VERSION < "3.3.0" - known_failures << "seattlerb/pct_w_heredoc_interp_nested.txt" - end - - def find_source_file_node(node) - if node.is_a?(YARP::SourceFileNode) - node - else - node && node.child_nodes.each do |child_node| - source_file_node = find_source_file_node(child_node) - return source_file_node if source_file_node - end - end - end - def test_parse_takes_file_path filepath = "filepath.rb" - parsed_result = YARP.parse("def foo; __FILE__; end", filepath) + result = YARP.parse("def foo; __FILE__; end", filepath) - assert_equal filepath, find_source_file_node(parsed_result.value).filepath + assert_equal filepath, find_source_file_node(result.value).filepath end + # To accurately compare against Ripper, we need to make sure that we're + # running on Ruby 3.2+. + check_ripper = RUBY_VERSION >= "3.2.0" + base = File.join(__dir__, "fixtures") Dir["**/*.txt", base: base].each do |relative| - next if known_failures.include?(relative) + # These fail on TruffleRuby due to a difference in Symbol#inspect: :测试 vs :"测试" + next if RUBY_ENGINE == "truffleruby" and %w[seattlerb/bug202.txt seattlerb/magic_encoding_comment.txt].include?(relative) filepath = File.join(base, relative) snapshot = File.expand_path(File.join("snapshots", relative), __dir__) + directory = File.dirname(snapshot) FileUtils.mkdir_p(directory) unless File.directory?(directory) @@ -69,7 +52,7 @@ def test_parse_takes_file_path # Make sure that it can be correctly parsed by Ripper. If it can't, then we have a fixture # that is invalid Ruby. - refute_nil Ripper.sexp_raw(source) + refute_nil Ripper.sexp_raw(source) if check_ripper # Next, assert that there were no errors during parsing. result = YARP.parse(source, relative) @@ -99,25 +82,35 @@ def test_parse_takes_file_path # Next, assert that the value can be serialized and deserialized without # changing the shape of the tree. - assert_equal_nodes(result.value, YARP.load(source, YARP.dump(source, relative))) + assert_equal_nodes(result.value, YARP.load(source, YARP.dump(source, relative)).value) # Next, assert that the newlines are in the expected places. expected_newlines = [0] source.b.scan("\n") { expected_newlines << $~.offset(0)[0] + 1 } assert_equal expected_newlines, YARP.const_get(:Debug).newlines(source) + # This file has changed behavior in Ripper in Ruby 3.3, so we skip it if + # we're on an earlier version. + return if relative == "seattlerb/pct_w_heredoc_interp_nested.txt" && RUBY_VERSION < "3.3.0" + + # It seems like there are some oddities with nested heredocs and ripper. + # Waiting for feedback on https://bugs.ruby-lang.org/issues/19838. + return if relative == "seattlerb/heredoc_nested.txt" + # Finally, assert that we can lex the source and get the same tokens as # Ripper. lex_result = YARP.lex_compat(source) assert_equal [], lex_result.errors tokens = lex_result.value - begin - YARP.lex_ripper(source).zip(tokens).each do |(ripper, yarp)| - assert_equal ripper, yarp + if check_ripper + begin + YARP.lex_ripper(source).zip(tokens).each do |(ripper, yarp)| + assert_equal ripper, yarp + end + rescue SyntaxError + raise ArgumentError, "Test file has invalid syntax #{filepath}" end - rescue SyntaxError - raise ArgumentError, "Test file has invalid syntax #{filepath}" end end end @@ -137,13 +130,21 @@ def test_parse_takes_file_path result = YARP.parse(snippet, relative) assert_empty result.errors - assert_equal_nodes(result.value, YARP.load(snippet, YARP.dump(snippet, relative))) + assert_equal_nodes(result.value, YARP.load(snippet, YARP.dump(snippet, relative)).value) end end end private + def find_source_file_node(program) + queue = [program] + while (node = queue.shift) + return node if node.is_a?(YARP::SourceFileNode) + queue.concat(node.child_nodes.compact) + end + end + def ignore_warnings previous_verbosity = $VERBOSE $VERBOSE = nil diff --git a/test/yarp/regexp_test.rb b/test/yarp/regexp_test.rb index 035bead8130e62..bb236e2f1f9daf 100644 --- a/test/yarp/regexp_test.rb +++ b/test/yarp/regexp_test.rb @@ -2,6 +2,8 @@ require "yarp_test_helper" +return if YARP::BACKEND == :FFI + class RegexpTest < Test::Unit::TestCase ############################################################################## # These tests test the actual use case of extracting named capture groups diff --git a/test/ruby_api_test.rb b/test/yarp/ruby_api_test.rb similarity index 100% rename from test/ruby_api_test.rb rename to test/yarp/ruby_api_test.rb diff --git a/test/yarp/snapshots/arithmetic.txt b/test/yarp/snapshots/arithmetic.txt index 7de7a714b60f16..c82760a7e39826 100644 --- a/test/yarp/snapshots/arithmetic.txt +++ b/test/yarp/snapshots/arithmetic.txt @@ -8,7 +8,7 @@ ProgramNode(0...39)( nil, ArgumentsNode(4...8)( [CallNode(4...8)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "bar"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "bar"), nil, (4...5), nil, @@ -26,7 +26,7 @@ ProgramNode(0...39)( ), CallNode(10...18)( CallNode(10...14)( - CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "foo"), + CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "foo"), nil, (10...11), nil, @@ -40,7 +40,7 @@ ProgramNode(0...39)( (14...15), nil, ArgumentsNode(15...18)( - [CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 0, "bar")] + [CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 2, "bar")] ), nil, nil, @@ -49,7 +49,7 @@ ProgramNode(0...39)( ), CallNode(20...29)( CallNode(20...24)( - CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "foo"), + CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "foo"), nil, (20...21), nil, @@ -63,7 +63,7 @@ ProgramNode(0...39)( (24...26), nil, ArgumentsNode(26...29)( - [CallNode(26...29)(nil, nil, (26...29), nil, nil, nil, nil, 0, "bar")] + [CallNode(26...29)(nil, nil, (26...29), nil, nil, nil, nil, 2, "bar")] ), nil, nil, @@ -85,7 +85,7 @@ ProgramNode(0...39)( nil, nil, nil, - 0, + 2, "bar" ), nil, diff --git a/test/yarp/snapshots/arrays.txt b/test/yarp/snapshots/arrays.txt index 219573ccba6a3a..ec251f0827757d 100644 --- a/test/yarp/snapshots/arrays.txt +++ b/test/yarp/snapshots/arrays.txt @@ -4,19 +4,19 @@ ProgramNode(0...511)( [ArrayNode(0...4)( [SplatNode(1...3)( (1...2), - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "a") + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "a") )], (0...1), (3...4) ), CallNode(6...29)( - CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "foo"), + CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "foo"), nil, (9...19), (9...10), ArgumentsNode(10...29)( - [CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 0, "bar"), - CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 0, "baz"), + [CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 2, "bar"), + CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 2, "baz"), ArrayNode(22...29)( [IntegerNode(22...23)(), IntegerNode(25...26)(), @@ -75,7 +75,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), CallNode(108...111)( @@ -86,7 +86,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" ), (105...107) @@ -105,7 +105,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -120,7 +120,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -141,7 +141,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "baz" ), CallNode(130...133)( @@ -152,7 +152,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "qux" )] ), @@ -171,7 +171,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -186,7 +186,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -207,7 +207,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -226,7 +226,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -241,7 +241,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" ), CallNode(164...167)( @@ -252,7 +252,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -270,7 +270,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -285,7 +285,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" ), CallNode(179...182)( @@ -296,7 +296,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "baz" ), CallNode(186...189)( @@ -307,7 +307,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "qux" )] ), @@ -326,7 +326,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -347,7 +347,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -377,7 +377,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -393,7 +393,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -408,7 +408,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "baz" ), CallNode(229...232)( @@ -419,7 +419,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "qux" )] ), @@ -443,7 +443,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -458,7 +458,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -476,7 +476,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -491,7 +491,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" ), CallNode(256...259)( @@ -502,7 +502,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -532,7 +532,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "kw" ), (270...272) @@ -553,7 +553,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "kw" ), (281...283) @@ -574,7 +574,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "kw" ), (292...294) @@ -592,7 +592,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "kw" ), (304...306) @@ -612,7 +612,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "foo" ), CallNode(322...325)( @@ -623,7 +623,7 @@ ProgramNode(0...511)( nil, nil, nil, - 0, + 2, "bar" ), (319...321) diff --git a/test/yarp/snapshots/begin_ensure.txt b/test/yarp/snapshots/begin_ensure.txt index b82cf6a007a000..e04a1236df3ee0 100644 --- a/test/yarp/snapshots/begin_ensure.txt +++ b/test/yarp/snapshots/begin_ensure.txt @@ -4,14 +4,14 @@ ProgramNode(0...94)( [BeginNode(0...20)( (0...5), StatementsNode(6...7)( - [CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "a")] + [CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "a")] ), nil, nil, EnsureNode(8...20)( (8...14), StatementsNode(15...16)( - [CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 0, "b")] + [CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 2, "b")] ), (17...20) ), @@ -20,14 +20,14 @@ ProgramNode(0...94)( BeginNode(22...46)( (22...27), StatementsNode(29...30)( - [CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 0, "a")] + [CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 2, "a")] ), nil, nil, EnsureNode(32...46)( (32...38), StatementsNode(40...41)( - [CallNode(40...41)(nil, nil, (40...41), nil, nil, nil, nil, 0, "b")] + [CallNode(40...41)(nil, nil, (40...41), nil, nil, nil, nil, 2, "b")] ), (43...46) ), @@ -36,14 +36,14 @@ ProgramNode(0...94)( BeginNode(48...70)( (48...53), StatementsNode(54...55)( - [CallNode(54...55)(nil, nil, (54...55), nil, nil, nil, nil, 0, "a")] + [CallNode(54...55)(nil, nil, (54...55), nil, nil, nil, nil, 2, "a")] ), nil, nil, EnsureNode(57...70)( (57...63), StatementsNode(64...65)( - [CallNode(64...65)(nil, nil, (64...65), nil, nil, nil, nil, 0, "b")] + [CallNode(64...65)(nil, nil, (64...65), nil, nil, nil, nil, 2, "b")] ), (67...70) ), @@ -52,14 +52,14 @@ ProgramNode(0...94)( BeginNode(72...94)( (72...77), StatementsNode(78...79)( - [CallNode(78...79)(nil, nil, (78...79), nil, nil, nil, nil, 0, "a")] + [CallNode(78...79)(nil, nil, (78...79), nil, nil, nil, nil, 2, "a")] ), nil, nil, EnsureNode(81...94)( (81...87), StatementsNode(88...89)( - [CallNode(88...89)(nil, nil, (88...89), nil, nil, nil, nil, 0, "b")] + [CallNode(88...89)(nil, nil, (88...89), nil, nil, nil, nil, 2, "b")] ), (91...94) ), diff --git a/test/yarp/snapshots/begin_rescue.txt b/test/yarp/snapshots/begin_rescue.txt index 7c8b139dcedade..f7195f80a08d54 100644 --- a/test/yarp/snapshots/begin_rescue.txt +++ b/test/yarp/snapshots/begin_rescue.txt @@ -4,7 +4,7 @@ ProgramNode(0...578)( [BeginNode(0...33)( (0...5), StatementsNode(7...8)( - [CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "a")] + [CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "a")] ), RescueNode(10...19)( (10...16), @@ -12,14 +12,14 @@ ProgramNode(0...578)( nil, nil, StatementsNode(18...19)( - [CallNode(18...19)(nil, nil, (18...19), nil, nil, nil, nil, 0, "b")] + [CallNode(18...19)(nil, nil, (18...19), nil, nil, nil, nil, 2, "b")] ), nil ), ElseNode(21...33)( (21...25), StatementsNode(27...28)( - [CallNode(27...28)(nil, nil, (27...28), nil, nil, nil, nil, 0, "c")] + [CallNode(27...28)(nil, nil, (27...28), nil, nil, nil, nil, 2, "c")] ), (30...33) ), @@ -29,7 +29,7 @@ ProgramNode(0...578)( BeginNode(35...79)( (35...40), StatementsNode(42...43)( - [CallNode(42...43)(nil, nil, (42...43), nil, nil, nil, nil, 0, "a")] + [CallNode(42...43)(nil, nil, (42...43), nil, nil, nil, nil, 2, "a")] ), RescueNode(45...54)( (45...51), @@ -37,21 +37,21 @@ ProgramNode(0...578)( nil, nil, StatementsNode(53...54)( - [CallNode(53...54)(nil, nil, (53...54), nil, nil, nil, nil, 0, "b")] + [CallNode(53...54)(nil, nil, (53...54), nil, nil, nil, nil, 2, "b")] ), nil ), ElseNode(56...71)( (56...60), StatementsNode(62...63)( - [CallNode(62...63)(nil, nil, (62...63), nil, nil, nil, nil, 0, "c")] + [CallNode(62...63)(nil, nil, (62...63), nil, nil, nil, nil, 2, "c")] ), (65...71) ), EnsureNode(65...79)( (65...71), StatementsNode(73...74)( - [CallNode(73...74)(nil, nil, (73...74), nil, nil, nil, nil, 0, "d")] + [CallNode(73...74)(nil, nil, (73...74), nil, nil, nil, nil, 2, "d")] ), (76...79) ), @@ -60,7 +60,7 @@ ProgramNode(0...578)( BeginNode(81...92)( (81...86), StatementsNode(87...88)( - [CallNode(87...88)(nil, nil, (87...88), nil, nil, nil, nil, 0, "a")] + [CallNode(87...88)(nil, nil, (87...88), nil, nil, nil, nil, 2, "a")] ), nil, nil, @@ -78,7 +78,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -98,7 +98,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -118,7 +118,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -138,7 +138,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -156,7 +156,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -174,7 +174,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "c" )] ), @@ -192,7 +192,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -215,7 +215,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -233,7 +233,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -251,7 +251,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "c" )] ), @@ -273,7 +273,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -291,7 +291,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -309,7 +309,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -329,7 +329,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -347,7 +347,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -368,7 +368,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -386,7 +386,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -407,7 +407,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -425,7 +425,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -446,7 +446,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -464,7 +464,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -485,7 +485,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -503,7 +503,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -524,7 +524,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -542,7 +542,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -563,7 +563,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -581,7 +581,7 @@ ProgramNode(0...578)( nil, nil, nil, - 0, + 2, "b" )] ), diff --git a/test/yarp/snapshots/blocks.txt b/test/yarp/snapshots/blocks.txt index 4fcbaace1461d6..3579d99bd75dfb 100644 --- a/test/yarp/snapshots/blocks.txt +++ b/test/yarp/snapshots/blocks.txt @@ -2,12 +2,12 @@ ProgramNode(0...402)( [:fork], StatementsNode(0...402)( [CallNode(0...16)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...8), (3...4), ArgumentsNode(4...7)( - [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "bar")] + [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "bar")] ), (7...8), BlockNode(9...16)( @@ -22,7 +22,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -33,12 +33,12 @@ ProgramNode(0...402)( "[]" ), CallNode(18...37)( - CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 0, "foo"), + CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 2, "foo"), nil, (21...26), (21...22), ArgumentsNode(22...25)( - [CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 0, "bar")] + [CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 2, "bar")] ), (25...26), BlockNode(27...37)( @@ -53,7 +53,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -64,7 +64,7 @@ ProgramNode(0...402)( "[]" ), CallNode(39...74)( - CallNode(39...40)(nil, nil, (39...40), nil, nil, nil, nil, 0, "x"), + CallNode(39...40)(nil, nil, (39...40), nil, nil, nil, nil, 2, "x"), (40...41), (41...47), (47...48), @@ -119,7 +119,7 @@ ProgramNode(0...402)( (88...91), nil, ArgumentsNode(92...109)( - [CallNode(92...95)(nil, nil, (92...95), nil, nil, nil, nil, 0, "bar"), + [CallNode(92...95)(nil, nil, (92...95), nil, nil, nil, nil, 2, "bar"), ParenthesesNode(97...109)( StatementsNode(98...108)( [CallNode(98...108)( @@ -157,7 +157,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -186,7 +186,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -226,7 +226,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "b" ), nil, @@ -342,7 +342,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -357,7 +357,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -374,7 +374,7 @@ ProgramNode(0...402)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/boolean_operators.txt b/test/yarp/snapshots/boolean_operators.txt index 6c3ef5a4a7c21b..1b8a2aaed91214 100644 --- a/test/yarp/snapshots/boolean_operators.txt +++ b/test/yarp/snapshots/boolean_operators.txt @@ -4,20 +4,20 @@ ProgramNode(0...24)( [LocalVariableOperatorAndWriteNode(0...7)( (0...1), (2...5), - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b"), + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b"), :a ), LocalVariableOperatorWriteNode(9...15)( (9...10), (11...13), - CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 0, "b"), + CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "b"), :a, :+ ), LocalVariableOperatorOrWriteNode(17...24)( (17...18), (19...22), - CallNode(23...24)(nil, nil, (23...24), nil, nil, nil, nil, 0, "b"), + CallNode(23...24)(nil, nil, (23...24), nil, nil, nil, nil, 2, "b"), :a )] ) diff --git a/test/yarp/snapshots/case.txt b/test/yarp/snapshots/case.txt index f1ee1c9c2d22dc..f041410e3ce108 100644 --- a/test/yarp/snapshots/case.txt +++ b/test/yarp/snapshots/case.txt @@ -70,7 +70,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "foo" ) )], @@ -106,7 +106,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "this" ), [WhenNode(147...167)( @@ -131,7 +131,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -146,7 +146,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -173,7 +173,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "a" )], nil @@ -191,7 +191,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "type" ), [WhenNode(246...253)( diff --git a/test/yarp/snapshots/classes.txt b/test/yarp/snapshots/classes.txt index 7b65c457ef5a71..60ab0eadc5e075 100644 --- a/test/yarp/snapshots/classes.txt +++ b/test/yarp/snapshots/classes.txt @@ -80,7 +80,7 @@ ProgramNode(0...370)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -158,7 +158,7 @@ ProgramNode(0...370)( nil, nil, nil, - 0, + 2, "foo" ), (232...233), @@ -186,7 +186,7 @@ ProgramNode(0...370)( nil, nil, nil, - 0, + 2, "foo" ), (254...255), diff --git a/test/yarp/snapshots/comments.txt b/test/yarp/snapshots/comments.txt index 4b629af138fe4f..e24df47bc83170 100644 --- a/test/yarp/snapshots/comments.txt +++ b/test/yarp/snapshots/comments.txt @@ -1,12 +1,12 @@ ProgramNode(0...118)( [], StatementsNode(0...118)( - [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), - CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 0, "b"), - CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 0, "c"), - CallNode(28...29)(nil, nil, (28...29), nil, nil, nil, nil, 0, "d"), + [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), + CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 2, "b"), + CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 2, "c"), + CallNode(28...29)(nil, nil, (28...29), nil, nil, nil, nil, 2, "d"), CallNode(31...47)( - CallNode(31...32)(nil, nil, (31...32), nil, nil, nil, nil, 0, "e"), + CallNode(31...32)(nil, nil, (31...32), nil, nil, nil, nil, 2, "e"), (45...46), (46...47), nil, @@ -17,7 +17,7 @@ ProgramNode(0...118)( "f" ), CallNode(49...64)( - CallNode(49...50)(nil, nil, (49...50), nil, nil, nil, nil, 0, "g"), + CallNode(49...50)(nil, nil, (49...50), nil, nil, nil, nil, 2, "g"), (62...63), (63...64), nil, @@ -28,7 +28,7 @@ ProgramNode(0...118)( "h" ), CallNode(66...80)( - CallNode(66...67)(nil, nil, (66...67), nil, nil, nil, nil, 0, "i"), + CallNode(66...67)(nil, nil, (66...67), nil, nil, nil, nil, 2, "i"), (78...79), (79...80), nil, @@ -39,7 +39,7 @@ ProgramNode(0...118)( "j" ), CallNode(82...98)( - CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 0, "k"), + CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 2, "k"), (96...97), (97...98), nil, @@ -50,7 +50,7 @@ ProgramNode(0...118)( "l" ), CallNode(100...118)( - CallNode(100...101)(nil, nil, (100...101), nil, nil, nil, nil, 0, "m"), + CallNode(100...101)(nil, nil, (100...101), nil, nil, nil, nil, 2, "m"), (115...117), (117...118), nil, diff --git a/test/yarp/snapshots/constants.txt b/test/yarp/snapshots/constants.txt index 5469144be39f09..7e82efd5b662cc 100644 --- a/test/yarp/snapshots/constants.txt +++ b/test/yarp/snapshots/constants.txt @@ -16,7 +16,7 @@ ProgramNode(0...715)( (10...12) ), ConstantPathNode(15...19)( - CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 0, "a"), + CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 2, "a"), ConstantReadNode(18...19)(), (16...18) ), @@ -715,7 +715,7 @@ ProgramNode(0...715)( CallNode(615...620)( ConstantReadNode(615...616)(), (616...618), - (619...620), + (618...619), nil, ArgumentsNode(619...620)( [CallNode(619...620)( @@ -726,19 +726,19 @@ ProgramNode(0...715)( nil, nil, nil, - 0, + 2, "i" )] ), nil, nil, 0, - "i" + "%" ), CallNode(622...627)( ConstantReadNode(622...623)(), (623...625), - (626...627), + (625...626), nil, ArgumentsNode(626...627)( [CallNode(626...627)( @@ -749,19 +749,19 @@ ProgramNode(0...715)( nil, nil, nil, - 0, + 2, "w" )] ), nil, nil, 0, - "w" + "%" ), CallNode(629...634)( ConstantReadNode(629...630)(), (630...632), - (633...634), + (632...633), nil, ArgumentsNode(633...634)( [CallNode(633...634)( @@ -772,36 +772,36 @@ ProgramNode(0...715)( nil, nil, nil, - 0, + 2, "x" )] ), nil, nil, 0, - "x" + "%" ), CallNode(636...641)( ConstantReadNode(636...637)(), (637...639), - (640...641), + (639...640), nil, ArgumentsNode(640...641)([ConstantReadNode(640...641)()]), nil, nil, 0, - "I" + "%" ), CallNode(643...648)( ConstantReadNode(643...644)(), (644...646), - (647...648), + (646...647), nil, ArgumentsNode(647...648)([ConstantReadNode(647...648)()]), nil, nil, 0, - "W" + "%" ), CallNode(650...654)( ConstantReadNode(650...651)(), diff --git a/test/yarp/snapshots/dash_heredocs.txt b/test/yarp/snapshots/dash_heredocs.txt index ad79c4625173f2..0745fd81ef94a6 100644 --- a/test/yarp/snapshots/dash_heredocs.txt +++ b/test/yarp/snapshots/dash_heredocs.txt @@ -41,7 +41,7 @@ ProgramNode(0...231)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -74,7 +74,7 @@ ProgramNode(0...231)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -97,7 +97,7 @@ ProgramNode(0...231)( nil, nil, nil, - 0, + 2, "b" )] ), diff --git a/test/yarp/snapshots/defined.txt b/test/yarp/snapshots/defined.txt index df02a1d10d720b..4d0b377a8a7ac1 100644 --- a/test/yarp/snapshots/defined.txt +++ b/test/yarp/snapshots/defined.txt @@ -21,8 +21,8 @@ ProgramNode(0...78)( DefinedNode(45...66)( (53...54), AndNode(54...65)( - CallNode(54...57)(nil, nil, (54...57), nil, nil, nil, nil, 0, "foo"), - CallNode(62...65)(nil, nil, (62...65), nil, nil, nil, nil, 0, "bar"), + CallNode(54...57)(nil, nil, (54...57), nil, nil, nil, nil, 2, "foo"), + CallNode(62...65)(nil, nil, (62...65), nil, nil, nil, nil, 2, "bar"), (58...61) ), (65...66), diff --git a/test/yarp/snapshots/hashes.txt b/test/yarp/snapshots/hashes.txt index 41c166bb2783d5..cfd3e04f163653 100644 --- a/test/yarp/snapshots/hashes.txt +++ b/test/yarp/snapshots/hashes.txt @@ -6,13 +6,13 @@ ProgramNode(0...120)( HashNode(9...27)( (9...10), [AssocNode(11...17)( - CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 0, "a"), - CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 0, "b"), + CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 2, "a"), + CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 2, "b"), (13...15) ), AssocNode(19...25)( - CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 0, "c"), - CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 0, "d"), + CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 2, "c"), + CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 2, "d"), (21...23) )], (26...27) @@ -20,12 +20,12 @@ ProgramNode(0...120)( HashNode(29...44)( (29...30), [AssocNode(31...37)( - CallNode(31...32)(nil, nil, (31...32), nil, nil, nil, nil, 0, "a"), - CallNode(36...37)(nil, nil, (36...37), nil, nil, nil, nil, 0, "b"), + CallNode(31...32)(nil, nil, (31...32), nil, nil, nil, nil, 2, "a"), + CallNode(36...37)(nil, nil, (36...37), nil, nil, nil, nil, 2, "b"), (33...35) ), AssocSplatNode(39...42)( - CallNode(41...42)(nil, nil, (41...42), nil, nil, nil, nil, 0, "c"), + CallNode(41...42)(nil, nil, (41...42), nil, nil, nil, nil, 2, "c"), (39...41) )], (43...44) @@ -34,12 +34,12 @@ ProgramNode(0...120)( (46...47), [AssocNode(54...58)( SymbolNode(54...56)(nil, (54...55), (55...56), "a"), - CallNode(57...58)(nil, nil, (57...58), nil, nil, nil, nil, 0, "b"), + CallNode(57...58)(nil, nil, (57...58), nil, nil, nil, nil, 2, "b"), nil ), AssocNode(66...70)( SymbolNode(66...68)(nil, (66...67), (67...68), "c"), - CallNode(69...70)(nil, nil, (69...70), nil, nil, nil, nil, 0, "d"), + CallNode(69...70)(nil, nil, (69...70), nil, nil, nil, nil, 2, "d"), nil )], (78...79) @@ -48,16 +48,16 @@ ProgramNode(0...120)( (81...82), [AssocNode(83...87)( SymbolNode(83...85)(nil, (83...84), (84...85), "a"), - CallNode(86...87)(nil, nil, (86...87), nil, nil, nil, nil, 0, "b"), + CallNode(86...87)(nil, nil, (86...87), nil, nil, nil, nil, 2, "b"), nil ), AssocNode(89...93)( SymbolNode(89...91)(nil, (89...90), (90...91), "c"), - CallNode(92...93)(nil, nil, (92...93), nil, nil, nil, nil, 0, "d"), + CallNode(92...93)(nil, nil, (92...93), nil, nil, nil, nil, 2, "d"), nil ), AssocSplatNode(95...98)( - CallNode(97...98)(nil, nil, (97...98), nil, nil, nil, nil, 0, "e"), + CallNode(97...98)(nil, nil, (97...98), nil, nil, nil, nil, 2, "e"), (95...97) ), AssocNode(100...104)( @@ -70,7 +70,7 @@ ProgramNode(0...120)( nil, nil, nil, - 0, + 2, "g" ), nil diff --git a/test/yarp/snapshots/if.txt b/test/yarp/snapshots/if.txt index 1dc934f73ad9d6..c12691abfe5c2d 100644 --- a/test/yarp/snapshots/if.txt +++ b/test/yarp/snapshots/if.txt @@ -80,7 +80,7 @@ ProgramNode(0...382)( nil, nil, nil, - 0, + 2, "exit_loop" ), StatementsNode(188...196)( @@ -102,7 +102,7 @@ ProgramNode(0...382)( nil, nil, nil, - 0, + 2, "foo" ), StatementsNode(214...217)( @@ -114,7 +114,7 @@ ProgramNode(0...382)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -123,7 +123,7 @@ ProgramNode(0...382)( ), IfNode(223...234)( (230...232), - CallNode(233...234)(nil, nil, (233...234), nil, nil, nil, nil, 0, "c"), + CallNode(233...234)(nil, nil, (233...234), nil, nil, nil, nil, 2, "c"), StatementsNode(223...229)( [IfNode(223...229)( (225...227), @@ -135,7 +135,7 @@ ProgramNode(0...382)( nil, nil, nil, - 0, + 2, "b" ), StatementsNode(223...224)( @@ -147,7 +147,7 @@ ProgramNode(0...382)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -196,7 +196,7 @@ ProgramNode(0...382)( nil, nil, nil, - 0, + 2, "type" ), IntegerNode(272...273)(), @@ -214,7 +214,7 @@ ProgramNode(0...382)( nil, nil, nil, - 0, + 2, "type" ), ConstantReadNode(288...289)(), diff --git a/test/yarp/snapshots/lambda.txt b/test/yarp/snapshots/lambda.txt index 9d62e3d079ff24..bf59e6aa6848b2 100644 --- a/test/yarp/snapshots/lambda.txt +++ b/test/yarp/snapshots/lambda.txt @@ -45,7 +45,7 @@ ProgramNode(0...51)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -83,7 +83,7 @@ ProgramNode(0...51)( nil, nil, nil, - 0, + 2, "b" ), nil, diff --git a/test/yarp/snapshots/method_calls.txt b/test/yarp/snapshots/method_calls.txt index 719f07e0eb443d..f59fb7e46d0bf9 100644 --- a/test/yarp/snapshots/method_calls.txt +++ b/test/yarp/snapshots/method_calls.txt @@ -1,8 +1,8 @@ -ProgramNode(0...1187)( +ProgramNode(0...1237)( [], - StatementsNode(0...1187)( + StatementsNode(0...1237)( [CallNode(0...14)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...7), nil, @@ -15,13 +15,13 @@ ProgramNode(0...1187)( "bar" ), CallNode(16...25)( - CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 0, "a"), + CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 2, "a"), (17...18), (18...19), (19...20), ArgumentsNode(20...24)( - [CallNode(20...21)(nil, nil, (20...21), nil, nil, nil, nil, 0, "c"), - CallNode(23...24)(nil, nil, (23...24), nil, nil, nil, nil, 0, "d")] + [CallNode(20...21)(nil, nil, (20...21), nil, nil, nil, nil, 2, "c"), + CallNode(23...24)(nil, nil, (23...24), nil, nil, nil, nil, 2, "d")] ), (24...25), nil, @@ -29,7 +29,7 @@ ProgramNode(0...1187)( "b" ), CallNode(27...32)( - CallNode(27...28)(nil, nil, (27...28), nil, nil, nil, nil, 0, "a"), + CallNode(27...28)(nil, nil, (27...28), nil, nil, nil, nil, 2, "a"), (28...29), (29...30), (30...31), @@ -41,7 +41,7 @@ ProgramNode(0...1187)( ), CallNode(34...52)( CallNode(34...44)( - CallNode(34...37)(nil, nil, (34...37), nil, nil, nil, nil, 0, "foo"), + CallNode(34...37)(nil, nil, (34...37), nil, nil, nil, nil, 2, "foo"), (40...41), (41...44), nil, @@ -62,7 +62,7 @@ ProgramNode(0...1187)( ), CallNode(54...56)(nil, nil, (54...56), nil, nil, nil, nil, 0, "a!"), CallNode(58...62)( - CallNode(58...59)(nil, nil, (58...59), nil, nil, nil, nil, 0, "a"), + CallNode(58...59)(nil, nil, (58...59), nil, nil, nil, nil, 2, "a"), (59...60), (0...0), (60...61), @@ -73,7 +73,7 @@ ProgramNode(0...1187)( "call" ), CallNode(64...75)( - CallNode(64...65)(nil, nil, (64...65), nil, nil, nil, nil, 0, "a"), + CallNode(64...65)(nil, nil, (64...65), nil, nil, nil, nil, 2, "a"), (65...66), (0...0), (66...67), @@ -88,7 +88,7 @@ ProgramNode(0...1187)( "call" ), CallNode(77...81)( - CallNode(77...78)(nil, nil, (77...78), nil, nil, nil, nil, 0, "a"), + CallNode(77...78)(nil, nil, (77...78), nil, nil, nil, nil, 2, "a"), (78...80), (80...81), nil, @@ -98,87 +98,100 @@ ProgramNode(0...1187)( 0, "b" ), - CallNode(83...94)( - CallNode(83...86)(nil, nil, (83...86), nil, nil, nil, nil, 0, "foo"), + CallNode(83...89)( + CallNode(83...84)(nil, nil, (83...84), nil, nil, nil, nil, 2, "a"), + (84...86), (86...87), - (87...90), nil, - ArgumentsNode(93...94)([IntegerNode(93...94)()]), + ArgumentsNode(88...89)( + [CallNode(88...89)(nil, nil, (88...89), nil, nil, nil, nil, 2, "c")] + ), + nil, + nil, + 0, + "b" + ), + CallNode(91...102)( + CallNode(91...94)(nil, nil, (91...94), nil, nil, nil, nil, 2, "foo"), + (94...95), + (95...98), + nil, + ArgumentsNode(101...102)([IntegerNode(101...102)()]), nil, nil, 0, "bar=" ), - CallNode(96...98)(nil, nil, (96...98), nil, nil, nil, nil, 0, "a?"), - CallNode(100...109)( + CallNode(104...106)(nil, nil, (104...106), nil, nil, nil, nil, 0, "a?"), + CallNode(108...117)( nil, nil, - (100...101), - (101...102), - ArgumentsNode(102...108)( - [BlockArgumentNode(102...108)( - CallNode(103...108)( + (108...109), + (109...110), + ArgumentsNode(110...116)( + [BlockArgumentNode(110...116)( + CallNode(111...116)( nil, nil, - (103...108), + (111...116), nil, nil, nil, nil, - 0, + 2, "block" ), - (102...103) + (110...111) )] ), - (108...109), + (116...117), nil, 0, "a" ), - CallNode(111...122)( + CallNode(119...130)( nil, nil, - (111...112), - (112...113), - ArgumentsNode(113...121)( - [KeywordHashNode(113...121)( - [AssocSplatNode(113...121)( - CallNode(115...121)( + (119...120), + (120...121), + ArgumentsNode(121...129)( + [KeywordHashNode(121...129)( + [AssocSplatNode(121...129)( + CallNode(123...129)( nil, nil, - (115...121), + (123...129), nil, nil, nil, nil, - 0, + 2, "kwargs" ), - (113...115) + (121...123) )] )] ), - (121...122), + (129...130), nil, 0, "a" ), - CallNode(124...129)( - CallNode(124...127)( - CallNode(124...125)( + CallNode(132...137)( + CallNode(132...135)( + CallNode(132...133)( nil, nil, - (124...125), + (132...133), nil, nil, nil, nil, - 0, + 2, "a" ), - (125...126), - (126...127), + (133...134), + (134...135), nil, nil, nil, @@ -186,8 +199,8 @@ ProgramNode(0...1187)( 0, "b" ), - (127...128), - (128...129), + (135...136), + (136...137), nil, nil, nil, @@ -195,103 +208,103 @@ ProgramNode(0...1187)( 0, "c" ), - CallNode(131...138)( + CallNode(139...146)( nil, nil, - (131...132), - (132...133), - ArgumentsNode(133...137)( - [CallNode(133...134)( + (139...140), + (140...141), + ArgumentsNode(141...145)( + [CallNode(141...142)( nil, nil, - (133...134), + (141...142), nil, nil, nil, nil, - 0, + 2, "b" ), - CallNode(136...137)( + CallNode(144...145)( nil, nil, - (136...137), + (144...145), nil, nil, nil, nil, - 0, + 2, "c" )] ), - (137...138), + (145...146), nil, 0, "a" ), - CallNode(140...143)( + CallNode(148...151)( nil, nil, - (140...141), - (141...142), + (148...149), + (149...150), nil, - (142...143), + (150...151), nil, 0, "a" ), - CallNode(145...153)( + CallNode(153...161)( nil, nil, - (145...146), - (146...147), - ArgumentsNode(147...152)( - [SplatNode(147...152)( - (147...148), - CallNode(148...152)( + (153...154), + (154...155), + ArgumentsNode(155...160)( + [SplatNode(155...160)( + (155...156), + CallNode(156...160)( nil, nil, - (148...152), + (156...160), nil, nil, nil, nil, - 0, + 2, "args" ) )] ), - (152...153), + (160...161), nil, 0, "a" ), - CallNode(155...161)( + CallNode(163...169)( nil, nil, - (155...156), + (163...164), nil, - ArgumentsNode(157...161)( - [CallNode(157...158)( + ArgumentsNode(165...169)( + [CallNode(165...166)( nil, nil, - (157...158), + (165...166), nil, nil, nil, nil, - 0, + 2, "b" ), - CallNode(160...161)( + CallNode(168...169)( nil, nil, - (160...161), + (168...169), nil, nil, nil, nil, - 0, + 2, "c" )] ), @@ -300,32 +313,32 @@ ProgramNode(0...1187)( 0, "a" ), - CallNode(163...171)( - CallNode(163...164)(nil, nil, (163...164), nil, nil, nil, nil, 0, "a"), - (164...165), - (165...166), + CallNode(171...179)( + CallNode(171...172)(nil, nil, (171...172), nil, nil, nil, nil, 2, "a"), + (172...173), + (173...174), nil, - ArgumentsNode(167...171)( - [CallNode(167...168)( + ArgumentsNode(175...179)( + [CallNode(175...176)( nil, nil, - (167...168), + (175...176), nil, nil, nil, nil, - 0, + 2, "c" ), - CallNode(170...171)( + CallNode(178...179)( nil, nil, - (170...171), + (178...179), nil, nil, nil, nil, - 0, + 2, "d" )] ), @@ -334,21 +347,21 @@ ProgramNode(0...1187)( 0, "b" ), - MultiWriteNode(173...196)( - [CallNode(173...180)( - CallNode(173...176)( + MultiWriteNode(181...204)( + [CallNode(181...188)( + CallNode(181...184)( nil, nil, - (173...176), + (181...184), nil, nil, nil, nil, - 0, + 2, "foo" ), - (176...177), - (177...180), + (184...185), + (185...188), nil, nil, nil, @@ -356,20 +369,20 @@ ProgramNode(0...1187)( 0, "foo=" ), - CallNode(182...189)( - CallNode(182...185)( + CallNode(190...197)( + CallNode(190...193)( nil, nil, - (182...185), + (190...193), nil, nil, nil, nil, - 0, + 2, "bar" ), - (185...186), - (186...189), + (193...194), + (194...197), nil, nil, nil, @@ -377,19 +390,19 @@ ProgramNode(0...1187)( 0, "bar=" )], - (190...191), - ArrayNode(192...196)( - [IntegerNode(192...193)(), IntegerNode(195...196)()], + (198...199), + ArrayNode(200...204)( + [IntegerNode(200...201)(), IntegerNode(203...204)()], nil, nil ), nil, nil ), - CallNode(198...202)( - CallNode(198...199)(nil, nil, (198...199), nil, nil, nil, nil, 0, "a"), - (199...201), - (201...202), + CallNode(206...210)( + CallNode(206...207)(nil, nil, (206...207), nil, nil, nil, nil, 2, "a"), + (207...209), + (209...210), nil, nil, nil, @@ -397,59 +410,59 @@ ProgramNode(0...1187)( 1, "b" ), - CallNode(204...209)( - CallNode(204...205)(nil, nil, (204...205), nil, nil, nil, nil, 0, "a"), - (205...207), + CallNode(212...217)( + CallNode(212...213)(nil, nil, (212...213), nil, nil, nil, nil, 2, "a"), + (213...215), (0...0), - (207...208), + (215...216), nil, - (208...209), + (216...217), nil, 1, "call" ), - CallNode(211...218)( - CallNode(211...212)(nil, nil, (211...212), nil, nil, nil, nil, 0, "a"), - (212...214), - (214...215), - (215...216), - ArgumentsNode(216...217)( - [CallNode(216...217)( + CallNode(219...226)( + CallNode(219...220)(nil, nil, (219...220), nil, nil, nil, nil, 2, "a"), + (220...222), + (222...223), + (223...224), + ArgumentsNode(224...225)( + [CallNode(224...225)( nil, nil, - (216...217), + (224...225), nil, nil, nil, nil, - 0, + 2, "c" )] ), - (217...218), + (225...226), nil, 1, "b" ), - CallNode(220...226)( - CallNode(220...221)(nil, nil, (220...221), nil, nil, nil, nil, 0, "a"), - (221...223), - (223...224), - (224...225), + CallNode(228...234)( + CallNode(228...229)(nil, nil, (228...229), nil, nil, nil, nil, 2, "a"), + (229...231), + (231...232), + (232...233), nil, - (225...226), + (233...234), nil, 1, "b" ), - IfNode(228...261)( - (239...241), - AndNode(242...261)( - OrNode(242...253)( - CallNode(242...246)( + IfNode(236...269)( + (247...249), + AndNode(250...269)( + OrNode(250...261)( + CallNode(250...254)( nil, nil, - (242...246), + (250...254), nil, nil, nil, @@ -457,41 +470,41 @@ ProgramNode(0...1187)( 0, "bar?" ), - CallNode(250...253)( + CallNode(258...261)( nil, nil, - (250...253), + (258...261), nil, nil, nil, nil, - 0, + 2, "baz" ), - (247...249) + (255...257) ), - CallNode(258...261)( + CallNode(266...269)( nil, nil, - (258...261), + (266...269), nil, nil, nil, nil, - 0, + 2, "qux" ), - (254...257) + (262...265) ), - StatementsNode(228...238)( - [CallNode(228...238)( + StatementsNode(236...246)( + [CallNode(236...246)( nil, nil, - (228...231), + (236...239), nil, - ArgumentsNode(232...238)( - [SymbolNode(232...234)((232...233), (233...234), nil, "a"), - SymbolNode(236...238)((236...237), (237...238), nil, "b")] + ArgumentsNode(240...246)( + [SymbolNode(240...242)((240...241), (241...242), nil, "a"), + SymbolNode(244...246)((244...245), (245...246), nil, "b")] ), nil, nil, @@ -502,104 +515,104 @@ ProgramNode(0...1187)( nil, nil ), - CallNode(263...278)( + CallNode(271...286)( nil, nil, - (263...266), - (266...267), - ArgumentsNode(267...276)( - [SymbolNode(267...269)((267...268), (268...269), nil, "a"), - SymbolNode(274...276)((274...275), (275...276), nil, "b")] + (271...274), + (274...275), + ArgumentsNode(275...284)( + [SymbolNode(275...277)((275...276), (276...277), nil, "a"), + SymbolNode(282...284)((282...283), (283...284), nil, "b")] ), - (277...278), + (285...286), nil, 0, "foo" ), - CallNode(280...290)( + CallNode(288...298)( nil, nil, - (280...283), - (283...284), - ArgumentsNode(284...289)( - [SplatNode(284...289)( - (284...285), - CallNode(285...289)( + (288...291), + (291...292), + ArgumentsNode(292...297)( + [SplatNode(292...297)( + (292...293), + CallNode(293...297)( nil, nil, - (285...289), + (293...297), nil, nil, nil, nil, - 0, + 2, "rest" ) )] ), - (289...290), + (297...298), nil, 0, "foo" ), - CallNode(292...332)( - nil, - nil, - (292...295), - (295...296), - ArgumentsNode(296...331)( - [SymbolNode(296...298)((296...297), (297...298), nil, "a"), - KeywordHashNode(300...324)( - [AssocNode(300...314)( - SymbolNode(300...302)((300...301), (301...302), nil, "h"), - ArrayNode(306...314)( - [SymbolNode(307...309)((307...308), (308...309), nil, "x"), - SymbolNode(311...313)((311...312), (312...313), nil, "y")], - (306...307), - (313...314) + CallNode(300...340)( + nil, + nil, + (300...303), + (303...304), + ArgumentsNode(304...339)( + [SymbolNode(304...306)((304...305), (305...306), nil, "a"), + KeywordHashNode(308...332)( + [AssocNode(308...322)( + SymbolNode(308...310)((308...309), (309...310), nil, "h"), + ArrayNode(314...322)( + [SymbolNode(315...317)((315...316), (316...317), nil, "x"), + SymbolNode(319...321)((319...320), (320...321), nil, "y")], + (314...315), + (321...322) ), - (303...305) + (311...313) ), - AssocNode(316...324)( - SymbolNode(316...318)((316...317), (317...318), nil, "a"), - SymbolNode(322...324)((322...323), (323...324), nil, "b"), - (319...321) + AssocNode(324...332)( + SymbolNode(324...326)((324...325), (325...326), nil, "a"), + SymbolNode(330...332)((330...331), (331...332), nil, "b"), + (327...329) )] ), - BlockArgumentNode(326...331)( - SymbolNode(327...331)((327...328), (328...331), nil, "bar"), - (326...327) + BlockArgumentNode(334...339)( + SymbolNode(335...339)((335...336), (336...339), nil, "bar"), + (334...335) )] ), - (331...332), + (339...340), nil, 0, "foo" ), - CallNode(334...383)( + CallNode(342...391)( nil, nil, - (334...336), + (342...344), nil, - ArgumentsNode(337...383)( - [IntegerNode(337...340)(), - HashNode(342...383)( - (342...343), - [AssocNode(344...361)( - SymbolNode(344...350)((344...345), (345...350), nil, "there"), - SymbolNode(354...361)((354...355), (355...361), nil, "friend"), - (351...353) + ArgumentsNode(345...391)( + [IntegerNode(345...348)(), + HashNode(350...391)( + (350...351), + [AssocNode(352...369)( + SymbolNode(352...358)((352...353), (353...358), nil, "there"), + SymbolNode(362...369)((362...363), (363...369), nil, "friend"), + (359...361) ), - AssocSplatNode(363...367)( - HashNode(365...367)((365...366), [], (366...367)), - (363...365) + AssocSplatNode(371...375)( + HashNode(373...375)((373...374), [], (374...375)), + (371...373) ), - AssocNode(369...381)( - SymbolNode(369...376)(nil, (369...375), (375...376), "whatup"), - SymbolNode(377...381)((377...378), (378...381), nil, "dog"), + AssocNode(377...389)( + SymbolNode(377...384)(nil, (377...383), (383...384), "whatup"), + SymbolNode(385...389)((385...386), (386...389), nil, "dog"), nil )], - (382...383) + (390...391) )] ), nil, @@ -607,28 +620,28 @@ ProgramNode(0...1187)( 0, "hi" ), - CallNode(385...421)( + CallNode(393...429)( nil, nil, - (385...388), + (393...396), nil, - ArgumentsNode(389...400)( - [SymbolNode(389...391)((389...390), (390...391), nil, "a"), - KeywordHashNode(393...400)( - [AssocNode(393...400)( - SymbolNode(393...395)(nil, (393...394), (394...395), "b"), - TrueNode(396...400)(), + ArgumentsNode(397...408)( + [SymbolNode(397...399)((397...398), (398...399), nil, "a"), + KeywordHashNode(401...408)( + [AssocNode(401...408)( + SymbolNode(401...403)(nil, (401...402), (402...403), "b"), + TrueNode(404...408)(), nil )] )] ), nil, - BlockNode(401...421)( + BlockNode(409...429)( [:a, :b], - BlockParametersNode(404...410)( - ParametersNode(405...409)( - [RequiredParameterNode(405...406)(:a), - RequiredParameterNode(408...409)(:b)], + BlockParametersNode(412...418)( + ParametersNode(413...417)( + [RequiredParameterNode(413...414)(:a), + RequiredParameterNode(416...417)(:b)], [], [], nil, @@ -637,17 +650,17 @@ ProgramNode(0...1187)( nil ), [], - (404...405), - (409...410) + (412...413), + (417...418) ), - StatementsNode(411...417)( - [CallNode(411...417)( + StatementsNode(419...425)( + [CallNode(419...425)( nil, nil, - (411...415), + (419...423), nil, - ArgumentsNode(416...417)( - [LocalVariableReadNode(416...417)(:a, 0)] + ArgumentsNode(424...425)( + [LocalVariableReadNode(424...425)(:a, 0)] ), nil, nil, @@ -655,22 +668,22 @@ ProgramNode(0...1187)( "puts" )] ), - (401...403), - (418...421) + (409...411), + (426...429) ), 0, "foo" ), - CallNode(423...440)( + CallNode(431...448)( nil, nil, - (423...425), + (431...433), nil, - ArgumentsNode(426...440)( - [KeywordHashNode(426...440)( - [AssocNode(426...440)( - SymbolNode(426...432)(nil, (426...431), (431...432), "there"), - SymbolNode(433...440)((433...434), (434...440), nil, "friend"), + ArgumentsNode(434...448)( + [KeywordHashNode(434...448)( + [AssocNode(434...448)( + SymbolNode(434...440)(nil, (434...439), (439...440), "there"), + SymbolNode(441...448)((441...442), (442...448), nil, "friend"), nil )] )] @@ -680,25 +693,25 @@ ProgramNode(0...1187)( 0, "hi" ), - CallNode(442...482)( + CallNode(450...490)( nil, nil, - (442...444), + (450...452), nil, - ArgumentsNode(445...482)( - [KeywordHashNode(445...482)( - [AssocNode(445...462)( - SymbolNode(445...451)((445...446), (446...451), nil, "there"), - SymbolNode(455...462)((455...456), (456...462), nil, "friend"), - (452...454) + ArgumentsNode(453...490)( + [KeywordHashNode(453...490)( + [AssocNode(453...470)( + SymbolNode(453...459)((453...454), (454...459), nil, "there"), + SymbolNode(463...470)((463...464), (464...470), nil, "friend"), + (460...462) ), - AssocSplatNode(464...468)( - HashNode(466...468)((466...467), [], (467...468)), - (464...466) + AssocSplatNode(472...476)( + HashNode(474...476)((474...475), [], (475...476)), + (472...474) ), - AssocNode(470...482)( - SymbolNode(470...477)(nil, (470...476), (476...477), "whatup"), - SymbolNode(478...482)((478...479), (479...482), nil, "dog"), + AssocNode(478...490)( + SymbolNode(478...485)(nil, (478...484), (484...485), "whatup"), + SymbolNode(486...490)((486...487), (487...490), nil, "dog"), nil )] )] @@ -708,75 +721,75 @@ ProgramNode(0...1187)( 0, "hi" ), - CallNode(484...525)( + CallNode(492...533)( nil, nil, - (484...486), - (486...487), - ArgumentsNode(487...524)( - [KeywordHashNode(487...524)( - [AssocNode(487...504)( - SymbolNode(487...493)((487...488), (488...493), nil, "there"), - SymbolNode(497...504)((497...498), (498...504), nil, "friend"), - (494...496) + (492...494), + (494...495), + ArgumentsNode(495...532)( + [KeywordHashNode(495...532)( + [AssocNode(495...512)( + SymbolNode(495...501)((495...496), (496...501), nil, "there"), + SymbolNode(505...512)((505...506), (506...512), nil, "friend"), + (502...504) ), - AssocSplatNode(506...510)( - HashNode(508...510)((508...509), [], (509...510)), - (506...508) + AssocSplatNode(514...518)( + HashNode(516...518)((516...517), [], (517...518)), + (514...516) ), - AssocNode(512...524)( - SymbolNode(512...519)(nil, (512...518), (518...519), "whatup"), - SymbolNode(520...524)((520...521), (521...524), nil, "dog"), + AssocNode(520...532)( + SymbolNode(520...527)(nil, (520...526), (526...527), "whatup"), + SymbolNode(528...532)((528...529), (529...532), nil, "dog"), nil )] )] ), - (524...525), + (532...533), nil, 0, "hi" ), - CallNode(527...563)( + CallNode(535...571)( nil, nil, - (527...530), - (530...531), - ArgumentsNode(531...562)( - [HashNode(531...553)( - (531...532), - [AssocNode(533...540)( - SymbolNode(533...535)(nil, (533...534), (534...535), "a"), - TrueNode(536...540)(), + (535...538), + (538...539), + ArgumentsNode(539...570)( + [HashNode(539...561)( + (539...540), + [AssocNode(541...548)( + SymbolNode(541...543)(nil, (541...542), (542...543), "a"), + TrueNode(544...548)(), nil ), - AssocNode(542...550)( - SymbolNode(542...544)(nil, (542...543), (543...544), "b"), - FalseNode(545...550)(), + AssocNode(550...558)( + SymbolNode(550...552)(nil, (550...551), (551...552), "b"), + FalseNode(553...558)(), nil )], - (552...553) + (560...561) ), - BlockArgumentNode(555...562)( - SymbolNode(556...562)((556...557), (557...562), nil, "block"), - (555...556) + BlockArgumentNode(563...570)( + SymbolNode(564...570)((564...565), (565...570), nil, "block"), + (563...564) )] ), - (562...563), + (570...571), nil, 0, "foo" ), - CallNode(565...585)( + CallNode(573...593)( nil, nil, - (565...567), + (573...575), nil, - ArgumentsNode(568...585)( - [KeywordHashNode(568...585)( - [AssocNode(568...585)( - SymbolNode(568...574)((568...569), (569...574), nil, "there"), - SymbolNode(578...585)((578...579), (579...585), nil, "friend"), - (575...577) + ArgumentsNode(576...593)( + [KeywordHashNode(576...593)( + [AssocNode(576...593)( + SymbolNode(576...582)((576...577), (577...582), nil, "there"), + SymbolNode(586...593)((586...587), (587...593), nil, "friend"), + (583...585) )] )] ), @@ -785,61 +798,77 @@ ProgramNode(0...1187)( 0, "hi" ), - CallNode(587...600)( + CallNode(595...608)( nil, nil, - (587...590), - (590...591), - ArgumentsNode(591...597)( - [SymbolNode(591...593)((591...592), (592...593), nil, "a"), - SymbolNode(595...597)((595...596), (596...597), nil, "b")] + (595...598), + (598...599), + ArgumentsNode(599...605)( + [SymbolNode(599...601)((599...600), (600...601), nil, "a"), + SymbolNode(603...605)((603...604), (604...605), nil, "b")] ), - (599...600), + (607...608), nil, 0, "foo" ), - CallNode(602...619)( + CallNode(610...627)( nil, nil, - (602...605), - (605...606), - ArgumentsNode(607...616)( - [SymbolNode(607...609)((607...608), (608...609), nil, "a"), - KeywordHashNode(611...616)( - [AssocNode(611...616)( - SymbolNode(611...613)(nil, (611...612), (612...613), "b"), - SymbolNode(614...616)((614...615), (615...616), nil, "c"), + (610...613), + (613...614), + ArgumentsNode(615...624)( + [SymbolNode(615...617)((615...616), (616...617), nil, "a"), + KeywordHashNode(619...624)( + [AssocNode(619...624)( + SymbolNode(619...621)(nil, (619...620), (620...621), "b"), + SymbolNode(622...624)((622...623), (623...624), nil, "c"), nil )] )] ), - (618...619), + (626...627), + nil, + 0, + "foo" + ), + CallNode(629...640)( + nil, + nil, + (629...632), + nil, + ArgumentsNode(633...640)( + [BlockArgumentNode(633...640)( + SymbolNode(634...640)((634...635), (635...640), nil, "block"), + (633...634) + )] + ), + nil, nil, 0, "foo" ), - CallNode(621...651)( + CallNode(642...672)( nil, nil, - (621...624), + (642...645), nil, - ArgumentsNode(625...651)( - [KeywordHashNode(625...642)( - [AssocNode(625...632)( - SymbolNode(625...627)(nil, (625...626), (626...627), "a"), - TrueNode(628...632)(), + ArgumentsNode(646...672)( + [KeywordHashNode(646...663)( + [AssocNode(646...653)( + SymbolNode(646...648)(nil, (646...647), (647...648), "a"), + TrueNode(649...653)(), nil ), - AssocNode(634...642)( - SymbolNode(634...636)(nil, (634...635), (635...636), "b"), - FalseNode(637...642)(), + AssocNode(655...663)( + SymbolNode(655...657)(nil, (655...656), (656...657), "b"), + FalseNode(658...663)(), nil )] ), - BlockArgumentNode(644...651)( - SymbolNode(645...651)((645...646), (646...651), nil, "block"), - (644...645) + BlockArgumentNode(665...672)( + SymbolNode(666...672)((666...667), (667...672), nil, "block"), + (665...666) )] ), nil, @@ -847,17 +876,17 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(653...674)( + CallNode(674...695)( nil, nil, - (653...662), + (674...683), nil, - ArgumentsNode(663...674)( - [IntegerNode(663...664)(), - KeywordHashNode(666...674)( - [AssocNode(666...674)( - SymbolNode(666...672)(nil, (666...671), (671...672), "kwarg"), - IntegerNode(673...674)(), + ArgumentsNode(684...695)( + [IntegerNode(684...685)(), + KeywordHashNode(687...695)( + [AssocNode(687...695)( + SymbolNode(687...693)(nil, (687...692), (692...693), "kwarg"), + IntegerNode(694...695)(), nil )] )] @@ -867,178 +896,168 @@ ProgramNode(0...1187)( 0, "some_func" ), - CallNode(676...694)( - ConstantReadNode(676...682)(), - (682...683), - (683...690), - (690...691), - ArgumentsNode(691...693)([IntegerNode(691...693)()]), - (693...694), + CallNode(697...715)( + ConstantReadNode(697...703)(), + (703...704), + (704...711), + (711...712), + ArgumentsNode(712...714)([IntegerNode(712...714)()]), + (714...715), nil, 0, "Integer" ), - CallNode(696...706)( - CallNode(696...697)(nil, nil, (696...697), nil, nil, nil, nil, 0, "x"), - (697...698), - (698...702), + CallNode(717...727)( + CallNode(717...718)(nil, nil, (717...718), nil, nil, nil, nil, 2, "x"), + (718...719), + (719...723), nil, nil, nil, - BlockNode(703...706)([], nil, nil, (703...704), (705...706)), + BlockNode(724...727)([], nil, nil, (724...725), (726...727)), 0, "each" ), - CallNode(708...722)( - CallNode(708...711)( + CallNode(729...743)( + CallNode(729...732)( nil, nil, - (708...711), + (729...732), nil, nil, nil, nil, - 0, + 2, "foo" ), - (711...712), - (712...715), + (732...733), + (733...736), nil, nil, nil, - BlockNode(716...722)( + BlockNode(737...743)( [], nil, - StatementsNode(718...720)([BackReferenceReadNode(718...720)()]), - (716...717), - (721...722) + StatementsNode(739...741)([BackReferenceReadNode(739...741)()]), + (737...738), + (742...743) ), 0, "map" ), - CallNode(724...736)( - ConstantPathNode(724...728)( - ConstantReadNode(724...725)(), - ConstantReadNode(727...728)(), - (725...727) + CallNode(745...757)( + ConstantPathNode(745...749)( + ConstantReadNode(745...746)(), + ConstantReadNode(748...749)(), + (746...748) ), - (728...730), - (730...731), + (749...751), + (751...752), nil, - ArgumentsNode(732...736)( - [SymbolNode(732...736)((732...733), (733...736), nil, "foo")] + ArgumentsNode(753...757)( + [SymbolNode(753...757)((753...754), (754...757), nil, "foo")] ), nil, nil, 0, "C" ), - CallNode(738...751)( - ConstantPathNode(738...742)( - ConstantReadNode(738...739)(), - ConstantReadNode(741...742)(), - (739...741) + CallNode(759...772)( + ConstantPathNode(759...763)( + ConstantReadNode(759...760)(), + ConstantReadNode(762...763)(), + (760...762) ), - (742...744), - (744...745), - (745...746), - ArgumentsNode(746...750)( - [SymbolNode(746...750)((746...747), (747...750), nil, "foo")] + (763...765), + (765...766), + (766...767), + ArgumentsNode(767...771)( + [SymbolNode(767...771)((767...768), (768...771), nil, "foo")] ), - (750...751), + (771...772), nil, 0, "C" ), - CallNode(753...770)( - ConstantPathNode(753...757)( - ConstantReadNode(753...754)(), - ConstantReadNode(756...757)(), - (754...756) + CallNode(774...791)( + ConstantPathNode(774...778)( + ConstantReadNode(774...775)(), + ConstantReadNode(777...778)(), + (775...777) ), - (757...759), - (759...760), - (760...761), - ArgumentsNode(761...765)( - [SymbolNode(761...765)((761...762), (762...765), nil, "foo")] + (778...780), + (780...781), + (781...782), + ArgumentsNode(782...786)( + [SymbolNode(782...786)((782...783), (783...786), nil, "foo")] ), - (765...766), - BlockNode(767...770)([], nil, nil, (767...768), (769...770)), + (786...787), + BlockNode(788...791)([], nil, nil, (788...789), (790...791)), 0, "C" ), - CallNode(772...784)( - nil, - nil, - (772...775), - (775...776), - ArgumentsNode(776...783)( - [KeywordHashNode(776...783)( - [AssocNode(776...783)( - SymbolNode(776...780)( - (776...777), - (777...778), - (778...780), + CallNode(793...805)( + nil, + nil, + (793...796), + (796...797), + ArgumentsNode(797...804)( + [KeywordHashNode(797...804)( + [AssocNode(797...804)( + SymbolNode(797...801)( + (797...798), + (798...799), + (799...801), "a" ), - CallNode(781...783)( - IntegerNode(782...783)(), - nil, - (781...782), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + IntegerNode(802...804)(), nil )] )] ), - (783...784), + (804...805), nil, 0, "foo" ), - CallNode(786...814)( + CallNode(807...835)( nil, nil, - (786...789), + (807...810), nil, - ArgumentsNode(790...814)( - [KeywordHashNode(790...814)( - [AssocNode(790...814)( - SymbolNode(790...794)(nil, (790...793), (793...794), "bar"), - HashNode(795...814)( - (795...796), - [AssocNode(797...812)( - SymbolNode(797...801)( + ArgumentsNode(811...835)( + [KeywordHashNode(811...835)( + [AssocNode(811...835)( + SymbolNode(811...815)(nil, (811...814), (814...815), "bar"), + HashNode(816...835)( + (816...817), + [AssocNode(818...833)( + SymbolNode(818...822)( nil, - (797...800), - (800...801), + (818...821), + (821...822), "baz" ), - CallNode(802...812)( + CallNode(823...833)( nil, nil, - (802...805), + (823...826), nil, nil, nil, - BlockNode(806...812)( + BlockNode(827...833)( [], nil, nil, - (806...808), - (809...812) + (827...829), + (830...833) ), 0, "qux" ), nil )], - (813...814) + (834...835) ), nil )] @@ -1049,38 +1068,38 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(816...840)( + CallNode(837...861)( nil, nil, - (816...819), + (837...840), nil, - ArgumentsNode(820...840)( - [KeywordHashNode(820...840)( - [AssocNode(820...840)( - SymbolNode(820...824)(nil, (820...823), (823...824), "bar"), - HashNode(825...840)( - (825...826), - [AssocSplatNode(827...838)( - CallNode(829...838)( + ArgumentsNode(841...861)( + [KeywordHashNode(841...861)( + [AssocNode(841...861)( + SymbolNode(841...845)(nil, (841...844), (844...845), "bar"), + HashNode(846...861)( + (846...847), + [AssocSplatNode(848...859)( + CallNode(850...859)( nil, nil, - (829...831), + (850...852), nil, nil, nil, - BlockNode(832...838)( + BlockNode(853...859)( [], nil, nil, - (832...834), - (835...838) + (853...855), + (856...859) ), 0, "kw" ), - (827...829) + (848...850) )], - (839...840) + (860...861) ), nil )] @@ -1091,88 +1110,88 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(842...878)( + CallNode(863...899)( nil, nil, - (842...845), + (863...866), nil, - ArgumentsNode(846...871)( - [InterpolatedStringNode(846...871)( - (846...847), - [EmbeddedStatementsNode(847...870)( - (847...849), - StatementsNode(849...869)( - [CallNode(849...869)( - CallNode(849...852)( + ArgumentsNode(867...892)( + [InterpolatedStringNode(867...892)( + (867...868), + [EmbeddedStatementsNode(868...891)( + (868...870), + StatementsNode(870...890)( + [CallNode(870...890)( + CallNode(870...873)( nil, nil, - (849...852), + (870...873), nil, nil, nil, nil, - 0, + 2, "bar" ), - (852...853), - (853...856), + (873...874), + (874...877), nil, nil, nil, - BlockNode(857...869)( + BlockNode(878...890)( [], nil, - StatementsNode(860...865)( - [StringNode(860...865)( - (860...861), - (861...864), - (864...865), + StatementsNode(881...886)( + [StringNode(881...886)( + (881...882), + (882...885), + (885...886), "baz" )] ), - (857...859), - (866...869) + (878...880), + (887...890) ), 0, "map" )] ), - (869...870) + (890...891) )], - (870...871) + (891...892) )] ), nil, - BlockNode(872...878)([], nil, nil, (872...874), (875...878)), + BlockNode(893...899)([], nil, nil, (893...895), (896...899)), 0, "foo" ), - CallNode(880...908)( + CallNode(901...929)( nil, nil, - (880...883), + (901...904), nil, - ArgumentsNode(884...908)( - [ClassNode(884...908)( + ArgumentsNode(905...929)( + [ClassNode(905...929)( [], - (884...889), - ConstantReadNode(890...893)(), + (905...910), + ConstantReadNode(911...914)(), nil, nil, - StatementsNode(894...904)( - [CallNode(894...904)( + StatementsNode(915...925)( + [CallNode(915...925)( nil, nil, - (894...897), + (915...918), nil, nil, nil, - BlockNode(898...904)([], nil, nil, (898...900), (901...904)), + BlockNode(919...925)([], nil, nil, (919...921), (922...925)), 0, "baz" )] ), - (905...908) + (926...929) )] ), nil, @@ -1180,30 +1199,30 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(910...939)( + CallNode(931...960)( nil, nil, - (910...913), + (931...934), nil, - ArgumentsNode(914...939)( - [ModuleNode(914...939)( + ArgumentsNode(935...960)( + [ModuleNode(935...960)( [], - (914...920), - ConstantReadNode(921...924)(), - StatementsNode(925...935)( - [CallNode(925...935)( + (935...941), + ConstantReadNode(942...945)(), + StatementsNode(946...956)( + [CallNode(946...956)( nil, nil, - (925...928), + (946...949), nil, nil, nil, - BlockNode(929...935)([], nil, nil, (929...931), (932...935)), + BlockNode(950...956)([], nil, nil, (950...952), (953...956)), 0, "baz" )] ), - (936...939) + (957...960) )] ), nil, @@ -1211,26 +1230,26 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(941...957)( + CallNode(962...978)( nil, nil, - (941...944), + (962...965), nil, - ArgumentsNode(945...957)( - [ArrayNode(945...957)( - [CallNode(946...956)( + ArgumentsNode(966...978)( + [ArrayNode(966...978)( + [CallNode(967...977)( nil, nil, - (946...949), + (967...970), nil, nil, nil, - BlockNode(950...956)([], nil, nil, (950...952), (953...956)), + BlockNode(971...977)([], nil, nil, (971...973), (974...977)), 0, "baz" )], - (945...946), - (956...957) + (966...967), + (977...978) )] ), nil, @@ -1238,28 +1257,28 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(959...987)( + CallNode(980...1008)( nil, nil, - (959...960), + (980...981), nil, - ArgumentsNode(961...987)( - [BeginNode(961...987)( - (961...966), - StatementsNode(967...983)( - [CallNode(967...983)( - IntegerNode(967...968)(), - (968...969), - (969...974), + ArgumentsNode(982...1008)( + [BeginNode(982...1008)( + (982...987), + StatementsNode(988...1004)( + [CallNode(988...1004)( + IntegerNode(988...989)(), + (989...990), + (990...995), nil, nil, nil, - BlockNode(975...983)( + BlockNode(996...1004)( [], nil, - StatementsNode(978...979)([IntegerNode(978...979)()]), - (975...977), - (980...983) + StatementsNode(999...1000)([IntegerNode(999...1000)()]), + (996...998), + (1001...1004) ), 0, "times" @@ -1268,7 +1287,7 @@ ProgramNode(0...1187)( nil, nil, nil, - (984...987) + (1005...1008) )] ), nil, @@ -1276,39 +1295,39 @@ ProgramNode(0...1187)( 0, "p" ), - CallNode(989...1040)( + CallNode(1010...1061)( nil, nil, - (989...992), + (1010...1013), nil, - ArgumentsNode(993...1040)( - [SymbolNode(993...995)((993...994), (994...995), nil, "a"), - IfNode(999...1040)( - (999...1001), - CallNode(1002...1003)( + ArgumentsNode(1014...1061)( + [SymbolNode(1014...1016)((1014...1015), (1015...1016), nil, "a"), + IfNode(1020...1061)( + (1020...1022), + CallNode(1023...1024)( nil, nil, - (1002...1003), + (1023...1024), nil, nil, nil, nil, - 0, + 2, "x" ), - StatementsNode(1008...1034)( - [CallNode(1008...1034)( + StatementsNode(1029...1055)( + [CallNode(1029...1055)( nil, nil, - (1008...1011), + (1029...1032), nil, nil, nil, - BlockNode(1012...1034)( + BlockNode(1033...1055)( [:a], - BlockParametersNode(1015...1018)( - ParametersNode(1016...1017)( - [RequiredParameterNode(1016...1017)(:a)], + BlockParametersNode(1036...1039)( + ParametersNode(1037...1038)( + [RequiredParameterNode(1037...1038)(:a)], [], [], nil, @@ -1317,21 +1336,21 @@ ProgramNode(0...1187)( nil ), [], - (1015...1016), - (1017...1018) + (1036...1037), + (1038...1039) ), - StatementsNode(1025...1026)( - [LocalVariableReadNode(1025...1026)(:a, 0)] + StatementsNode(1046...1047)( + [LocalVariableReadNode(1046...1047)(:a, 0)] ), - (1012...1014), - (1031...1034) + (1033...1035), + (1052...1055) ), 0, "bar" )] ), nil, - (1037...1040) + (1058...1061) )] ), nil, @@ -1339,39 +1358,39 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(1042...1132)( + CallNode(1063...1153)( nil, nil, - (1042...1045), + (1063...1066), nil, - ArgumentsNode(1046...1132)( - [SymbolNode(1046...1048)((1046...1047), (1047...1048), nil, "a"), - WhileNode(1052...1096)( - (1052...1057), - CallNode(1058...1059)( + ArgumentsNode(1067...1153)( + [SymbolNode(1067...1069)((1067...1068), (1068...1069), nil, "a"), + WhileNode(1073...1117)( + (1073...1078), + CallNode(1079...1080)( nil, nil, - (1058...1059), + (1079...1080), nil, nil, nil, nil, - 0, + 2, "x" ), - StatementsNode(1064...1090)( - [CallNode(1064...1090)( + StatementsNode(1085...1111)( + [CallNode(1085...1111)( nil, nil, - (1064...1067), + (1085...1088), nil, nil, nil, - BlockNode(1068...1090)( + BlockNode(1089...1111)( [:a], - BlockParametersNode(1071...1074)( - ParametersNode(1072...1073)( - [RequiredParameterNode(1072...1073)(:a)], + BlockParametersNode(1092...1095)( + ParametersNode(1093...1094)( + [RequiredParameterNode(1093...1094)(:a)], [], [], nil, @@ -1380,52 +1399,54 @@ ProgramNode(0...1187)( nil ), [], - (1071...1072), - (1073...1074) + (1092...1093), + (1094...1095) ), - StatementsNode(1081...1082)( - [LocalVariableReadNode(1081...1082)(:a, 0)] + StatementsNode(1102...1103)( + [LocalVariableReadNode(1102...1103)(:a, 0)] ), - (1068...1070), - (1087...1090) + (1089...1091), + (1108...1111) ), 0, "bar" )] - ) + ), + 0 ), - UntilNode(1100...1132)( - (1100...1105), - CallNode(1106...1107)( + UntilNode(1121...1153)( + (1121...1126), + CallNode(1127...1128)( nil, nil, - (1106...1107), + (1127...1128), nil, nil, nil, nil, - 0, + 2, "x" ), - StatementsNode(1112...1126)( - [CallNode(1112...1126)( + StatementsNode(1133...1147)( + [CallNode(1133...1147)( nil, nil, - (1112...1115), + (1133...1136), nil, nil, nil, - BlockNode(1116...1126)( + BlockNode(1137...1147)( [], nil, nil, - (1116...1118), - (1123...1126) + (1137...1139), + (1144...1147) ), 0, "baz" )] - ) + ), + 0 )] ), nil, @@ -1433,20 +1454,20 @@ ProgramNode(0...1187)( 0, "foo" ), - CallNode(1134...1143)( - HashNode(1134...1136)((1134...1135), [], (1135...1136)), + CallNode(1155...1164)( + HashNode(1155...1157)((1155...1156), [], (1156...1157)), nil, - (1137...1138), + (1158...1159), nil, - ArgumentsNode(1139...1143)( - [CallNode(1139...1143)( + ArgumentsNode(1160...1164)( + [CallNode(1160...1164)( nil, nil, - (1139...1140), + (1160...1161), nil, nil, nil, - BlockNode(1141...1143)([], nil, nil, (1141...1142), (1142...1143)), + BlockNode(1162...1164)([], nil, nil, (1162...1163), (1163...1164)), 0, "A" )] @@ -1456,24 +1477,24 @@ ProgramNode(0...1187)( 0, "+" ), - CallNode(1145...1161)( - HashNode(1145...1147)((1145...1146), [], (1146...1147)), + CallNode(1166...1182)( + HashNode(1166...1168)((1166...1167), [], (1167...1168)), nil, - (1148...1149), + (1169...1170), nil, - ArgumentsNode(1150...1161)( - [CallNode(1150...1161)( + ArgumentsNode(1171...1182)( + [CallNode(1171...1182)( nil, nil, - (1150...1151), + (1171...1172), nil, nil, nil, - BlockNode(1152...1161)( + BlockNode(1173...1182)( [:a], - BlockParametersNode(1154...1157)( - ParametersNode(1155...1156)( - [RequiredParameterNode(1155...1156)(:a)], + BlockParametersNode(1175...1178)( + ParametersNode(1176...1177)( + [RequiredParameterNode(1176...1177)(:a)], [], [], nil, @@ -1482,14 +1503,14 @@ ProgramNode(0...1187)( nil ), [], - (1154...1155), - (1156...1157) + (1175...1176), + (1177...1178) ), - StatementsNode(1158...1159)( - [LocalVariableReadNode(1158...1159)(:a, 0)] + StatementsNode(1179...1180)( + [LocalVariableReadNode(1179...1180)(:a, 0)] ), - (1152...1153), - (1160...1161) + (1173...1174), + (1181...1182) ), 0, "A" @@ -1500,30 +1521,30 @@ ProgramNode(0...1187)( 0, "+" ), - CallNode(1163...1174)( - CallNode(1163...1167)( + CallNode(1184...1195)( + CallNode(1184...1188)( nil, nil, - (1163...1164), + (1184...1185), nil, nil, nil, - BlockNode(1165...1167)([], nil, nil, (1165...1166), (1166...1167)), + BlockNode(1186...1188)([], nil, nil, (1186...1187), (1187...1188)), 0, "A" ), nil, - (1168...1169), + (1189...1190), nil, - ArgumentsNode(1170...1174)( - [CallNode(1170...1174)( + ArgumentsNode(1191...1195)( + [CallNode(1191...1195)( nil, nil, - (1170...1171), + (1191...1192), nil, nil, nil, - BlockNode(1172...1174)([], nil, nil, (1172...1173), (1173...1174)), + BlockNode(1193...1195)([], nil, nil, (1193...1194), (1194...1195)), 0, "A" )] @@ -1533,30 +1554,30 @@ ProgramNode(0...1187)( 0, "+" ), - CallNode(1176...1187)( - CallNode(1176...1179)( + CallNode(1197...1208)( + CallNode(1197...1200)( nil, nil, - (1176...1179), + (1197...1200), nil, nil, nil, nil, - 0, + 2, "lst" ), nil, - (1180...1182), + (1201...1203), nil, - ArgumentsNode(1183...1187)( - [CallNode(1183...1187)( + ArgumentsNode(1204...1208)( + [CallNode(1204...1208)( nil, nil, - (1183...1184), + (1204...1205), nil, nil, nil, - BlockNode(1185...1187)([], nil, nil, (1185...1186), (1186...1187)), + BlockNode(1206...1208)([], nil, nil, (1206...1207), (1207...1208)), 0, "A" )] @@ -1565,6 +1586,67 @@ ProgramNode(0...1187)( nil, 0, "<<" + ), + InterpolatedStringNode(1210...1227)( + (1210...1211), + [EmbeddedStatementsNode(1211...1226)( + (1211...1213), + StatementsNode(1214...1224)( + [CallNode(1214...1224)( + nil, + nil, + (1214...1218), + nil, + ArgumentsNode(1219...1224)( + [ParenthesesNode(1219...1224)( + StatementsNode(1220...1223)( + [StringNode(1220...1223)( + (1220...1221), + (1221...1222), + (1222...1223), + " " + )] + ), + (1219...1220), + (1223...1224) + )] + ), + nil, + nil, + 0, + "join" + )] + ), + (1225...1226) + )], + (1226...1227) + ), + InterpolatedStringNode(1229...1237)( + (1229...1230), + [EmbeddedStatementsNode(1230...1236)( + (1230...1232), + StatementsNode(1232...1235)( + [ParenthesesNode(1232...1235)( + StatementsNode(1233...1234)( + [CallNode(1233...1234)( + nil, + nil, + (1233...1234), + nil, + nil, + nil, + nil, + 2, + "v" + )] + ), + (1232...1233), + (1234...1235) + )] + ), + (1235...1236) + )], + (1236...1237) )] ) ) diff --git a/test/yarp/snapshots/methods.txt b/test/yarp/snapshots/methods.txt index 8d1eee8a2a36dd..a2cfa8e06d0626 100644 --- a/test/yarp/snapshots/methods.txt +++ b/test/yarp/snapshots/methods.txt @@ -94,7 +94,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "b" ), (101...102), @@ -121,7 +121,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "a" ), (116...117), @@ -186,7 +186,7 @@ ProgramNode(0...1194)( ), DefNode(177...188)( (183...184), - CallNode(181...182)(nil, nil, (181...182), nil, nil, nil, nil, 0, "a"), + CallNode(181...182)(nil, nil, (181...182), nil, nil, nil, nil, 2, "a"), nil, nil, [], @@ -847,7 +847,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "b" ), (769...770), @@ -935,7 +935,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "b" ), (833...834), @@ -1052,7 +1052,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "bar" ), (957...959) @@ -1066,7 +1066,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "baz" ), (964...966) @@ -1080,7 +1080,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "qux" ), (971...973) @@ -1339,7 +1339,7 @@ ProgramNode(0...1194)( nil, nil, nil, - 0, + 2, "item" ), nil, diff --git a/test/yarp/snapshots/modules.txt b/test/yarp/snapshots/modules.txt index 432d4c99165301..705563a9f04cdf 100644 --- a/test/yarp/snapshots/modules.txt +++ b/test/yarp/snapshots/modules.txt @@ -30,7 +30,7 @@ ProgramNode(0...140)( nil, nil, nil, - 0, + 2, "bbb" )] ), @@ -43,7 +43,7 @@ ProgramNode(0...140)( [], (40...46), ConstantPathNode(47...51)( - CallNode(47...48)(nil, nil, (47...48), nil, nil, nil, nil, 0, "m"), + CallNode(47...48)(nil, nil, (47...48), nil, nil, nil, nil, 2, "m"), ConstantReadNode(50...51)(), (48...50) ), diff --git a/test/yarp/snapshots/non_alphanumeric_methods.txt b/test/yarp/snapshots/non_alphanumeric_methods.txt index ac2beadd0d9d82..a8e9cd798fb465 100644 --- a/test/yarp/snapshots/non_alphanumeric_methods.txt +++ b/test/yarp/snapshots/non_alphanumeric_methods.txt @@ -215,7 +215,7 @@ ProgramNode(0...434)( ), DefNode(195...206)( (201...202), - CallNode(199...200)(nil, nil, (199...200), nil, nil, nil, nil, 0, "a"), + CallNode(199...200)(nil, nil, (199...200), nil, nil, nil, nil, 2, "a"), nil, nil, [], diff --git a/test/yarp/snapshots/not.txt b/test/yarp/snapshots/not.txt index 7bec91e7e73520..5a9889bf6aa5cd 100644 --- a/test/yarp/snapshots/not.txt +++ b/test/yarp/snapshots/not.txt @@ -3,7 +3,7 @@ ProgramNode(0...190)( StatementsNode(0...190)( [AndNode(0...19)( CallNode(0...7)( - CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "foo"), + CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "foo"), nil, (0...3), nil, @@ -14,7 +14,7 @@ ProgramNode(0...190)( "!" ), CallNode(12...19)( - CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "bar"), + CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "bar"), nil, (12...15), nil, @@ -28,8 +28,8 @@ ProgramNode(0...190)( ), CallNode(21...37)( AndNode(25...36)( - CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 0, "foo"), - CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 0, "bar"), + CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 2, "foo"), + CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 2, "bar"), (29...32) ), nil, @@ -42,7 +42,7 @@ ProgramNode(0...190)( "!" ), CallNode(39...46)( - CallNode(43...46)(nil, nil, (43...46), nil, nil, nil, nil, 0, "foo"), + CallNode(43...46)(nil, nil, (43...46), nil, nil, nil, nil, 2, "foo"), nil, (39...42), nil, @@ -54,7 +54,7 @@ ProgramNode(0...190)( ), AndNode(48...69)( CallNode(48...55)( - CallNode(52...55)(nil, nil, (52...55), nil, nil, nil, nil, 0, "foo"), + CallNode(52...55)(nil, nil, (52...55), nil, nil, nil, nil, 2, "foo"), nil, (48...51), nil, @@ -65,7 +65,7 @@ ProgramNode(0...190)( "!" ), CallNode(60...69)( - CallNode(66...69)(nil, nil, (66...69), nil, nil, nil, nil, 0, "bar"), + CallNode(66...69)(nil, nil, (66...69), nil, nil, nil, nil, 2, "bar"), nil, (60...63), nil, @@ -79,7 +79,7 @@ ProgramNode(0...190)( ), AndNode(72...97)( CallNode(72...79)( - CallNode(76...79)(nil, nil, (76...79), nil, nil, nil, nil, 0, "foo"), + CallNode(76...79)(nil, nil, (76...79), nil, nil, nil, nil, 2, "foo"), nil, (72...75), nil, @@ -90,7 +90,7 @@ ProgramNode(0...190)( "!" ), CallNode(88...97)( - CallNode(94...97)(nil, nil, (94...97), nil, nil, nil, nil, 0, "bar"), + CallNode(94...97)(nil, nil, (94...97), nil, nil, nil, nil, 2, "bar"), nil, (88...91), nil, @@ -112,7 +112,7 @@ ProgramNode(0...190)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -133,7 +133,7 @@ ProgramNode(0...190)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -156,7 +156,7 @@ ProgramNode(0...190)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -177,7 +177,7 @@ ProgramNode(0...190)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -190,7 +190,7 @@ ProgramNode(0...190)( "!" ), CallNode(158...172)( - RangeNode(162...172)( + FlipFlopNode(162...172)( CallNode(162...165)( nil, nil, @@ -214,7 +214,7 @@ ProgramNode(0...190)( "bar" ), (166...168), - 2 + 0 ), nil, (158...161), @@ -228,7 +228,7 @@ ProgramNode(0...190)( CallNode(174...190)( ParenthesesNode(178...190)( StatementsNode(179...189)( - [RangeNode(179...189)( + [FlipFlopNode(179...189)( CallNode(179...182)( nil, nil, @@ -252,7 +252,7 @@ ProgramNode(0...190)( "bar" ), (183...185), - 2 + 0 )] ), (178...179), diff --git a/test/yarp/snapshots/numbers.txt b/test/yarp/snapshots/numbers.txt index 04cb532e881abe..72fb895125d250 100644 --- a/test/yarp/snapshots/numbers.txt +++ b/test/yarp/snapshots/numbers.txt @@ -22,45 +22,13 @@ ProgramNode(0...161)( IntegerNode(82...85)(), ImaginaryNode(87...89)(IntegerNode(87...88)()), RationalNode(91...93)(IntegerNode(91...92)()), - CallNode(95...97)( - IntegerNode(96...97)(), - nil, - (95...96), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + IntegerNode(95...97)(), ImaginaryNode(99...102)(RationalNode(99...101)(IntegerNode(99...100)())), ImaginaryNode(104...109)(RationalNode(104...108)(FloatNode(104...107)())), - CallNode(111...115)( - ImaginaryNode(112...115)( - RationalNode(112...114)(IntegerNode(112...113)()) - ), - nil, - (111...112), - nil, - nil, - nil, - nil, - 0, - "-@" - ), - CallNode(117...123)( - ImaginaryNode(118...123)( - RationalNode(118...122)(FloatNode(118...121)()) - ), - nil, - (117...118), - nil, - nil, - nil, - nil, - 0, - "-@" + ImaginaryNode(111...115)( + RationalNode(111...114)(IntegerNode(111...113)()) ), + ImaginaryNode(117...123)(RationalNode(117...122)(FloatNode(117...121)())), RationalNode(125...129)(IntegerNode(125...128)()), ImaginaryNode(131...135)(IntegerNode(131...134)()), ImaginaryNode(137...142)( diff --git a/test/yarp/snapshots/patterns.txt b/test/yarp/snapshots/patterns.txt index 397000235c829e..d578a43f066cb2 100644 --- a/test/yarp/snapshots/patterns.txt +++ b/test/yarp/snapshots/patterns.txt @@ -2,51 +2,47 @@ ProgramNode(0...3743)( [:bar, :baz, :qux, :b, :a], StatementsNode(0...3743)( [MatchRequiredNode(0...10)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), LocalVariableWriteNode(7...10)(:bar, 0, nil, (7...10), nil), (4...6) ), MatchRequiredNode(11...19)( - CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "foo"), + CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "foo"), IntegerNode(18...19)(), (15...17) ), MatchRequiredNode(20...30)( - CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 0, "foo"), + CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 2, "foo"), FloatNode(27...30)(), (24...26) ), MatchRequiredNode(31...40)( - CallNode(31...34)(nil, nil, (31...34), nil, nil, nil, nil, 0, "foo"), + CallNode(31...34)(nil, nil, (31...34), nil, nil, nil, nil, 2, "foo"), ImaginaryNode(38...40)(IntegerNode(38...39)()), (35...37) ), MatchRequiredNode(41...50)( - CallNode(41...44)(nil, nil, (41...44), nil, nil, nil, nil, 0, "foo"), + CallNode(41...44)(nil, nil, (41...44), nil, nil, nil, nil, 2, "foo"), RationalNode(48...50)(IntegerNode(48...49)()), (45...47) ), MatchRequiredNode(51...62)( - CallNode(51...54)(nil, nil, (51...54), nil, nil, nil, nil, 0, "foo"), + CallNode(51...54)(nil, nil, (51...54), nil, nil, nil, nil, 2, "foo"), SymbolNode(58...62)((58...59), (59...62), nil, "foo"), (55...57) ), MatchRequiredNode(63...77)( - CallNode(63...66)(nil, nil, (63...66), nil, nil, nil, nil, 0, "foo"), + CallNode(63...66)(nil, nil, (63...66), nil, nil, nil, nil, 2, "foo"), SymbolNode(70...77)((70...73), (73...76), (76...77), "foo"), (67...69) ), MatchRequiredNode(78...91)( - CallNode(78...81)(nil, nil, (78...81), nil, nil, nil, nil, 0, "foo"), - InterpolatedSymbolNode(85...91)( - (85...87), - [StringNode(87...90)(nil, (87...90), nil, "foo")], - (90...91) - ), + CallNode(78...81)(nil, nil, (78...81), nil, nil, nil, nil, 2, "foo"), + SymbolNode(85...91)(nil, (87...90), nil, "foo"), (82...84) ), MatchRequiredNode(92...104)( - CallNode(92...95)(nil, nil, (92...95), nil, nil, nil, nil, 0, "foo"), + CallNode(92...95)(nil, nil, (92...95), nil, nil, nil, nil, 2, "foo"), RegularExpressionNode(99...104)( (99...100), (100...103), @@ -65,7 +61,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), XStringNode(112...117)((112...113), (113...116), (116...117), "foo"), @@ -80,7 +76,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), XStringNode(125...132)((125...128), (128...131), (131...132), "foo"), @@ -95,7 +91,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(140...147)( @@ -114,7 +110,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(155...162)( @@ -133,7 +129,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(170...177)( @@ -152,7 +148,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(185...192)( @@ -171,7 +167,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), StringNode(200...207)((200...203), (203...206), (206...207), "foo"), @@ -186,7 +182,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), StringNode(215...222)((215...218), (218...221), (221...222), "foo"), @@ -201,7 +197,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), StringNode(230...235)((230...231), (231...234), (234...235), "foo"), @@ -216,7 +212,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), NilNode(243...246)(), @@ -231,7 +227,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SelfNode(254...258)(), @@ -246,7 +242,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), TrueNode(266...270)(), @@ -261,7 +257,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), FalseNode(278...283)(), @@ -276,7 +272,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SourceFileNode(291...299)("patterns.txt"), @@ -291,7 +287,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SourceLineNode(307...315)(), @@ -306,7 +302,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SourceEncodingNode(323...335)(), @@ -321,7 +317,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), LambdaNode(343...353)( @@ -341,7 +337,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(362...368)( @@ -361,7 +357,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(376...386)( @@ -381,7 +377,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(394...402)( @@ -401,7 +397,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(410...418)( @@ -421,7 +417,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(426...438)( @@ -441,7 +437,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(446...464)( @@ -461,20 +457,12 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(472...488)( - InterpolatedSymbolNode(472...478)( - (472...474), - [StringNode(474...477)(nil, (474...477), nil, "foo")], - (477...478) - ), - InterpolatedSymbolNode(482...488)( - (482...484), - [StringNode(484...487)(nil, (484...487), nil, "foo")], - (487...488) - ), + SymbolNode(472...478)(nil, (474...477), nil, "foo"), + SymbolNode(482...488)(nil, (484...487), nil, "foo"), (479...481), 0 ), @@ -489,7 +477,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(496...510)( @@ -521,7 +509,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(518...532)( @@ -541,7 +529,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(540...558)( @@ -561,7 +549,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(566...584)( @@ -589,7 +577,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(592...610)( @@ -617,7 +605,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(618...636)( @@ -645,7 +633,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(644...662)( @@ -673,7 +661,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(670...688)( @@ -693,7 +681,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(696...714)( @@ -713,7 +701,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(722...736)( @@ -733,7 +721,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(744...754)( @@ -753,7 +741,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(762...774)( @@ -773,7 +761,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(782...794)( @@ -793,7 +781,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(802...816)( @@ -813,7 +801,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(824...844)( @@ -833,7 +821,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(852...872)( @@ -853,7 +841,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(880...908)( @@ -873,7 +861,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RangeNode(916...940)( @@ -907,7 +895,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), PinnedVariableNode(949...953)( @@ -925,7 +913,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), PinnedVariableNode(961...966)( @@ -943,7 +931,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), PinnedVariableNode(974...980)( @@ -961,7 +949,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), PinnedVariableNode(988...993)( @@ -979,7 +967,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), PinnedExpressionNode(1002...1006)( @@ -999,7 +987,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), PinnedExpressionNode(1014...1020)( @@ -1019,7 +1007,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), PinnedExpressionNode(1028...1044)( @@ -1061,7 +1049,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ConstantReadNode(1053...1056)(), @@ -1076,7 +1064,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ConstantPathNode(1064...1077)( @@ -1099,7 +1087,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ConstantPathNode(1085...1090)( @@ -1118,7 +1106,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ConstantPathNode(1098...1113)( @@ -1145,7 +1133,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1122...1127)( @@ -1167,7 +1155,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1135...1141)( @@ -1189,7 +1177,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1149...1161)( @@ -1213,7 +1201,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1169...1177)( @@ -1241,7 +1229,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1185...1199)( @@ -1278,7 +1266,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1207...1221)( @@ -1315,7 +1303,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), FindPatternNode(1229...1249)( @@ -1361,7 +1349,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1258...1263)( @@ -1383,7 +1371,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1271...1277)( @@ -1405,7 +1393,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1285...1297)( @@ -1429,7 +1417,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1305...1315)( @@ -1458,7 +1446,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1323...1331)( @@ -1486,7 +1474,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1339...1353)( @@ -1523,7 +1511,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1361...1375)( @@ -1560,7 +1548,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), FindPatternNode(1383...1403)( @@ -1606,7 +1594,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1412...1416)( @@ -1637,7 +1625,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1424...1438)( @@ -1681,7 +1669,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1446...1460)( @@ -1724,7 +1712,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1468...1482)( @@ -1768,7 +1756,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), FindPatternNode(1490...1505)( @@ -1814,7 +1802,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1514...1516)( @@ -1836,7 +1824,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1524...1534)( @@ -1886,7 +1874,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1543...1549)( @@ -1917,7 +1905,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1557...1573)( @@ -1961,7 +1949,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1581...1597)( @@ -2004,7 +1992,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayPatternNode(1605...1621)( @@ -2048,7 +2036,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), FindPatternNode(1629...1646)( @@ -2094,7 +2082,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), LocalVariableWriteNode(1655...1658)(:bar, 0, nil, (1655...1658), nil), @@ -2109,7 +2097,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), IntegerNode(1666...1667)(), @@ -2124,7 +2112,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), FloatNode(1675...1678)(), @@ -2139,7 +2127,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ImaginaryNode(1686...1688)(IntegerNode(1686...1687)()), @@ -2154,7 +2142,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RationalNode(1696...1698)(IntegerNode(1696...1697)()), @@ -2169,7 +2157,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SymbolNode(1706...1710)((1706...1707), (1707...1710), nil, "foo"), @@ -2184,7 +2172,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SymbolNode(1718...1725)( @@ -2204,14 +2192,10 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), - InterpolatedSymbolNode(1733...1739)( - (1733...1735), - [StringNode(1735...1738)(nil, (1735...1738), nil, "foo")], - (1738...1739) - ), + SymbolNode(1733...1739)(nil, (1735...1738), nil, "foo"), (1730...1732) ), MatchPredicateNode(1740...1752)( @@ -2223,7 +2207,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), RegularExpressionNode(1747...1752)( @@ -2244,7 +2228,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), XStringNode(1760...1765)( @@ -2264,7 +2248,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), XStringNode(1773...1780)( @@ -2284,7 +2268,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(1788...1795)( @@ -2303,7 +2287,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(1803...1810)( @@ -2322,7 +2306,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(1818...1825)( @@ -2341,7 +2325,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), ArrayNode(1833...1840)( @@ -2360,7 +2344,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), StringNode(1848...1855)( @@ -2380,7 +2364,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), StringNode(1863...1870)( @@ -2400,7 +2384,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), StringNode(1878...1883)( @@ -2420,7 +2404,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), NilNode(1891...1894)(), @@ -2435,7 +2419,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SelfNode(1902...1906)(), @@ -2450,7 +2434,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), TrueNode(1914...1918)(), @@ -2465,7 +2449,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), FalseNode(1926...1931)(), @@ -2480,7 +2464,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SourceFileNode(1939...1947)("patterns.txt"), @@ -2495,7 +2479,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SourceLineNode(1955...1963)(), @@ -2510,7 +2494,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), SourceEncodingNode(1971...1983)(), @@ -2525,7 +2509,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), LambdaNode(1991...2001)( @@ -2547,7 +2531,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2013...2024)( @@ -2575,7 +2559,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2039...2048)( @@ -2597,7 +2581,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2063...2074)( @@ -2619,7 +2603,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2089...2099)( @@ -2641,7 +2625,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2114...2124)( @@ -2663,7 +2647,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2139...2151)( @@ -2685,7 +2669,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2166...2181)( @@ -2712,15 +2696,11 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2196...2210)( - InterpolatedSymbolNode(2199...2205)( - (2199...2201), - [StringNode(2201...2204)(nil, (2201...2204), nil, "foo")], - (2204...2205) - ), + SymbolNode(2199...2205)(nil, (2201...2204), nil, "foo"), nil, (2196...2198), (2206...2210) @@ -2738,7 +2718,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2225...2238)( @@ -2766,7 +2746,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2253...2266)( @@ -2793,7 +2773,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2281...2296)( @@ -2820,7 +2800,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2311...2326)( @@ -2846,7 +2826,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2341...2356)( @@ -2872,7 +2852,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2371...2386)( @@ -2898,7 +2878,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2401...2416)( @@ -2924,7 +2904,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2431...2446)( @@ -2951,7 +2931,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2461...2476)( @@ -2978,7 +2958,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2491...2504)( @@ -3005,7 +2985,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2519...2530)( @@ -3027,7 +3007,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2545...2557)( @@ -3049,7 +3029,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2572...2584)( @@ -3071,7 +3051,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2599...2612)( @@ -3093,7 +3073,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2627...2643)( @@ -3115,7 +3095,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2658...2674)( @@ -3137,7 +3117,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2689...2709)( @@ -3159,7 +3139,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2724...2742)( @@ -3188,7 +3168,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2758...2776)( @@ -3224,7 +3204,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2791...2807)( @@ -3252,7 +3232,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2822...2840)( @@ -3280,7 +3260,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2855...2872)( @@ -3310,7 +3290,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2887...2904)( @@ -3340,7 +3320,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2919...2938)( @@ -3375,7 +3355,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2953...2975)( @@ -3410,7 +3390,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(2990...3011)( @@ -3418,11 +3398,7 @@ ProgramNode(0...3743)( (3000...3002), LocalVariableReadNode(3003...3006)(:baz, 0), StatementsNode(2993...2999)( - [InterpolatedSymbolNode(2993...2999)( - (2993...2995), - [StringNode(2995...2998)(nil, (2995...2998), nil, "foo")], - (2998...2999) - )] + [SymbolNode(2993...2999)(nil, (2995...2998), nil, "foo")] ), nil, nil @@ -3444,7 +3420,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3026...3046)( @@ -3480,7 +3456,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3061...3081)( @@ -3515,7 +3491,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3096...3118)( @@ -3550,7 +3526,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3133...3155)( @@ -3584,7 +3560,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3170...3192)( @@ -3618,7 +3594,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3207...3229)( @@ -3652,7 +3628,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3244...3266)( @@ -3686,7 +3662,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3281...3303)( @@ -3721,7 +3697,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3318...3340)( @@ -3756,7 +3732,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3355...3375)( @@ -3791,7 +3767,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3390...3408)( @@ -3819,7 +3795,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3423...3442)( @@ -3847,7 +3823,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3457...3476)( @@ -3875,7 +3851,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3491...3511)( @@ -3903,7 +3879,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3526...3549)( @@ -3933,7 +3909,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3564...3587)( @@ -3961,7 +3937,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3602...3629)( @@ -3989,7 +3965,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(3644...3669)( @@ -4028,7 +4004,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "a" ), ArrayPatternNode(3683...3685)( @@ -4054,7 +4030,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "a" ), ArrayPatternNode(3696...3703)( @@ -4076,7 +4052,7 @@ ProgramNode(0...3743)( nil, nil, nil, - 0, + 2, "foo" ), HashPatternNode(3712...3743)( diff --git a/test/yarp/snapshots/procs.txt b/test/yarp/snapshots/procs.txt index 0e02784453a1fa..3db8ec5b1378d9 100644 --- a/test/yarp/snapshots/procs.txt +++ b/test/yarp/snapshots/procs.txt @@ -51,7 +51,7 @@ ProgramNode(0...266)( (71...73), nil, StatementsNode(76...79)( - [CallNode(76...79)(nil, nil, (76...79), nil, nil, nil, nil, 0, "foo")] + [CallNode(76...79)(nil, nil, (76...79), nil, nil, nil, nil, 2, "foo")] ) ), LambdaNode(83...98)( @@ -59,7 +59,7 @@ ProgramNode(0...266)( (83...85), nil, StatementsNode(90...93)( - [CallNode(90...93)(nil, nil, (90...93), nil, nil, nil, nil, 0, "foo")] + [CallNode(90...93)(nil, nil, (90...93), nil, nil, nil, nil, 2, "foo")] ) ), LambdaNode(100...129)( diff --git a/test/yarp/snapshots/ranges.txt b/test/yarp/snapshots/ranges.txt index d78044bab0b61e..8873f61b0a9d68 100644 --- a/test/yarp/snapshots/ranges.txt +++ b/test/yarp/snapshots/ranges.txt @@ -22,7 +22,7 @@ ProgramNode(0...85)( 1 ), CallNode(22...31)( - CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 0, "foo"), + CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 2, "foo"), nil, (25...31), (25...26), @@ -48,7 +48,7 @@ ProgramNode(0...85)( nil, nil, nil, - 0, + 2, "bar" ), (40...43), @@ -85,7 +85,7 @@ ProgramNode(0...85)( nil, nil, nil, - 0, + 2, "bar" ), (71...73), diff --git a/test/yarp/snapshots/regex.txt b/test/yarp/snapshots/regex.txt index b53f35df2a5d80..67d7ab0480cf02 100644 --- a/test/yarp/snapshots/regex.txt +++ b/test/yarp/snapshots/regex.txt @@ -40,7 +40,7 @@ ProgramNode(0...278)( nil, nil, nil, - 0, + 2, "bbb" )] ), @@ -71,7 +71,7 @@ ProgramNode(0...278)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/rescue.txt b/test/yarp/snapshots/rescue.txt index 01887935e8b514..b8944afd19bcf2 100644 --- a/test/yarp/snapshots/rescue.txt +++ b/test/yarp/snapshots/rescue.txt @@ -2,12 +2,12 @@ ProgramNode(0...316)( [:a], StatementsNode(0...316)( [RescueModifierNode(0...14)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (4...10), NilNode(11...14)() ), RescueModifierNode(16...30)( - CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "foo"), + CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "foo"), (20...26), NilNode(27...30)() ), @@ -27,7 +27,7 @@ ProgramNode(0...316)( NilNode(81...84)() ), RescueModifierNode(86...105)( - CallNode(86...89)(nil, nil, (86...89), nil, nil, nil, nil, 0, "foo"), + CallNode(86...89)(nil, nil, (86...89), nil, nil, nil, nil, 2, "foo"), (90...96), OrNode(97...105)( NilNode(97...100)(), @@ -44,7 +44,7 @@ ProgramNode(0...316)( nil, nil, nil, - 0, + 2, "foo" ), (111...117), @@ -71,7 +71,7 @@ ProgramNode(0...316)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -87,7 +87,7 @@ ProgramNode(0...316)( nil, nil, nil, - 0, + 2, "b" ) )], @@ -139,7 +139,7 @@ ProgramNode(0...316)( nil, nil, nil, - 0, + 2, "y" )] ), @@ -201,7 +201,7 @@ ProgramNode(0...316)( nil, nil, nil, - 0, + 2, "foo" ), (225...231), @@ -219,7 +219,7 @@ ProgramNode(0...316)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/seattlerb/attrasgn_array_arg.txt b/test/yarp/snapshots/seattlerb/attrasgn_array_arg.txt index 4da302b14114fa..b9a116975a9bbb 100644 --- a/test/yarp/snapshots/seattlerb/attrasgn_array_arg.txt +++ b/test/yarp/snapshots/seattlerb/attrasgn_array_arg.txt @@ -2,7 +2,7 @@ ProgramNode(0...13)( [], StatementsNode(0...13)( [CallNode(0...13)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), nil, (1...9), (1...2), diff --git a/test/yarp/snapshots/seattlerb/attrasgn_array_lhs.txt b/test/yarp/snapshots/seattlerb/attrasgn_array_lhs.txt index e720ae5c863f82..666f9e34765e2b 100644 --- a/test/yarp/snapshots/seattlerb/attrasgn_array_lhs.txt +++ b/test/yarp/snapshots/seattlerb/attrasgn_array_lhs.txt @@ -23,7 +23,7 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "from" ), CallNode(21...23)( @@ -34,7 +34,7 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "to" ), (18...20), diff --git a/test/yarp/snapshots/seattlerb/attrasgn_primary_dot_constant.txt b/test/yarp/snapshots/seattlerb/attrasgn_primary_dot_constant.txt index 562fa404d41144..f9d549a27bee7a 100644 --- a/test/yarp/snapshots/seattlerb/attrasgn_primary_dot_constant.txt +++ b/test/yarp/snapshots/seattlerb/attrasgn_primary_dot_constant.txt @@ -2,7 +2,7 @@ ProgramNode(0...7)( [], StatementsNode(0...7)( [CallNode(0...7)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, diff --git a/test/yarp/snapshots/seattlerb/backticks_interpolation_line.txt b/test/yarp/snapshots/seattlerb/backticks_interpolation_line.txt index 27d3f4e3cf8a77..86c78947fa9591 100644 --- a/test/yarp/snapshots/seattlerb/backticks_interpolation_line.txt +++ b/test/yarp/snapshots/seattlerb/backticks_interpolation_line.txt @@ -20,7 +20,7 @@ ProgramNode(0...8)( nil, nil, nil, - 0, + 2, "y" )] ), diff --git a/test/yarp/snapshots/seattlerb/bdot2.txt b/test/yarp/snapshots/seattlerb/bdot2.txt index 107f9ec20685fc..ff960bce8eb784 100644 --- a/test/yarp/snapshots/seattlerb/bdot2.txt +++ b/test/yarp/snapshots/seattlerb/bdot2.txt @@ -4,10 +4,10 @@ ProgramNode(0...14)( [RangeNode(0...4)(nil, IntegerNode(2...4)(), (0...2), 0), RangeNode(7...10)( nil, - CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "a"), + CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "a"), (7...9), 0 ), - CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 0, "c")] + CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/bdot3.txt b/test/yarp/snapshots/seattlerb/bdot3.txt index 433ff9b38f8598..abc8a679f1c0fe 100644 --- a/test/yarp/snapshots/seattlerb/bdot3.txt +++ b/test/yarp/snapshots/seattlerb/bdot3.txt @@ -4,10 +4,10 @@ ProgramNode(0...16)( [RangeNode(0...5)(nil, IntegerNode(3...5)(), (0...3), 1), RangeNode(8...12)( nil, - CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 0, "a"), + CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 2, "a"), (8...11), 1 ), - CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 0, "c")] + CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/block_break.txt b/test/yarp/snapshots/seattlerb/block_break.txt index 3d93c86f692a84..9ebe2b1488f2b7 100644 --- a/test/yarp/snapshots/seattlerb/block_break.txt +++ b/test/yarp/snapshots/seattlerb/block_break.txt @@ -17,7 +17,7 @@ ProgramNode(0...26)( nil, nil, nil, - 0, + 2, "arg" )] ), diff --git a/test/yarp/snapshots/seattlerb/block_call_defn_call_block_call.txt b/test/yarp/snapshots/seattlerb/block_call_defn_call_block_call.txt index 5c68b7247858bf..46b55171fab0af 100644 --- a/test/yarp/snapshots/seattlerb/block_call_defn_call_block_call.txt +++ b/test/yarp/snapshots/seattlerb/block_call_defn_call_block_call.txt @@ -28,7 +28,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -47,7 +47,7 @@ ProgramNode(0...30)( "a" ), CallNode(20...30)( - CallNode(20...21)(nil, nil, (20...21), nil, nil, nil, nil, 0, "e"), + CallNode(20...21)(nil, nil, (20...21), nil, nil, nil, nil, 2, "e"), (21...22), (22...23), nil, diff --git a/test/yarp/snapshots/seattlerb/block_call_dot_op2_brace_block.txt b/test/yarp/snapshots/seattlerb/block_call_dot_op2_brace_block.txt index 5b3de7d352910b..60c529a4253913 100644 --- a/test/yarp/snapshots/seattlerb/block_call_dot_op2_brace_block.txt +++ b/test/yarp/snapshots/seattlerb/block_call_dot_op2_brace_block.txt @@ -3,7 +3,7 @@ ProgramNode(0...31)( StatementsNode(0...31)( [CallNode(0...31)( CallNode(0...16)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, @@ -33,7 +33,7 @@ ProgramNode(0...31)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -65,7 +65,7 @@ ProgramNode(0...31)( (24...25) ), StatementsNode(26...27)( - [CallNode(26...27)(nil, nil, (26...27), nil, nil, nil, nil, 0, "g")] + [CallNode(26...27)(nil, nil, (26...27), nil, nil, nil, nil, 2, "g")] ), (19...21), (28...31) diff --git a/test/yarp/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt b/test/yarp/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt index 28d30af0c607db..c41a55f13fe948 100644 --- a/test/yarp/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt +++ b/test/yarp/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt @@ -3,7 +3,7 @@ ProgramNode(0...33)( StatementsNode(0...33)( [CallNode(0...33)( CallNode(0...16)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, @@ -33,7 +33,7 @@ ProgramNode(0...33)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -47,7 +47,7 @@ ProgramNode(0...33)( (17...18), nil, ArgumentsNode(19...20)( - [CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 0, "f")] + [CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 2, "f")] ), nil, BlockNode(21...33)( @@ -67,7 +67,7 @@ ProgramNode(0...33)( (26...27) ), StatementsNode(28...29)( - [CallNode(28...29)(nil, nil, (28...29), nil, nil, nil, nil, 0, "h")] + [CallNode(28...29)(nil, nil, (28...29), nil, nil, nil, nil, 2, "h")] ), (21...23), (30...33) diff --git a/test/yarp/snapshots/seattlerb/block_call_operation_colon.txt b/test/yarp/snapshots/seattlerb/block_call_operation_colon.txt index 9f2be35702d3c2..348e82f706c1a8 100644 --- a/test/yarp/snapshots/seattlerb/block_call_operation_colon.txt +++ b/test/yarp/snapshots/seattlerb/block_call_operation_colon.txt @@ -3,12 +3,12 @@ ProgramNode(0...15)( StatementsNode(0...15)( [CallNode(0...15)( CallNode(0...12)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, ArgumentsNode(4...5)( - [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "c")] + [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "c")] ), nil, BlockNode(6...12)([], nil, nil, (6...8), (9...12)), diff --git a/test/yarp/snapshots/seattlerb/block_call_operation_dot.txt b/test/yarp/snapshots/seattlerb/block_call_operation_dot.txt index 255fdc22714710..05edca98a44f6a 100644 --- a/test/yarp/snapshots/seattlerb/block_call_operation_dot.txt +++ b/test/yarp/snapshots/seattlerb/block_call_operation_dot.txt @@ -3,12 +3,12 @@ ProgramNode(0...14)( StatementsNode(0...14)( [CallNode(0...14)( CallNode(0...12)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, ArgumentsNode(4...5)( - [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "c")] + [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "c")] ), nil, BlockNode(6...12)([], nil, nil, (6...8), (9...12)), diff --git a/test/yarp/snapshots/seattlerb/block_call_paren_call_block_call.txt b/test/yarp/snapshots/seattlerb/block_call_paren_call_block_call.txt index 0689466b69b8b5..4b7916f0e6b8d1 100644 --- a/test/yarp/snapshots/seattlerb/block_call_paren_call_block_call.txt +++ b/test/yarp/snapshots/seattlerb/block_call_paren_call_block_call.txt @@ -9,7 +9,7 @@ ProgramNode(0...16)( ArgumentsNode(2...5)( [ParenthesesNode(2...5)( StatementsNode(3...4)( - [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "b")] + [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "b")] ), (2...3), (4...5) @@ -21,7 +21,7 @@ ProgramNode(0...16)( "a" ), CallNode(6...16)( - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "c"), + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "c"), (7...8), (8...9), nil, diff --git a/test/yarp/snapshots/seattlerb/block_command_operation_colon.txt b/test/yarp/snapshots/seattlerb/block_command_operation_colon.txt index 9007764dea68f4..afac178321bfd0 100644 --- a/test/yarp/snapshots/seattlerb/block_command_operation_colon.txt +++ b/test/yarp/snapshots/seattlerb/block_command_operation_colon.txt @@ -14,7 +14,7 @@ ProgramNode(0...17)( "a" ), (11...13), - (16...17), + (13...14), nil, ArgumentsNode(15...17)( [SymbolNode(15...17)((15...16), (16...17), nil, "d")] @@ -22,7 +22,7 @@ ProgramNode(0...17)( nil, nil, 0, - "d" + "c" )] ) ) diff --git a/test/yarp/snapshots/seattlerb/block_next.txt b/test/yarp/snapshots/seattlerb/block_next.txt index b7babbf781eed8..021f2ed15c55bd 100644 --- a/test/yarp/snapshots/seattlerb/block_next.txt +++ b/test/yarp/snapshots/seattlerb/block_next.txt @@ -17,7 +17,7 @@ ProgramNode(0...25)( nil, nil, nil, - 0, + 2, "arg" )] ), diff --git a/test/yarp/snapshots/seattlerb/block_return.txt b/test/yarp/snapshots/seattlerb/block_return.txt index b8adacc523c855..97fab8c51438ef 100644 --- a/test/yarp/snapshots/seattlerb/block_return.txt +++ b/test/yarp/snapshots/seattlerb/block_return.txt @@ -18,7 +18,7 @@ ProgramNode(0...27)( nil, nil, nil, - 0, + 2, "arg" )] ), diff --git a/test/yarp/snapshots/seattlerb/bug191.txt b/test/yarp/snapshots/seattlerb/bug191.txt index 0e45d22daea0b4..46d5ed6d7408f9 100644 --- a/test/yarp/snapshots/seattlerb/bug191.txt +++ b/test/yarp/snapshots/seattlerb/bug191.txt @@ -3,14 +3,14 @@ ProgramNode(0...20)( StatementsNode(0...20)( [IfNode(0...9)( nil, - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), StatementsNode(4...6)( [StringNode(4...6)((4...5), (5...5), (5...6), "")] ), ElseNode(6...9)( (6...7), StatementsNode(8...9)( - [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "b")] + [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "b")] ), nil ), @@ -18,14 +18,14 @@ ProgramNode(0...20)( ), IfNode(11...20)( nil, - CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 0, "a"), + CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 2, "a"), StatementsNode(15...17)( [StringNode(15...17)((15...16), (16...16), (16...17), "")] ), ElseNode(17...20)( (17...18), StatementsNode(19...20)( - [CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 0, "b")] + [CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 2, "b")] ), nil ), diff --git a/test/yarp/snapshots/seattlerb/bug290.txt b/test/yarp/snapshots/seattlerb/bug290.txt index 84e7cbeb976e1f..30d5780f5059f2 100644 --- a/test/yarp/snapshots/seattlerb/bug290.txt +++ b/test/yarp/snapshots/seattlerb/bug290.txt @@ -4,7 +4,7 @@ ProgramNode(0...15)( [BeginNode(0...15)( (0...5), StatementsNode(8...11)( - [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 0, "foo")] + [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 2, "foo")] ), nil, nil, diff --git a/test/yarp/snapshots/seattlerb/bug_187.txt b/test/yarp/snapshots/seattlerb/bug_187.txt index b0c76b3c4b3d87..f4ca89ff6d9066 100644 --- a/test/yarp/snapshots/seattlerb/bug_187.txt +++ b/test/yarp/snapshots/seattlerb/bug_187.txt @@ -21,7 +21,7 @@ ProgramNode(0...28)( nil, nil, nil, - 0, + 2, "a" ), (15...16), diff --git a/test/yarp/snapshots/seattlerb/bug_args__19.txt b/test/yarp/snapshots/seattlerb/bug_args__19.txt index 64dece1b91d08d..eba3f72951a957 100644 --- a/test/yarp/snapshots/seattlerb/bug_args__19.txt +++ b/test/yarp/snapshots/seattlerb/bug_args__19.txt @@ -30,7 +30,7 @@ ProgramNode(0...16)( (11...12) ), StatementsNode(13...14)( - [CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 0, "d")] + [CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 2, "d")] ), (2...3), (15...16) diff --git a/test/yarp/snapshots/seattlerb/bug_comma.txt b/test/yarp/snapshots/seattlerb/bug_comma.txt index b4dbc7db5a0990..a6dd7516aebf8e 100644 --- a/test/yarp/snapshots/seattlerb/bug_comma.txt +++ b/test/yarp/snapshots/seattlerb/bug_comma.txt @@ -18,7 +18,7 @@ ProgramNode(0...24)( nil, nil, nil, - 0, + 2, "dir" )] ), diff --git a/test/yarp/snapshots/seattlerb/bug_not_parens.txt b/test/yarp/snapshots/seattlerb/bug_not_parens.txt index 3a12af1da87388..e4a01de3f48a92 100644 --- a/test/yarp/snapshots/seattlerb/bug_not_parens.txt +++ b/test/yarp/snapshots/seattlerb/bug_not_parens.txt @@ -2,7 +2,7 @@ ProgramNode(0...6)( [], StatementsNode(0...6)( [CallNode(0...6)( - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "a"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "a"), nil, (0...3), (3...4), diff --git a/test/yarp/snapshots/seattlerb/bug_op_asgn_rescue.txt b/test/yarp/snapshots/seattlerb/bug_op_asgn_rescue.txt index 2a445ebfdb109f..e54cde69f5737f 100644 --- a/test/yarp/snapshots/seattlerb/bug_op_asgn_rescue.txt +++ b/test/yarp/snapshots/seattlerb/bug_op_asgn_rescue.txt @@ -5,7 +5,7 @@ ProgramNode(0...18)( (0...1), (2...5), RescueModifierNode(6...18)( - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b"), + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b"), (8...14), NilNode(15...18)() ), diff --git a/test/yarp/snapshots/seattlerb/call_arg_kwsplat.txt b/test/yarp/snapshots/seattlerb/call_arg_kwsplat.txt index 9571678cf7bb2d..6a98d992d3c9fc 100644 --- a/test/yarp/snapshots/seattlerb/call_arg_kwsplat.txt +++ b/test/yarp/snapshots/seattlerb/call_arg_kwsplat.txt @@ -7,7 +7,7 @@ ProgramNode(0...9)( (0...1), (1...2), ArgumentsNode(2...8)( - [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "b"), + [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "b"), KeywordHashNode(5...8)( [AssocSplatNode(5...8)(IntegerNode(7...8)(), (5...7))] )] diff --git a/test/yarp/snapshots/seattlerb/call_args_assoc_quoted.txt b/test/yarp/snapshots/seattlerb/call_args_assoc_quoted.txt index 792b07c41db537..b632adc6ba5016 100644 --- a/test/yarp/snapshots/seattlerb/call_args_assoc_quoted.txt +++ b/test/yarp/snapshots/seattlerb/call_args_assoc_quoted.txt @@ -22,7 +22,7 @@ ProgramNode(0...31)( nil, nil, nil, - 0, + 2, "k" )] ), diff --git a/test/yarp/snapshots/seattlerb/call_args_command.txt b/test/yarp/snapshots/seattlerb/call_args_command.txt index 649e360f18e38e..fa5c35b8680781 100644 --- a/test/yarp/snapshots/seattlerb/call_args_command.txt +++ b/test/yarp/snapshots/seattlerb/call_args_command.txt @@ -2,13 +2,13 @@ ProgramNode(0...9)( [], StatementsNode(0...9)( [CallNode(0...9)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, ArgumentsNode(4...9)( [CallNode(4...9)( - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "c"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "c"), (5...6), (6...7), nil, diff --git a/test/yarp/snapshots/seattlerb/call_bang_command_call.txt b/test/yarp/snapshots/seattlerb/call_bang_command_call.txt index 37cf8e13af396f..104d90d1c2a1a1 100644 --- a/test/yarp/snapshots/seattlerb/call_bang_command_call.txt +++ b/test/yarp/snapshots/seattlerb/call_bang_command_call.txt @@ -3,7 +3,7 @@ ProgramNode(0...7)( StatementsNode(0...7)( [CallNode(0...7)( CallNode(2...7)( - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "a"), + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "a"), (3...4), (4...5), nil, diff --git a/test/yarp/snapshots/seattlerb/call_begin_call_block_call.txt b/test/yarp/snapshots/seattlerb/call_begin_call_block_call.txt index 7d0e92cf1d9d36..9b60d515f0c75e 100644 --- a/test/yarp/snapshots/seattlerb/call_begin_call_block_call.txt +++ b/test/yarp/snapshots/seattlerb/call_begin_call_block_call.txt @@ -19,7 +19,7 @@ ProgramNode(0...22)( nil, nil, nil, - 0, + 2, "b" ), (9...10), diff --git a/test/yarp/snapshots/seattlerb/call_block_arg_named.txt b/test/yarp/snapshots/seattlerb/call_block_arg_named.txt index e0d6cc8e03ff76..f24da1bcd504c1 100644 --- a/test/yarp/snapshots/seattlerb/call_block_arg_named.txt +++ b/test/yarp/snapshots/seattlerb/call_block_arg_named.txt @@ -8,7 +8,7 @@ ProgramNode(0...7)( (1...2), ArgumentsNode(2...6)( [BlockArgumentNode(2...6)( - CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 0, "blk"), + CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 2, "blk"), (2...3) )] ), diff --git a/test/yarp/snapshots/seattlerb/call_env.txt b/test/yarp/snapshots/seattlerb/call_env.txt index 9f2860ab56334d..8af975cdce7ef6 100644 --- a/test/yarp/snapshots/seattlerb/call_env.txt +++ b/test/yarp/snapshots/seattlerb/call_env.txt @@ -2,7 +2,7 @@ ProgramNode(0...7)( [], StatementsNode(0...7)( [CallNode(0...7)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...7), nil, diff --git a/test/yarp/snapshots/seattlerb/call_leading_dots.txt b/test/yarp/snapshots/seattlerb/call_leading_dots.txt index 47f2c8e5c54476..bc418635a105f8 100644 --- a/test/yarp/snapshots/seattlerb/call_leading_dots.txt +++ b/test/yarp/snapshots/seattlerb/call_leading_dots.txt @@ -3,7 +3,7 @@ ProgramNode(0...7)( StatementsNode(0...7)( [CallNode(0...7)( CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (2...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/call_leading_dots_comment.txt b/test/yarp/snapshots/seattlerb/call_leading_dots_comment.txt index 0f64dd7e26b75f..e9a88d05d4b850 100644 --- a/test/yarp/snapshots/seattlerb/call_leading_dots_comment.txt +++ b/test/yarp/snapshots/seattlerb/call_leading_dots_comment.txt @@ -3,7 +3,7 @@ ProgramNode(0...11)( StatementsNode(0...11)( [CallNode(0...11)( CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (2...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/call_trailing_dots.txt b/test/yarp/snapshots/seattlerb/call_trailing_dots.txt index 929decb5f14742..a2ccf8addde234 100644 --- a/test/yarp/snapshots/seattlerb/call_trailing_dots.txt +++ b/test/yarp/snapshots/seattlerb/call_trailing_dots.txt @@ -3,7 +3,7 @@ ProgramNode(0...7)( StatementsNode(0...7)( [CallNode(0...7)( CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/case_in.txt b/test/yarp/snapshots/seattlerb/case_in.txt index 981905526cecd3..e339f35c8c8b61 100644 --- a/test/yarp/snapshots/seattlerb/case_in.txt +++ b/test/yarp/snapshots/seattlerb/case_in.txt @@ -478,7 +478,7 @@ ProgramNode(0...746)( nil, nil, nil, - 0, + 2, "a" ), (604...605), diff --git a/test/yarp/snapshots/seattlerb/cond_unary_minus.txt b/test/yarp/snapshots/seattlerb/cond_unary_minus.txt index 79d8f4a09a68cd..d4453066740ebd 100644 --- a/test/yarp/snapshots/seattlerb/cond_unary_minus.txt +++ b/test/yarp/snapshots/seattlerb/cond_unary_minus.txt @@ -1,22 +1,6 @@ ProgramNode(0...10)( [], StatementsNode(0...10)( - [IfNode(0...10)( - (0...2), - CallNode(3...5)( - IntegerNode(4...5)(), - nil, - (3...4), - nil, - nil, - nil, - nil, - 0, - "-@" - ), - nil, - nil, - (7...10) - )] + [IfNode(0...10)((0...2), IntegerNode(3...5)(), nil, nil, (7...10))] ) ) diff --git a/test/yarp/snapshots/seattlerb/defn_oneliner_noargs.txt b/test/yarp/snapshots/seattlerb/defn_oneliner_noargs.txt index b560a37f612e5a..683c405b1853f0 100644 --- a/test/yarp/snapshots/seattlerb/defn_oneliner_noargs.txt +++ b/test/yarp/snapshots/seattlerb/defn_oneliner_noargs.txt @@ -14,7 +14,7 @@ ProgramNode(0...17)( nil, nil, nil, - 0, + 2, "system" )] ), diff --git a/test/yarp/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt b/test/yarp/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt index 7a106c57d680c4..bbf7fd2dcaebd9 100644 --- a/test/yarp/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt +++ b/test/yarp/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt @@ -14,7 +14,7 @@ ProgramNode(0...19)( nil, nil, nil, - 0, + 2, "system" )] ), diff --git a/test/yarp/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt b/test/yarp/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt index 57e5932ab46435..d223e069137481 100644 --- a/test/yarp/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt +++ b/test/yarp/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt @@ -21,7 +21,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "x" ), (15...16), diff --git a/test/yarp/snapshots/seattlerb/defs_endless_command.txt b/test/yarp/snapshots/seattlerb/defs_endless_command.txt index 11572715afa907..3675f26ddffe77 100644 --- a/test/yarp/snapshots/seattlerb/defs_endless_command.txt +++ b/test/yarp/snapshots/seattlerb/defs_endless_command.txt @@ -3,7 +3,7 @@ ProgramNode(0...35)( StatementsNode(0...35)( [DefNode(0...35)( (6...17), - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "x"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "x"), nil, StatementsNode(20...35)( [CallNode(20...35)( diff --git a/test/yarp/snapshots/seattlerb/defs_endless_command_rescue.txt b/test/yarp/snapshots/seattlerb/defs_endless_command_rescue.txt index b657a3f19d0ac1..e032fff9a6b45f 100644 --- a/test/yarp/snapshots/seattlerb/defs_endless_command_rescue.txt +++ b/test/yarp/snapshots/seattlerb/defs_endless_command_rescue.txt @@ -3,7 +3,7 @@ ProgramNode(0...45)( StatementsNode(0...45)( [DefNode(0...45)( (6...17), - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "x"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "x"), nil, StatementsNode(20...45)( [CallNode(20...45)( diff --git a/test/yarp/snapshots/seattlerb/do_bug.txt b/test/yarp/snapshots/seattlerb/do_bug.txt index 8226a3fa450101..269d349519a6ce 100644 --- a/test/yarp/snapshots/seattlerb/do_bug.txt +++ b/test/yarp/snapshots/seattlerb/do_bug.txt @@ -13,7 +13,7 @@ ProgramNode(0...33)( "a" ), CallNode(4...33)( - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "a"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "a"), (5...6), (6...7), nil, diff --git a/test/yarp/snapshots/seattlerb/dot2_nil__26.txt b/test/yarp/snapshots/seattlerb/dot2_nil__26.txt index 2db10727011070..38e8dfd9c0f009 100644 --- a/test/yarp/snapshots/seattlerb/dot2_nil__26.txt +++ b/test/yarp/snapshots/seattlerb/dot2_nil__26.txt @@ -2,7 +2,7 @@ ProgramNode(0...3)( [], StatementsNode(0...3)( [RangeNode(0...3)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), nil, (1...3), 0 diff --git a/test/yarp/snapshots/seattlerb/dot3_nil__26.txt b/test/yarp/snapshots/seattlerb/dot3_nil__26.txt index fce5824c9dab4b..91cf903a9a2d54 100644 --- a/test/yarp/snapshots/seattlerb/dot3_nil__26.txt +++ b/test/yarp/snapshots/seattlerb/dot3_nil__26.txt @@ -2,7 +2,7 @@ ProgramNode(0...4)( [], StatementsNode(0...4)( [RangeNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), nil, (1...4), 1 diff --git a/test/yarp/snapshots/seattlerb/dstr_evstr.txt b/test/yarp/snapshots/seattlerb/dstr_evstr.txt index c744aeee377f2d..75377e9c7faaf9 100644 --- a/test/yarp/snapshots/seattlerb/dstr_evstr.txt +++ b/test/yarp/snapshots/seattlerb/dstr_evstr.txt @@ -13,7 +13,7 @@ ProgramNode(0...12)( EmbeddedStatementsNode(7...11)( (7...9), StatementsNode(9...10)( - [CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "b")] + [CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "b")] ), (10...11) )], diff --git a/test/yarp/snapshots/seattlerb/dstr_evstr_empty_end.txt b/test/yarp/snapshots/seattlerb/dstr_evstr_empty_end.txt index 113270b9c03b26..e4a9c81b8854c1 100644 --- a/test/yarp/snapshots/seattlerb/dstr_evstr_empty_end.txt +++ b/test/yarp/snapshots/seattlerb/dstr_evstr_empty_end.txt @@ -14,7 +14,7 @@ ProgramNode(0...11)( nil, nil, nil, - 0, + 2, "field" )] ), diff --git a/test/yarp/snapshots/seattlerb/dsym_esc_to_sym.txt b/test/yarp/snapshots/seattlerb/dsym_esc_to_sym.txt index 41a66c61430996..16cd806d018f85 100644 --- a/test/yarp/snapshots/seattlerb/dsym_esc_to_sym.txt +++ b/test/yarp/snapshots/seattlerb/dsym_esc_to_sym.txt @@ -1,10 +1,4 @@ ProgramNode(0...17)( [], - StatementsNode(0...17)( - [InterpolatedSymbolNode(0...17)( - (0...2), - [StringNode(2...16)(nil, (2...16), nil, "Varietà")], - (16...17) - )] - ) + StatementsNode(0...17)([SymbolNode(0...17)(nil, (2...16), nil, "Varietà")]) ) diff --git a/test/yarp/snapshots/seattlerb/dsym_to_sym.txt b/test/yarp/snapshots/seattlerb/dsym_to_sym.txt index 67c71efb2daf15..f2e3452dc12e9b 100644 --- a/test/yarp/snapshots/seattlerb/dsym_to_sym.txt +++ b/test/yarp/snapshots/seattlerb/dsym_to_sym.txt @@ -2,16 +2,8 @@ ProgramNode(0...32)( [], StatementsNode(0...32)( [AliasNode(0...17)( - InterpolatedSymbolNode(6...11)( - (6...8), - [StringNode(8...10)(nil, (8...10), nil, "<<")], - (10...11) - ), - InterpolatedSymbolNode(12...17)( - (12...14), - [StringNode(14...16)(nil, (14...16), nil, ">>")], - (16...17) - ), + SymbolNode(6...11)(nil, (8...10), nil, "<<"), + SymbolNode(12...17)(nil, (14...16), nil, ">>"), (0...5) ), AliasNode(19...32)( diff --git a/test/yarp/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt b/test/yarp/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt index 805f6f9bd0eae0..e277d15a349438 100644 --- a/test/yarp/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt +++ b/test/yarp/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt @@ -2,12 +2,12 @@ ProgramNode(0...29)( [], StatementsNode(0...29)( [CallNode(0...29)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "h"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "h"), nil, (1...4), (1...2), ArgumentsNode(2...29)( - [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "k"), + [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "k"), BeginNode(5...29)( (5...10), StatementsNode(18...20)([IntegerNode(18...20)()]), diff --git a/test/yarp/snapshots/seattlerb/evstr_evstr.txt b/test/yarp/snapshots/seattlerb/evstr_evstr.txt index e4b49cb84d6649..f194b1b94a968e 100644 --- a/test/yarp/snapshots/seattlerb/evstr_evstr.txt +++ b/test/yarp/snapshots/seattlerb/evstr_evstr.txt @@ -6,14 +6,14 @@ ProgramNode(0...10)( [EmbeddedStatementsNode(1...5)( (1...3), StatementsNode(3...4)( - [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "a")] + [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "a")] ), (4...5) ), EmbeddedStatementsNode(5...9)( (5...7), StatementsNode(7...8)( - [CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "b")] + [CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "b")] ), (8...9) )], diff --git a/test/yarp/snapshots/seattlerb/evstr_str.txt b/test/yarp/snapshots/seattlerb/evstr_str.txt index 4571199189f762..2ebd4e46398021 100644 --- a/test/yarp/snapshots/seattlerb/evstr_str.txt +++ b/test/yarp/snapshots/seattlerb/evstr_str.txt @@ -6,7 +6,7 @@ ProgramNode(0...8)( [EmbeddedStatementsNode(1...5)( (1...3), StatementsNode(3...4)( - [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "a")] + [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "a")] ), (4...5) ), diff --git a/test/yarp/snapshots/seattlerb/expr_not_bang.txt b/test/yarp/snapshots/seattlerb/expr_not_bang.txt index ed1649eff8db17..43e47cb03b4987 100644 --- a/test/yarp/snapshots/seattlerb/expr_not_bang.txt +++ b/test/yarp/snapshots/seattlerb/expr_not_bang.txt @@ -8,7 +8,7 @@ ProgramNode(0...5)( (2...3), nil, ArgumentsNode(4...5)( - [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "b")] + [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "b")] ), nil, nil, diff --git a/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt b/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt index ffb6ee684b84eb..bca1426fc13fe5 100644 --- a/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt +++ b/test/yarp/snapshots/seattlerb/flip2_env_lvar.txt @@ -3,11 +3,11 @@ ProgramNode(0...16)( StatementsNode(0...16)( [IfNode(0...16)( (0...2), - RangeNode(3...7)( - CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "a"), - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b"), + FlipFlopNode(3...7)( + CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "a"), + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b"), (4...6), - 2 + 0 ), nil, nil, diff --git a/test/yarp/snapshots/seattlerb/heredoc_nested.txt b/test/yarp/snapshots/seattlerb/heredoc_nested.txt new file mode 100644 index 00000000000000..fdc29de9e0dade --- /dev/null +++ b/test/yarp/snapshots/seattlerb/heredoc_nested.txt @@ -0,0 +1,27 @@ +ProgramNode(0...23)( + [], + StatementsNode(0...23)( + [ArrayNode(0...23)( + [InterpolatedStringNode(1...21)( + (1...4), + [EmbeddedStatementsNode(6...12)( + (6...8), + StatementsNode(8...17)( + [InterpolatedStringNode(8...17)( + (8...11), + [StringNode(13...15)(nil, (13...15), nil, "b\n")], + (15...17) + )] + ), + (11...12) + ), + StringNode(12...13)(nil, (12...13), nil, "\n"), + StringNode(17...19)(nil, (17...19), nil, "a\n")], + (19...21) + ), + IntegerNode(21...22)()], + (0...1), + (22...23) + )] + ) +) diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt index 92628b34710c91..d5f32777c1264f 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt @@ -25,7 +25,7 @@ ProgramNode(0...20)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers.txt b/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers.txt index 100e56df89995a..69736976411983 100644 --- a/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers.txt +++ b/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers.txt @@ -17,7 +17,7 @@ ProgramNode(0...104)( "p" ), CallNode(16...21)( - CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 0, "a"), + CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 2, "a"), (17...18), (18...19), nil, @@ -28,7 +28,7 @@ ProgramNode(0...104)( "b" ), CallNode(24...32)( - CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 0, "c"), + CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 2, "c"), (25...26), (26...27), nil, @@ -41,7 +41,7 @@ ProgramNode(0...104)( "d" ), CallNode(35...40)( - CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 0, "e"), + CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 2, "e"), (36...37), (37...38), nil, @@ -52,7 +52,7 @@ ProgramNode(0...104)( "f" ), CallNode(43...51)( - CallNode(43...44)(nil, nil, (43...44), nil, nil, nil, nil, 0, "g"), + CallNode(43...44)(nil, nil, (43...44), nil, nil, nil, nil, 2, "g"), (44...45), (45...46), nil, @@ -76,7 +76,7 @@ ProgramNode(0...104)( "p" ), CallNode(61...67)( - CallNode(61...62)(nil, nil, (61...62), nil, nil, nil, nil, 0, "a"), + CallNode(61...62)(nil, nil, (61...62), nil, nil, nil, nil, 2, "a"), (62...63), (63...64), (64...65), @@ -87,7 +87,7 @@ ProgramNode(0...104)( "b" ), CallNode(70...79)( - CallNode(70...71)(nil, nil, (70...71), nil, nil, nil, nil, 0, "c"), + CallNode(70...71)(nil, nil, (70...71), nil, nil, nil, nil, 2, "c"), (71...72), (72...73), (73...74), @@ -100,7 +100,7 @@ ProgramNode(0...104)( "d" ), CallNode(82...88)( - CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 0, "e"), + CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 2, "e"), (83...84), (84...85), (85...86), @@ -111,7 +111,7 @@ ProgramNode(0...104)( "f" ), CallNode(91...100)( - CallNode(91...92)(nil, nil, (91...92), nil, nil, nil, nil, 0, "g"), + CallNode(91...92)(nil, nil, (91...92), nil, nil, nil, nil, 2, "g"), (92...93), (93...94), (94...95), diff --git a/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers2.txt b/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers2.txt index 49bb711232237d..86433437ce1ea6 100644 --- a/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers2.txt +++ b/test/yarp/snapshots/seattlerb/i_fucking_hate_line_numbers2.txt @@ -47,6 +47,6 @@ ProgramNode(0...48)( nil, (43...46) ), - CallNode(47...48)(nil, nil, (47...48), nil, nil, nil, nil, 0, "a")] + CallNode(47...48)(nil, nil, (47...48), nil, nil, nil, nil, 2, "a")] ) ) diff --git a/test/yarp/snapshots/seattlerb/index_0.txt b/test/yarp/snapshots/seattlerb/index_0.txt index 7e2d6f980ff5e7..42a7239752988d 100644 --- a/test/yarp/snapshots/seattlerb/index_0.txt +++ b/test/yarp/snapshots/seattlerb/index_0.txt @@ -2,12 +2,12 @@ ProgramNode(0...7)( [], StatementsNode(0...7)( [CallNode(0...7)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), nil, (1...3), (1...2), ArgumentsNode(6...7)( - [CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b")] + [CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b")] ), (2...3), nil, diff --git a/test/yarp/snapshots/seattlerb/index_0_opasgn.txt b/test/yarp/snapshots/seattlerb/index_0_opasgn.txt index 3271bfa5980bf6..1f6d27974ed588 100644 --- a/test/yarp/snapshots/seattlerb/index_0_opasgn.txt +++ b/test/yarp/snapshots/seattlerb/index_0_opasgn.txt @@ -3,7 +3,7 @@ ProgramNode(0...8)( StatementsNode(0...8)( [CallOperatorWriteNode(0...8)( CallNode(0...3)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), nil, (1...3), (1...2), @@ -14,7 +14,7 @@ ProgramNode(0...8)( "[]=" ), (4...6), - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "b"), + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "b"), :+ )] ) diff --git a/test/yarp/snapshots/seattlerb/kill_me4.txt b/test/yarp/snapshots/seattlerb/kill_me4.txt index 80211017a6da9a..afca77c5fa310a 100644 --- a/test/yarp/snapshots/seattlerb/kill_me4.txt +++ b/test/yarp/snapshots/seattlerb/kill_me4.txt @@ -6,7 +6,7 @@ ProgramNode(0...17)( 0, IfNode(2...17)( nil, - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "b"), + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "b"), StatementsNode(6...10)([TrueNode(6...10)()]), ElseNode(10...17)( (10...11), diff --git a/test/yarp/snapshots/seattlerb/label_vs_string.txt b/test/yarp/snapshots/seattlerb/label_vs_string.txt index bc2718a2084aec..f647e6da0e4859 100644 --- a/test/yarp/snapshots/seattlerb/label_vs_string.txt +++ b/test/yarp/snapshots/seattlerb/label_vs_string.txt @@ -2,7 +2,7 @@ ProgramNode(0...12)( [], StatementsNode(0...12)( [CallNode(0...12)( - CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 0, "_buf"), + CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 2, "_buf"), nil, (5...7), nil, diff --git a/test/yarp/snapshots/seattlerb/lasgn_command.txt b/test/yarp/snapshots/seattlerb/lasgn_command.txt index 3f27e4f78c1eec..696be7871609cc 100644 --- a/test/yarp/snapshots/seattlerb/lasgn_command.txt +++ b/test/yarp/snapshots/seattlerb/lasgn_command.txt @@ -5,7 +5,7 @@ ProgramNode(0...9)( :a, 0, CallNode(4...9)( - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "b"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "b"), (5...6), (6...7), nil, diff --git a/test/yarp/snapshots/seattlerb/lasgn_middle_splat.txt b/test/yarp/snapshots/seattlerb/lasgn_middle_splat.txt index b9cb8e9f9b0631..623f6dc1257f95 100644 --- a/test/yarp/snapshots/seattlerb/lasgn_middle_splat.txt +++ b/test/yarp/snapshots/seattlerb/lasgn_middle_splat.txt @@ -5,12 +5,12 @@ ProgramNode(0...12)( :a, 0, ArrayNode(4...12)( - [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "b"), + [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "b"), SplatNode(7...9)( (7...8), - CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "c") + CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "c") ), - CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 0, "d")], + CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 2, "d")], nil, nil ), diff --git a/test/yarp/snapshots/seattlerb/masgn_anon_splat_arg.txt b/test/yarp/snapshots/seattlerb/masgn_anon_splat_arg.txt index eb18d7615bf99b..738ee25165893a 100644 --- a/test/yarp/snapshots/seattlerb/masgn_anon_splat_arg.txt +++ b/test/yarp/snapshots/seattlerb/masgn_anon_splat_arg.txt @@ -11,7 +11,7 @@ ProgramNode(0...8)( ), LocalVariableWriteNode(3...4)(:a, 0, nil, (3...4), nil)], (5...6), - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "b"), + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "b"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/masgn_arg_colon_arg.txt b/test/yarp/snapshots/seattlerb/masgn_arg_colon_arg.txt index 4b90bf3ddc426e..1b1c0f43badc08 100644 --- a/test/yarp/snapshots/seattlerb/masgn_arg_colon_arg.txt +++ b/test/yarp/snapshots/seattlerb/masgn_arg_colon_arg.txt @@ -4,7 +4,7 @@ ProgramNode(0...11)( [MultiWriteNode(0...11)( [LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil), CallNode(3...7)( - CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "b"), + CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "b"), (4...6), (6...7), nil, @@ -15,7 +15,7 @@ ProgramNode(0...11)( "c=" )], (8...9), - CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 0, "d"), + CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 2, "d"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/masgn_arg_ident.txt b/test/yarp/snapshots/seattlerb/masgn_arg_ident.txt index 7ca20a45ada472..53ecd8fd183fc6 100644 --- a/test/yarp/snapshots/seattlerb/masgn_arg_ident.txt +++ b/test/yarp/snapshots/seattlerb/masgn_arg_ident.txt @@ -4,7 +4,7 @@ ProgramNode(0...10)( [MultiWriteNode(0...10)( [LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil), CallNode(3...6)( - CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "b"), + CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "b"), (4...5), (5...6), nil, @@ -15,7 +15,7 @@ ProgramNode(0...10)( "C=" )], (7...8), - CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "d"), + CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "d"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/masgn_arg_splat_arg.txt b/test/yarp/snapshots/seattlerb/masgn_arg_splat_arg.txt index cdabe61852f757..285c22f660ba87 100644 --- a/test/yarp/snapshots/seattlerb/masgn_arg_splat_arg.txt +++ b/test/yarp/snapshots/seattlerb/masgn_arg_splat_arg.txt @@ -9,7 +9,7 @@ ProgramNode(0...12)( ), LocalVariableWriteNode(7...8)(:c, 0, nil, (7...8), nil)], (9...10), - CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 0, "d"), + CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 2, "d"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/masgn_colon2.txt b/test/yarp/snapshots/seattlerb/masgn_colon2.txt index 32d035afa3eb48..490d1657b03762 100644 --- a/test/yarp/snapshots/seattlerb/masgn_colon2.txt +++ b/test/yarp/snapshots/seattlerb/masgn_colon2.txt @@ -5,7 +5,7 @@ ProgramNode(0...14)( [LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil), ConstantPathWriteNode(3...7)( ConstantPathNode(3...7)( - CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "b"), + CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "b"), ConstantReadNode(6...7)(), (4...6) ), diff --git a/test/yarp/snapshots/seattlerb/masgn_command_call.txt b/test/yarp/snapshots/seattlerb/masgn_command_call.txt index 8ffc56de6ffb5b..ef2eab9d34ed0a 100644 --- a/test/yarp/snapshots/seattlerb/masgn_command_call.txt +++ b/test/yarp/snapshots/seattlerb/masgn_command_call.txt @@ -6,7 +6,7 @@ ProgramNode(0...10)( SplatNode(1...2)((1...2), nil)], (3...4), CallNode(5...10)( - CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 0, "b"), + CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 2, "b"), (6...7), (7...8), nil, diff --git a/test/yarp/snapshots/seattlerb/masgn_double_paren.txt b/test/yarp/snapshots/seattlerb/masgn_double_paren.txt index 85b4f05f312622..4f19128a219d20 100644 --- a/test/yarp/snapshots/seattlerb/masgn_double_paren.txt +++ b/test/yarp/snapshots/seattlerb/masgn_double_paren.txt @@ -11,7 +11,7 @@ ProgramNode(2...9)( (5...6) )], (7...8), - CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "c"), + CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "c"), (0...1), (6...7) )] diff --git a/test/yarp/snapshots/seattlerb/masgn_paren.txt b/test/yarp/snapshots/seattlerb/masgn_paren.txt index cdf4678bc4135f..b47b00c417f004 100644 --- a/test/yarp/snapshots/seattlerb/masgn_paren.txt +++ b/test/yarp/snapshots/seattlerb/masgn_paren.txt @@ -6,7 +6,7 @@ ProgramNode(1...12)( LocalVariableWriteNode(4...5)(:b, 0, nil, (4...5), nil)], (7...8), CallNode(9...12)( - CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "c"), + CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "c"), (10...11), (11...12), nil, diff --git a/test/yarp/snapshots/seattlerb/masgn_splat_arg.txt b/test/yarp/snapshots/seattlerb/masgn_splat_arg.txt index 783ddde19aab22..21844a7c542b26 100644 --- a/test/yarp/snapshots/seattlerb/masgn_splat_arg.txt +++ b/test/yarp/snapshots/seattlerb/masgn_splat_arg.txt @@ -14,7 +14,7 @@ ProgramNode(0...9)( ), LocalVariableWriteNode(4...5)(:b, 0, nil, (4...5), nil)], (6...7), - CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "c"), + CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "c"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/masgn_splat_arg_arg.txt b/test/yarp/snapshots/seattlerb/masgn_splat_arg_arg.txt index be516e972b5fc3..af7f0b1b35721f 100644 --- a/test/yarp/snapshots/seattlerb/masgn_splat_arg_arg.txt +++ b/test/yarp/snapshots/seattlerb/masgn_splat_arg_arg.txt @@ -15,7 +15,7 @@ ProgramNode(0...12)( LocalVariableWriteNode(4...5)(:b, 0, nil, (4...5), nil), LocalVariableWriteNode(7...8)(:c, 0, nil, (7...8), nil)], (9...10), - CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 0, "d"), + CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 2, "d"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/masgn_var_star_var.txt b/test/yarp/snapshots/seattlerb/masgn_var_star_var.txt index b172d0bb868cd6..b2ce2af1738528 100644 --- a/test/yarp/snapshots/seattlerb/masgn_var_star_var.txt +++ b/test/yarp/snapshots/seattlerb/masgn_var_star_var.txt @@ -6,7 +6,7 @@ ProgramNode(0...11)( SplatNode(3...4)((3...4), nil), LocalVariableWriteNode(6...7)(:b, 0, nil, (6...7), nil)], (8...9), - CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 0, "c"), + CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 2, "c"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/messy_op_asgn_lineno.txt b/test/yarp/snapshots/seattlerb/messy_op_asgn_lineno.txt index 146ce2d61ada7b..71a28870bd2240 100644 --- a/test/yarp/snapshots/seattlerb/messy_op_asgn_lineno.txt +++ b/test/yarp/snapshots/seattlerb/messy_op_asgn_lineno.txt @@ -30,7 +30,7 @@ ProgramNode(0...15)( nil, nil, nil, - 0, + 2, "e" )] ), diff --git a/test/yarp/snapshots/seattlerb/method_call_assoc_trailing_comma.txt b/test/yarp/snapshots/seattlerb/method_call_assoc_trailing_comma.txt index 9b8bec66d2dfa0..1c0c544e85d5da 100644 --- a/test/yarp/snapshots/seattlerb/method_call_assoc_trailing_comma.txt +++ b/test/yarp/snapshots/seattlerb/method_call_assoc_trailing_comma.txt @@ -2,7 +2,7 @@ ProgramNode(0...10)( [], StatementsNode(0...10)( [CallNode(0...10)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), (3...4), diff --git a/test/yarp/snapshots/seattlerb/method_call_trailing_comma.txt b/test/yarp/snapshots/seattlerb/method_call_trailing_comma.txt index 93a93d6a15f36e..18089701db8f01 100644 --- a/test/yarp/snapshots/seattlerb/method_call_trailing_comma.txt +++ b/test/yarp/snapshots/seattlerb/method_call_trailing_comma.txt @@ -2,7 +2,7 @@ ProgramNode(0...7)( [], StatementsNode(0...7)( [CallNode(0...7)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), (3...4), diff --git a/test/yarp/snapshots/seattlerb/mlhs_back_anonsplat.txt b/test/yarp/snapshots/seattlerb/mlhs_back_anonsplat.txt index 410cfc8f14761a..c046218e1ee69e 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_back_anonsplat.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_back_anonsplat.txt @@ -7,7 +7,7 @@ ProgramNode(0...14)( LocalVariableWriteNode(6...7)(:c, 0, nil, (6...7), nil), SplatNode(9...10)((9...10), nil)], (11...12), - CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 0, "f"), + CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 2, "f"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/mlhs_back_splat.txt b/test/yarp/snapshots/seattlerb/mlhs_back_splat.txt index 8086347e1392e5..1ba49176842da2 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_back_splat.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_back_splat.txt @@ -10,7 +10,7 @@ ProgramNode(0...15)( LocalVariableWriteNode(10...11)(:s, 0, nil, (10...11), nil) )], (12...13), - CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 0, "f"), + CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "f"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/mlhs_front_anonsplat.txt b/test/yarp/snapshots/seattlerb/mlhs_front_anonsplat.txt index beaadf1892c605..b035fbb8b7d883 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_front_anonsplat.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_front_anonsplat.txt @@ -13,7 +13,7 @@ ProgramNode(0...14)( LocalVariableWriteNode(6...7)(:y, 0, nil, (6...7), nil), LocalVariableWriteNode(9...10)(:z, 0, nil, (9...10), nil)], (11...12), - CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 0, "f"), + CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 2, "f"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/mlhs_front_splat.txt b/test/yarp/snapshots/seattlerb/mlhs_front_splat.txt index 0c786546d32c31..653b0e167ff5e8 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_front_splat.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_front_splat.txt @@ -16,7 +16,7 @@ ProgramNode(0...15)( LocalVariableWriteNode(7...8)(:y, 0, nil, (7...8), nil), LocalVariableWriteNode(10...11)(:z, 0, nil, (10...11), nil)], (12...13), - CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 0, "f"), + CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "f"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/mlhs_keyword.txt b/test/yarp/snapshots/seattlerb/mlhs_keyword.txt index 2b5fc37ee078f3..8910c8b5d1a990 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_keyword.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_keyword.txt @@ -2,7 +2,7 @@ ProgramNode(0...16)( [], StatementsNode(0...16)( [CallNode(0...16)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...4), (4...5), diff --git a/test/yarp/snapshots/seattlerb/mlhs_mid_anonsplat.txt b/test/yarp/snapshots/seattlerb/mlhs_mid_anonsplat.txt index 54cab7d7f8164f..313a4590f7ff5d 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_mid_anonsplat.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_mid_anonsplat.txt @@ -10,7 +10,7 @@ ProgramNode(0...23)( LocalVariableWriteNode(15...16)(:y, 0, nil, (15...16), nil), LocalVariableWriteNode(18...19)(:z, 0, nil, (18...19), nil)], (20...21), - CallNode(22...23)(nil, nil, (22...23), nil, nil, nil, nil, 0, "f"), + CallNode(22...23)(nil, nil, (22...23), nil, nil, nil, nil, 2, "f"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/mlhs_mid_splat.txt b/test/yarp/snapshots/seattlerb/mlhs_mid_splat.txt index e8dd882dd293bd..5e307e81944223 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_mid_splat.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_mid_splat.txt @@ -13,7 +13,7 @@ ProgramNode(0...24)( LocalVariableWriteNode(16...17)(:y, 0, nil, (16...17), nil), LocalVariableWriteNode(19...20)(:z, 0, nil, (19...20), nil)], (21...22), - CallNode(23...24)(nil, nil, (23...24), nil, nil, nil, nil, 0, "f"), + CallNode(23...24)(nil, nil, (23...24), nil, nil, nil, nil, 2, "f"), nil, nil )] diff --git a/test/yarp/snapshots/seattlerb/mlhs_rescue.txt b/test/yarp/snapshots/seattlerb/mlhs_rescue.txt index cd6276e76e1a81..13d418461bccb0 100644 --- a/test/yarp/snapshots/seattlerb/mlhs_rescue.txt +++ b/test/yarp/snapshots/seattlerb/mlhs_rescue.txt @@ -6,7 +6,7 @@ ProgramNode(0...18)( LocalVariableWriteNode(3...4)(:b, 0, nil, (3...4), nil)], (5...6), RescueModifierNode(7...18)( - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "f"), + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "f"), (9...15), IntegerNode(16...18)() ), diff --git a/test/yarp/snapshots/seattlerb/motherfuckin_leading_dots.txt b/test/yarp/snapshots/seattlerb/motherfuckin_leading_dots.txt index 352bcbab600fee..881cc6d5a873fe 100644 --- a/test/yarp/snapshots/seattlerb/motherfuckin_leading_dots.txt +++ b/test/yarp/snapshots/seattlerb/motherfuckin_leading_dots.txt @@ -2,7 +2,7 @@ ProgramNode(0...4)( [], StatementsNode(0...4)( [CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (2...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/op_asgn_command_call.txt b/test/yarp/snapshots/seattlerb/op_asgn_command_call.txt index 256a063f406217..1daadaab67948b 100644 --- a/test/yarp/snapshots/seattlerb/op_asgn_command_call.txt +++ b/test/yarp/snapshots/seattlerb/op_asgn_command_call.txt @@ -5,7 +5,7 @@ ProgramNode(0...11)( (0...1), (2...5), CallNode(6...11)( - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b"), + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b"), (7...8), (8...9), nil, diff --git a/test/yarp/snapshots/seattlerb/op_asgn_index_command_call.txt b/test/yarp/snapshots/seattlerb/op_asgn_index_command_call.txt index 9b7b6f93da0558..5ae2a48469e3d9 100644 --- a/test/yarp/snapshots/seattlerb/op_asgn_index_command_call.txt +++ b/test/yarp/snapshots/seattlerb/op_asgn_index_command_call.txt @@ -3,7 +3,7 @@ ProgramNode(0...16)( StatementsNode(0...16)( [CallOperatorOrWriteNode(0...16)( CallNode(0...5)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), nil, (1...5), (1...2), diff --git a/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt b/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt index 051acb85b532af..0cd3775202dff6 100644 --- a/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt +++ b/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt @@ -14,7 +14,7 @@ ProgramNode(0...11)( (8...9), nil, ArgumentsNode(10...11)( - [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 0, "d")] + [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 2, "d")] ), nil, nil, diff --git a/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt b/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt index 5ca0e3ce5c1f61..5f369122ffa0b4 100644 --- a/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt +++ b/test/yarp/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt @@ -20,7 +20,7 @@ ProgramNode(0...11)( (8...9), nil, ArgumentsNode(10...11)( - [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 0, "d")] + [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 2, "d")] ), nil, nil, diff --git a/test/yarp/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt b/test/yarp/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt index 363660cf20ac99..2d5ef0f0df205f 100644 --- a/test/yarp/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt +++ b/test/yarp/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt @@ -3,7 +3,7 @@ ProgramNode(0...11)( StatementsNode(0...11)( [CallOperatorOrWriteNode(0...11)( CallNode(0...3)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, diff --git a/test/yarp/snapshots/seattlerb/parse_if_not_canonical.txt b/test/yarp/snapshots/seattlerb/parse_if_not_canonical.txt index 3d90e11f4c896a..223ede6af85291 100644 --- a/test/yarp/snapshots/seattlerb/parse_if_not_canonical.txt +++ b/test/yarp/snapshots/seattlerb/parse_if_not_canonical.txt @@ -5,7 +5,7 @@ ProgramNode(0...41)( (0...2), CallNode(3...15)( CallNode(7...15)( - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "var"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "var"), (10...11), (11...15), nil, diff --git a/test/yarp/snapshots/seattlerb/parse_if_not_noncanonical.txt b/test/yarp/snapshots/seattlerb/parse_if_not_noncanonical.txt index 3d90e11f4c896a..223ede6af85291 100644 --- a/test/yarp/snapshots/seattlerb/parse_if_not_noncanonical.txt +++ b/test/yarp/snapshots/seattlerb/parse_if_not_noncanonical.txt @@ -5,7 +5,7 @@ ProgramNode(0...41)( (0...2), CallNode(3...15)( CallNode(7...15)( - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "var"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "var"), (10...11), (11...15), nil, diff --git a/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment.txt b/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment.txt index 76b2ec33fabfc6..f6f0333e91df56 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment.txt @@ -1,8 +1,8 @@ ProgramNode(0...15)( [], StatementsNode(0...15)( - [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "b"), - CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 0, "c")] + [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "b"), + CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment_leading_newlines.txt b/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment_leading_newlines.txt index 0345dae43e9008..2650fb5c12a1b9 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment_leading_newlines.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_block_inline_comment_leading_newlines.txt @@ -1,8 +1,8 @@ ProgramNode(3...36)( [], StatementsNode(3...36)( - [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 0, "a"), - CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 0, "b"), - CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 0, "c")] + [CallNode(3...4)(nil, nil, (3...4), nil, nil, nil, nil, 2, "a"), + CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 2, "b"), + CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_block_inline_multiline_comment.txt b/test/yarp/snapshots/seattlerb/parse_line_block_inline_multiline_comment.txt index d8486cb823a638..0a01c627fbb74a 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_block_inline_multiline_comment.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_block_inline_multiline_comment.txt @@ -1,8 +1,8 @@ ProgramNode(0...33)( [], StatementsNode(0...33)( - [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "b"), - CallNode(32...33)(nil, nil, (32...33), nil, nil, nil, nil, 0, "c")] + [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "b"), + CallNode(32...33)(nil, nil, (32...33), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_dot2.txt b/test/yarp/snapshots/seattlerb/parse_line_dot2.txt index b535ac7c1c9114..04d53e2c51759d 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_dot2.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_dot2.txt @@ -3,11 +3,11 @@ ProgramNode(0...13)( StatementsNode(0...13)( [RangeNode(0...5)(IntegerNode(0...1)(), IntegerNode(4...5)(), (1...3), 0), RangeNode(6...11)( - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "a"), - CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 0, "b"), + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "a"), + CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 2, "b"), (7...9), 0 ), - CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 0, "c")] + CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_dot2_open.txt b/test/yarp/snapshots/seattlerb/parse_line_dot2_open.txt index 757e052c080113..35faa728edc321 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_dot2_open.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_dot2_open.txt @@ -3,11 +3,11 @@ ProgramNode(0...13)( StatementsNode(0...13)( [RangeNode(0...3)(IntegerNode(0...1)(), nil, (1...3), 0), RangeNode(6...9)( - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "a"), + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "a"), nil, (7...9), 0 ), - CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 0, "c")] + CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_dot3.txt b/test/yarp/snapshots/seattlerb/parse_line_dot3.txt index d50e6dc275a4ee..109bbadc623cf4 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_dot3.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_dot3.txt @@ -3,11 +3,11 @@ ProgramNode(0...15)( StatementsNode(0...15)( [RangeNode(0...6)(IntegerNode(0...1)(), IntegerNode(5...6)(), (1...4), 1), RangeNode(7...13)( - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "a"), - CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 0, "b"), + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "a"), + CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 2, "b"), (8...11), 1 ), - CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 0, "c")] + CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_dot3_open.txt b/test/yarp/snapshots/seattlerb/parse_line_dot3_open.txt index 16cdc0cce8f3b9..558c430b6a69fa 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_dot3_open.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_dot3_open.txt @@ -3,11 +3,11 @@ ProgramNode(0...15)( StatementsNode(0...15)( [RangeNode(0...4)(IntegerNode(0...1)(), nil, (1...4), 1), RangeNode(7...11)( - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "a"), + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "a"), nil, (8...11), 1 ), - CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 0, "c")] + CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "c")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_evstr_after_break.txt b/test/yarp/snapshots/seattlerb/parse_line_evstr_after_break.txt index 3807c61b206d5d..ac4be36fcca71b 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_evstr_after_break.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_evstr_after_break.txt @@ -8,7 +8,7 @@ ProgramNode(0...11)( [EmbeddedStatementsNode(6...10)( (6...8), StatementsNode(8...9)( - [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "b")] + [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "b")] ), (9...10) )], diff --git a/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt b/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt index e24231dcf9aa95..23122ab3673505 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt @@ -7,7 +7,7 @@ ProgramNode(0...14)( EmbeddedStatementsNode(7...11)( (7...9), StatementsNode(9...10)( - [CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "b")] + [CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "b")] ), (10...11) ), diff --git a/test/yarp/snapshots/seattlerb/parse_line_iter_call_no_parens.txt b/test/yarp/snapshots/seattlerb/parse_line_iter_call_no_parens.txt index 53c7b386602211..82dd3ce64f627e 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_iter_call_no_parens.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_iter_call_no_parens.txt @@ -7,7 +7,7 @@ ProgramNode(0...25)( (0...1), nil, ArgumentsNode(2...3)( - [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "a")] + [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "a")] ), nil, BlockNode(4...25)( diff --git a/test/yarp/snapshots/seattlerb/parse_line_iter_call_parens.txt b/test/yarp/snapshots/seattlerb/parse_line_iter_call_parens.txt index 229243ea666e36..db09ae12d0bf4c 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_iter_call_parens.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_iter_call_parens.txt @@ -7,7 +7,7 @@ ProgramNode(0...26)( (0...1), (1...2), ArgumentsNode(2...3)( - [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "a")] + [CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "a")] ), (3...4), BlockNode(5...26)( diff --git a/test/yarp/snapshots/seattlerb/parse_line_op_asgn.txt b/test/yarp/snapshots/seattlerb/parse_line_op_asgn.txt index e65af5c08d01fd..011858c31e5bf9 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_op_asgn.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_op_asgn.txt @@ -4,10 +4,10 @@ ProgramNode(6...34)( [LocalVariableOperatorWriteNode(6...24)( (6...9), (10...12), - CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "bar"), + CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "bar"), :foo, :+ ), - CallNode(31...34)(nil, nil, (31...34), nil, nil, nil, nil, 0, "baz")] + CallNode(31...34)(nil, nil, (31...34), nil, nil, nil, nil, 2, "baz")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_postexe.txt b/test/yarp/snapshots/seattlerb/parse_line_postexe.txt index 775d20927286d9..9e527ea587c932 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_postexe.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_postexe.txt @@ -3,7 +3,7 @@ ProgramNode(0...11)( StatementsNode(0...11)( [PostExecutionNode(0...11)( StatementsNode(6...9)( - [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "foo")] + [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "foo")] ), (0...3), (4...5), diff --git a/test/yarp/snapshots/seattlerb/parse_line_preexe.txt b/test/yarp/snapshots/seattlerb/parse_line_preexe.txt index 59ede98b60f7cf..49f485c79fc3e1 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_preexe.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_preexe.txt @@ -3,7 +3,7 @@ ProgramNode(0...13)( StatementsNode(0...13)( [PreExecutionNode(0...13)( StatementsNode(8...11)( - [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 0, "foo")] + [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 2, "foo")] ), (0...5), (6...7), diff --git a/test/yarp/snapshots/seattlerb/parse_line_rescue.txt b/test/yarp/snapshots/seattlerb/parse_line_rescue.txt index 1a1fc6b01d519e..02704b5790fb32 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_rescue.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_rescue.txt @@ -4,7 +4,7 @@ ProgramNode(0...35)( [BeginNode(0...35)( (0...5), StatementsNode(8...9)( - [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "a")] + [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "a")] ), RescueNode(10...31)( (10...16), @@ -12,7 +12,7 @@ ProgramNode(0...35)( nil, nil, StatementsNode(19...20)( - [CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 0, "b")] + [CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 2, "b")] ), RescueNode(21...31)( (21...27), @@ -28,7 +28,7 @@ ProgramNode(0...35)( nil, nil, nil, - 0, + 2, "c" )] ), diff --git a/test/yarp/snapshots/seattlerb/parse_line_to_ary.txt b/test/yarp/snapshots/seattlerb/parse_line_to_ary.txt index da2c3f5b2386ee..ed1ab308658bce 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_to_ary.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_to_ary.txt @@ -5,10 +5,10 @@ ProgramNode(0...10)( [LocalVariableWriteNode(0...1)(:a, 0, nil, (0...1), nil), LocalVariableWriteNode(3...4)(:b, 0, nil, (3...4), nil)], (5...6), - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "c"), + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "c"), nil, nil ), - CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "d")] + CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "d")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_line_trailing_newlines.txt b/test/yarp/snapshots/seattlerb/parse_line_trailing_newlines.txt index c28a53ddc85e61..e48c600649bbf7 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_trailing_newlines.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_trailing_newlines.txt @@ -1,7 +1,7 @@ ProgramNode(0...3)( [], StatementsNode(0...3)( - [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "b")] + [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "b")] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_pattern_019.txt b/test/yarp/snapshots/seattlerb/parse_pattern_019.txt index 0b317424986920..d6f5d2977abd8a 100644 --- a/test/yarp/snapshots/seattlerb/parse_pattern_019.txt +++ b/test/yarp/snapshots/seattlerb/parse_pattern_019.txt @@ -5,17 +5,7 @@ ProgramNode(0...26)( IntegerNode(5...6)(), [InNode(7...22)( RangeNode(10...15)( - CallNode(10...12)( - IntegerNode(11...12)(), - nil, - (10...11), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + IntegerNode(10...12)(), IntegerNode(14...15)(), (12...14), 0 diff --git a/test/yarp/snapshots/seattlerb/parse_pattern_044.txt b/test/yarp/snapshots/seattlerb/parse_pattern_044.txt index 572197b776dbb0..2788137784b48c 100644 --- a/test/yarp/snapshots/seattlerb/parse_pattern_044.txt +++ b/test/yarp/snapshots/seattlerb/parse_pattern_044.txt @@ -2,7 +2,7 @@ ProgramNode(0...31)( [], StatementsNode(0...31)( [CaseNode(0...31)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "obj"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "obj"), [InNode(9...27)( ArrayPatternNode(12...20)( ConstantReadNode(12...18)(), diff --git a/test/yarp/snapshots/seattlerb/parse_until_not_canonical.txt b/test/yarp/snapshots/seattlerb/parse_until_not_canonical.txt index 6ac4c6f0420021..acac8dd857298b 100644 --- a/test/yarp/snapshots/seattlerb/parse_until_not_canonical.txt +++ b/test/yarp/snapshots/seattlerb/parse_until_not_canonical.txt @@ -13,7 +13,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "var" ), (13...14), @@ -36,7 +36,8 @@ ProgramNode(0...30)( ), StatementsNode(21...26)( [StringNode(21...26)((21...22), (22...25), (25...26), "foo")] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_until_not_noncanonical.txt b/test/yarp/snapshots/seattlerb/parse_until_not_noncanonical.txt index 6ac4c6f0420021..acac8dd857298b 100644 --- a/test/yarp/snapshots/seattlerb/parse_until_not_noncanonical.txt +++ b/test/yarp/snapshots/seattlerb/parse_until_not_noncanonical.txt @@ -13,7 +13,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "var" ), (13...14), @@ -36,7 +36,8 @@ ProgramNode(0...30)( ), StatementsNode(21...26)( [StringNode(21...26)((21...22), (22...25), (25...26), "foo")] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_while_not_canonical.txt b/test/yarp/snapshots/seattlerb/parse_while_not_canonical.txt index 754694cefe175b..b113e0ad537a68 100644 --- a/test/yarp/snapshots/seattlerb/parse_while_not_canonical.txt +++ b/test/yarp/snapshots/seattlerb/parse_while_not_canonical.txt @@ -13,7 +13,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "var" ), (13...14), @@ -36,7 +36,8 @@ ProgramNode(0...30)( ), StatementsNode(21...26)( [StringNode(21...26)((21...22), (22...25), (25...26), "foo")] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/seattlerb/parse_while_not_noncanonical.txt b/test/yarp/snapshots/seattlerb/parse_while_not_noncanonical.txt index 754694cefe175b..b113e0ad537a68 100644 --- a/test/yarp/snapshots/seattlerb/parse_while_not_noncanonical.txt +++ b/test/yarp/snapshots/seattlerb/parse_while_not_noncanonical.txt @@ -13,7 +13,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "var" ), (13...14), @@ -36,7 +36,8 @@ ProgramNode(0...30)( ), StatementsNode(21...26)( [StringNode(21...26)((21...22), (22...25), (25...26), "foo")] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/seattlerb/pipe_semicolon.txt b/test/yarp/snapshots/seattlerb/pipe_semicolon.txt index 912eef617608da..cd40d9ac0b18b4 100644 --- a/test/yarp/snapshots/seattlerb/pipe_semicolon.txt +++ b/test/yarp/snapshots/seattlerb/pipe_semicolon.txt @@ -2,7 +2,7 @@ ProgramNode(0...18)( [], StatementsNode(0...18)( [CallNode(0...18)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, diff --git a/test/yarp/snapshots/seattlerb/pipe_space.txt b/test/yarp/snapshots/seattlerb/pipe_space.txt index dc569222e16195..8c66905d04c8a8 100644 --- a/test/yarp/snapshots/seattlerb/pipe_space.txt +++ b/test/yarp/snapshots/seattlerb/pipe_space.txt @@ -2,7 +2,7 @@ ProgramNode(0...14)( [], StatementsNode(0...14)( [CallNode(0...14)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, diff --git a/test/yarp/snapshots/seattlerb/rescue_do_end_raised.txt b/test/yarp/snapshots/seattlerb/rescue_do_end_raised.txt index 7209e7eb47f828..f4e4cda3ee3261 100644 --- a/test/yarp/snapshots/seattlerb/rescue_do_end_raised.txt +++ b/test/yarp/snapshots/seattlerb/rescue_do_end_raised.txt @@ -22,7 +22,7 @@ ProgramNode(0...35)( nil, nil, nil, - 0, + 2, "raise" )] ), diff --git a/test/yarp/snapshots/seattlerb/rescue_do_end_rescued.txt b/test/yarp/snapshots/seattlerb/rescue_do_end_rescued.txt index 07d7a0aa6acd7d..5376935a827006 100644 --- a/test/yarp/snapshots/seattlerb/rescue_do_end_rescued.txt +++ b/test/yarp/snapshots/seattlerb/rescue_do_end_rescued.txt @@ -22,7 +22,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "raise" )] ), diff --git a/test/yarp/snapshots/seattlerb/rescue_in_block.txt b/test/yarp/snapshots/seattlerb/rescue_in_block.txt index 0a9d0408149ce0..2f096cdf741b7b 100644 --- a/test/yarp/snapshots/seattlerb/rescue_in_block.txt +++ b/test/yarp/snapshots/seattlerb/rescue_in_block.txt @@ -28,7 +28,7 @@ ProgramNode(0...26)( nil, nil, nil, - 0, + 2, "stuff" )] ), diff --git a/test/yarp/snapshots/seattlerb/rescue_parens.txt b/test/yarp/snapshots/seattlerb/rescue_parens.txt index f7f6a7783e8802..c672e59e6f65d9 100644 --- a/test/yarp/snapshots/seattlerb/rescue_parens.txt +++ b/test/yarp/snapshots/seattlerb/rescue_parens.txt @@ -18,7 +18,7 @@ ProgramNode(0...14)( nil, nil, nil, - 0, + 2, "b" ), (5...11), @@ -30,7 +30,7 @@ ProgramNode(0...14)( nil, nil, nil, - 0, + 2, "c" ) )] diff --git a/test/yarp/snapshots/seattlerb/return_call_assocs.txt b/test/yarp/snapshots/seattlerb/return_call_assocs.txt index 72edbbbfa408c9..9698080b5e9918 100644 --- a/test/yarp/snapshots/seattlerb/return_call_assocs.txt +++ b/test/yarp/snapshots/seattlerb/return_call_assocs.txt @@ -123,7 +123,7 @@ ProgramNode(0...106)( nil, nil, nil, - 0, + 2, "z" ), IntegerNode(104...105)(), diff --git a/test/yarp/snapshots/seattlerb/safe_attrasgn.txt b/test/yarp/snapshots/seattlerb/safe_attrasgn.txt index fabbcb5ca70849..a48f189f41a122 100644 --- a/test/yarp/snapshots/seattlerb/safe_attrasgn.txt +++ b/test/yarp/snapshots/seattlerb/safe_attrasgn.txt @@ -2,7 +2,7 @@ ProgramNode(0...8)( [], StatementsNode(0...8)( [CallNode(0...8)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_attrasgn_constant.txt b/test/yarp/snapshots/seattlerb/safe_attrasgn_constant.txt index b82150403442a2..8f51d308631869 100644 --- a/test/yarp/snapshots/seattlerb/safe_attrasgn_constant.txt +++ b/test/yarp/snapshots/seattlerb/safe_attrasgn_constant.txt @@ -2,7 +2,7 @@ ProgramNode(0...8)( [], StatementsNode(0...8)( [CallNode(0...8)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_call.txt b/test/yarp/snapshots/seattlerb/safe_call.txt index 1621715838b418..d170db0f559f59 100644 --- a/test/yarp/snapshots/seattlerb/safe_call.txt +++ b/test/yarp/snapshots/seattlerb/safe_call.txt @@ -2,7 +2,7 @@ ProgramNode(0...4)( [], StatementsNode(0...4)( [CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_call_after_newline.txt b/test/yarp/snapshots/seattlerb/safe_call_after_newline.txt index d57c4b14f7e479..0f48cd9867ac30 100644 --- a/test/yarp/snapshots/seattlerb/safe_call_after_newline.txt +++ b/test/yarp/snapshots/seattlerb/safe_call_after_newline.txt @@ -2,7 +2,7 @@ ProgramNode(0...5)( [], StatementsNode(0...5)( [CallNode(0...5)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (2...4), (4...5), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_call_dot_parens.txt b/test/yarp/snapshots/seattlerb/safe_call_dot_parens.txt index 3eee73711e704d..63a6f3822afae9 100644 --- a/test/yarp/snapshots/seattlerb/safe_call_dot_parens.txt +++ b/test/yarp/snapshots/seattlerb/safe_call_dot_parens.txt @@ -2,7 +2,7 @@ ProgramNode(0...5)( [], StatementsNode(0...5)( [CallNode(0...5)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (0...0), (3...4), diff --git a/test/yarp/snapshots/seattlerb/safe_call_newline.txt b/test/yarp/snapshots/seattlerb/safe_call_newline.txt index 1621715838b418..d170db0f559f59 100644 --- a/test/yarp/snapshots/seattlerb/safe_call_newline.txt +++ b/test/yarp/snapshots/seattlerb/safe_call_newline.txt @@ -2,7 +2,7 @@ ProgramNode(0...4)( [], StatementsNode(0...4)( [CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_call_operator.txt b/test/yarp/snapshots/seattlerb/safe_call_operator.txt index 797d9795c1728c..58df15db4ae8e1 100644 --- a/test/yarp/snapshots/seattlerb/safe_call_operator.txt +++ b/test/yarp/snapshots/seattlerb/safe_call_operator.txt @@ -2,7 +2,7 @@ ProgramNode(0...6)( [], StatementsNode(0...6)( [CallNode(0...6)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_call_rhs_newline.txt b/test/yarp/snapshots/seattlerb/safe_call_rhs_newline.txt index 373fd185377392..4000ecf59b70a1 100644 --- a/test/yarp/snapshots/seattlerb/safe_call_rhs_newline.txt +++ b/test/yarp/snapshots/seattlerb/safe_call_rhs_newline.txt @@ -5,7 +5,7 @@ ProgramNode(0...8)( :c, 0, CallNode(4...8)( - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "a"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "a"), (5...7), (7...8), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_calls.txt b/test/yarp/snapshots/seattlerb/safe_calls.txt index ef0fe5c7a849c9..400667a3544a28 100644 --- a/test/yarp/snapshots/seattlerb/safe_calls.txt +++ b/test/yarp/snapshots/seattlerb/safe_calls.txt @@ -3,7 +3,7 @@ ProgramNode(0...10)( StatementsNode(0...10)( [CallNode(0...10)( CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_op_asgn.txt b/test/yarp/snapshots/seattlerb/safe_op_asgn.txt index a90eecb8fdfb4d..50e03a150c4f5c 100644 --- a/test/yarp/snapshots/seattlerb/safe_op_asgn.txt +++ b/test/yarp/snapshots/seattlerb/safe_op_asgn.txt @@ -3,7 +3,7 @@ ProgramNode(0...11)( StatementsNode(0...11)( [CallOperatorWriteNode(0...11)( CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/seattlerb/safe_op_asgn2.txt b/test/yarp/snapshots/seattlerb/safe_op_asgn2.txt index bf00e7947bf5e8..2b02d02caa81b8 100644 --- a/test/yarp/snapshots/seattlerb/safe_op_asgn2.txt +++ b/test/yarp/snapshots/seattlerb/safe_op_asgn2.txt @@ -3,7 +3,7 @@ ProgramNode(0...10)( StatementsNode(0...10)( [CallOperatorOrWriteNode(0...10)( CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, @@ -13,7 +13,7 @@ ProgramNode(0...10)( 1, "b=" ), - CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "x"), + CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "x"), (5...8) )] ) diff --git a/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt b/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt index fed889aa903a04..52bd599ce9b734 100644 --- a/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt +++ b/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt @@ -20,12 +20,12 @@ ProgramNode(0...40)( "puts" ), CallNode(35...40)( - CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 0, "a"), + CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 2, "a"), nil, (37...38), nil, ArgumentsNode(39...40)( - [CallNode(39...40)(nil, nil, (39...40), nil, nil, nil, nil, 0, "b")] + [CallNode(39...40)(nil, nil, (39...40), nil, nil, nil, nil, 2, "b")] ), nil, nil, diff --git a/test/yarp/snapshots/seattlerb/stabby_block_iter_call.txt b/test/yarp/snapshots/seattlerb/stabby_block_iter_call.txt index 9d56711a762222..f84e8227f954e0 100644 --- a/test/yarp/snapshots/seattlerb/stabby_block_iter_call.txt +++ b/test/yarp/snapshots/seattlerb/stabby_block_iter_call.txt @@ -21,7 +21,7 @@ ProgramNode(0...25)( nil, nil, nil, - 0, + 2, "a" ), (12...13), diff --git a/test/yarp/snapshots/seattlerb/str_double_double_escaped_newline.txt b/test/yarp/snapshots/seattlerb/str_double_double_escaped_newline.txt index fa91f00d29075a..2be5ea34e95522 100644 --- a/test/yarp/snapshots/seattlerb/str_double_double_escaped_newline.txt +++ b/test/yarp/snapshots/seattlerb/str_double_double_escaped_newline.txt @@ -14,6 +14,6 @@ ProgramNode(0...9)( 0, "a" ), - CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "b")] + CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "b")] ) ) diff --git a/test/yarp/snapshots/seattlerb/str_double_escaped_newline.txt b/test/yarp/snapshots/seattlerb/str_double_escaped_newline.txt index 2ff6d74fbb37a2..7b724c6b80e167 100644 --- a/test/yarp/snapshots/seattlerb/str_double_escaped_newline.txt +++ b/test/yarp/snapshots/seattlerb/str_double_escaped_newline.txt @@ -14,6 +14,6 @@ ProgramNode(0...8)( 0, "a" ), - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "b")] + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "b")] ) ) diff --git a/test/yarp/snapshots/seattlerb/str_double_newline.txt b/test/yarp/snapshots/seattlerb/str_double_newline.txt index a8e003e997d909..6b7a3afb32542c 100644 --- a/test/yarp/snapshots/seattlerb/str_double_newline.txt +++ b/test/yarp/snapshots/seattlerb/str_double_newline.txt @@ -14,6 +14,6 @@ ProgramNode(0...7)( 0, "a" ), - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b")] + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b")] ) ) diff --git a/test/yarp/snapshots/seattlerb/str_evstr.txt b/test/yarp/snapshots/seattlerb/str_evstr.txt index 54cd37035fd09f..18d41a9b6aa79f 100644 --- a/test/yarp/snapshots/seattlerb/str_evstr.txt +++ b/test/yarp/snapshots/seattlerb/str_evstr.txt @@ -7,7 +7,7 @@ ProgramNode(0...8)( EmbeddedStatementsNode(3...7)( (3...5), StatementsNode(5...6)( - [CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 0, "b")] + [CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 2, "b")] ), (6...7) )], diff --git a/test/yarp/snapshots/seattlerb/str_evstr_escape.txt b/test/yarp/snapshots/seattlerb/str_evstr_escape.txt index 41b2b9e294c5b6..e95335e227861d 100644 --- a/test/yarp/snapshots/seattlerb/str_evstr_escape.txt +++ b/test/yarp/snapshots/seattlerb/str_evstr_escape.txt @@ -7,7 +7,7 @@ ProgramNode(0...16)( EmbeddedStatementsNode(3...7)( (3...5), StatementsNode(5...6)( - [CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 0, "b")] + [CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 2, "b")] ), (6...7) ), diff --git a/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt b/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt index 3564378399f5dc..8c0ee1e1b7d263 100644 --- a/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt +++ b/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt @@ -6,7 +6,7 @@ ProgramNode(0...17)( [EmbeddedStatementsNode(5...9)( (5...7), StatementsNode(7...8)( - [CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "x")] + [CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "x")] ), (8...9) ), diff --git a/test/yarp/snapshots/seattlerb/str_interp_ternary_or_label.txt b/test/yarp/snapshots/seattlerb/str_interp_ternary_or_label.txt index d712ca00a475a8..d2ec64657fbd61 100644 --- a/test/yarp/snapshots/seattlerb/str_interp_ternary_or_label.txt +++ b/test/yarp/snapshots/seattlerb/str_interp_ternary_or_label.txt @@ -17,7 +17,7 @@ ProgramNode(0...23)( nil, nil, nil, - 0, + 2, "a" ), (4...5), @@ -45,7 +45,7 @@ ProgramNode(0...23)( nil, nil, nil, - 0, + 2, "a" )] ), diff --git a/test/yarp/snapshots/seattlerb/str_pct_Q_nested.txt b/test/yarp/snapshots/seattlerb/str_pct_Q_nested.txt index 57b00effb73b8f..613e85a088a0d9 100644 --- a/test/yarp/snapshots/seattlerb/str_pct_Q_nested.txt +++ b/test/yarp/snapshots/seattlerb/str_pct_Q_nested.txt @@ -15,7 +15,7 @@ ProgramNode(0...26)( nil, nil, nil, - 0, + 2, "nest" )] ), diff --git a/test/yarp/snapshots/seattlerb/str_single_double_escaped_newline.txt b/test/yarp/snapshots/seattlerb/str_single_double_escaped_newline.txt index fa91f00d29075a..2be5ea34e95522 100644 --- a/test/yarp/snapshots/seattlerb/str_single_double_escaped_newline.txt +++ b/test/yarp/snapshots/seattlerb/str_single_double_escaped_newline.txt @@ -14,6 +14,6 @@ ProgramNode(0...9)( 0, "a" ), - CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "b")] + CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "b")] ) ) diff --git a/test/yarp/snapshots/seattlerb/str_single_escaped_newline.txt b/test/yarp/snapshots/seattlerb/str_single_escaped_newline.txt index 1d2b327f6bca44..d97f1ce0169ef4 100644 --- a/test/yarp/snapshots/seattlerb/str_single_escaped_newline.txt +++ b/test/yarp/snapshots/seattlerb/str_single_escaped_newline.txt @@ -14,6 +14,6 @@ ProgramNode(0...8)( 0, "a" ), - CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 0, "b")] + CallNode(7...8)(nil, nil, (7...8), nil, nil, nil, nil, 2, "b")] ) ) diff --git a/test/yarp/snapshots/seattlerb/str_single_newline.txt b/test/yarp/snapshots/seattlerb/str_single_newline.txt index a8e003e997d909..6b7a3afb32542c 100644 --- a/test/yarp/snapshots/seattlerb/str_single_newline.txt +++ b/test/yarp/snapshots/seattlerb/str_single_newline.txt @@ -14,6 +14,6 @@ ProgramNode(0...7)( 0, "a" ), - CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b")] + CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b")] ) ) diff --git a/test/yarp/snapshots/seattlerb/symbol_list.txt b/test/yarp/snapshots/seattlerb/symbol_list.txt index cfd59c4e0e7fd2..386ac609dffd7f 100644 --- a/test/yarp/snapshots/seattlerb/symbol_list.txt +++ b/test/yarp/snapshots/seattlerb/symbol_list.txt @@ -7,7 +7,7 @@ ProgramNode(0...13)( [EmbeddedStatementsNode(3...7)( (3...5), StatementsNode(5...6)( - [CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 0, "a")] + [CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 2, "a")] ), (6...7) )], @@ -26,7 +26,7 @@ ProgramNode(0...13)( nil, nil, nil, - 0, + 2, "b" )] ), diff --git a/test/yarp/snapshots/seattlerb/thingy.txt b/test/yarp/snapshots/seattlerb/thingy.txt index 1a1c467f474410..f12a16ed4fc808 100644 --- a/test/yarp/snapshots/seattlerb/thingy.txt +++ b/test/yarp/snapshots/seattlerb/thingy.txt @@ -2,7 +2,7 @@ ProgramNode(0...15)( [], StatementsNode(0...15)( [CallNode(0...6)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "f"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "f"), (1...2), (0...0), (2...3), @@ -13,7 +13,7 @@ ProgramNode(0...15)( "call" ), CallNode(8...15)( - CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "f"), + CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "f"), (9...11), (0...0), (11...12), diff --git a/test/yarp/snapshots/seattlerb/uminus_float.txt b/test/yarp/snapshots/seattlerb/uminus_float.txt index ba5db74284bc57..fe6bbc4150ff47 100644 --- a/test/yarp/snapshots/seattlerb/uminus_float.txt +++ b/test/yarp/snapshots/seattlerb/uminus_float.txt @@ -1,16 +1 @@ -ProgramNode(0...4)( - [], - StatementsNode(0...4)( - [CallNode(0...4)( - FloatNode(1...4)(), - nil, - (0...1), - nil, - nil, - nil, - nil, - 0, - "-@" - )] - ) -) +ProgramNode(0...4)([], StatementsNode(0...4)([FloatNode(0...4)()])) diff --git a/test/yarp/snapshots/seattlerb/unary_minus.txt b/test/yarp/snapshots/seattlerb/unary_minus.txt index abe6695149d624..8f5ed5003ca9d1 100644 --- a/test/yarp/snapshots/seattlerb/unary_minus.txt +++ b/test/yarp/snapshots/seattlerb/unary_minus.txt @@ -2,7 +2,7 @@ ProgramNode(0...2)( [], StatementsNode(0...2)( [CallNode(0...2)( - CallNode(1...2)(nil, nil, (1...2), nil, nil, nil, nil, 0, "a"), + CallNode(1...2)(nil, nil, (1...2), nil, nil, nil, nil, 2, "a"), nil, (0...1), nil, diff --git a/test/yarp/snapshots/seattlerb/unary_plus.txt b/test/yarp/snapshots/seattlerb/unary_plus.txt index 635c033e94476e..6d74a2b362c4ae 100644 --- a/test/yarp/snapshots/seattlerb/unary_plus.txt +++ b/test/yarp/snapshots/seattlerb/unary_plus.txt @@ -2,7 +2,7 @@ ProgramNode(0...2)( [], StatementsNode(0...2)( [CallNode(0...2)( - CallNode(1...2)(nil, nil, (1...2), nil, nil, nil, nil, 0, "a"), + CallNode(1...2)(nil, nil, (1...2), nil, nil, nil, nil, 2, "a"), nil, (0...1), nil, diff --git a/test/yarp/snapshots/seattlerb/unary_tilde.txt b/test/yarp/snapshots/seattlerb/unary_tilde.txt index e73fdd577f4c25..8ec6e9145f434c 100644 --- a/test/yarp/snapshots/seattlerb/unary_tilde.txt +++ b/test/yarp/snapshots/seattlerb/unary_tilde.txt @@ -2,7 +2,7 @@ ProgramNode(0...2)( [], StatementsNode(0...2)( [CallNode(0...2)( - CallNode(1...2)(nil, nil, (1...2), nil, nil, nil, nil, 0, "a"), + CallNode(1...2)(nil, nil, (1...2), nil, nil, nil, nil, 2, "a"), nil, (0...1), nil, diff --git a/test/yarp/snapshots/seattlerb/when_splat.txt b/test/yarp/snapshots/seattlerb/when_splat.txt index a4caedf3016fa2..75e44cd75df0bf 100644 --- a/test/yarp/snapshots/seattlerb/when_splat.txt +++ b/test/yarp/snapshots/seattlerb/when_splat.txt @@ -2,12 +2,12 @@ ProgramNode(0...25)( [], StatementsNode(0...25)( [CaseNode(0...25)( - CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 0, "a"), + CallNode(5...6)(nil, nil, (5...6), nil, nil, nil, nil, 2, "a"), [WhenNode(8...15)( (8...12), [SplatNode(13...15)( (13...14), - CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 0, "b") + CallNode(14...15)(nil, nil, (14...15), nil, nil, nil, nil, 2, "b") )], nil )], diff --git a/test/yarp/snapshots/seattlerb/wtf_7.txt b/test/yarp/snapshots/seattlerb/wtf_7.txt index e74a5311787bf4..60b902f4d232ea 100644 --- a/test/yarp/snapshots/seattlerb/wtf_7.txt +++ b/test/yarp/snapshots/seattlerb/wtf_7.txt @@ -2,7 +2,7 @@ ProgramNode(0...11)( [], StatementsNode(0...11)( [CallNode(0...11)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...2), (2...3), nil, @@ -18,7 +18,7 @@ ProgramNode(0...11)( [], nil, StatementsNode(9...10)( - [CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "c")] + [CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "c")] ), (8...9), (10...11) diff --git a/test/yarp/snapshots/seattlerb/wtf_8.txt b/test/yarp/snapshots/seattlerb/wtf_8.txt index 211cd9f048dbaa..ed7a53a89a85b2 100644 --- a/test/yarp/snapshots/seattlerb/wtf_8.txt +++ b/test/yarp/snapshots/seattlerb/wtf_8.txt @@ -2,9 +2,9 @@ ProgramNode(0...12)( [], StatementsNode(0...12)( [CallNode(0...12)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), - (11...12), + (3...4), nil, ArgumentsNode(5...8)( [ParenthesesNode(5...8)( @@ -18,13 +18,13 @@ ProgramNode(0...12)( [], nil, StatementsNode(10...11)( - [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 0, "c")] + [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 2, "c")] ), (9...10), (11...12) ), 0, - "}" + "b" )] ) ) diff --git a/test/yarp/snapshots/seattlerb/yield_call_assocs.txt b/test/yarp/snapshots/seattlerb/yield_call_assocs.txt index e6a56df147c556..820afa6c08d37f 100644 --- a/test/yarp/snapshots/seattlerb/yield_call_assocs.txt +++ b/test/yarp/snapshots/seattlerb/yield_call_assocs.txt @@ -134,7 +134,7 @@ ProgramNode(0...100)( nil, nil, nil, - 0, + 2, "z" ), IntegerNode(98...99)(), diff --git a/test/yarp/snapshots/seattlerb/zomg_sometimes_i_hate_this_project.txt b/test/yarp/snapshots/seattlerb/zomg_sometimes_i_hate_this_project.txt index ffc7e315da87b9..44a67b33775e27 100644 --- a/test/yarp/snapshots/seattlerb/zomg_sometimes_i_hate_this_project.txt +++ b/test/yarp/snapshots/seattlerb/zomg_sometimes_i_hate_this_project.txt @@ -26,7 +26,7 @@ ProgramNode(6...66)( nil, nil, nil, - 0, + 2, "b" ), StatementsNode(32...35)( @@ -53,7 +53,7 @@ ProgramNode(6...66)( nil, nil, nil, - 0, + 2, "d" )] ), diff --git a/test/yarp/snapshots/strings.txt b/test/yarp/snapshots/strings.txt index 5f3e5d29331c78..ab74cd0bd957f2 100644 --- a/test/yarp/snapshots/strings.txt +++ b/test/yarp/snapshots/strings.txt @@ -39,7 +39,7 @@ ProgramNode(0...498)( nil, nil, nil, - 0, + 2, "bbb" )] ), @@ -82,7 +82,7 @@ ProgramNode(0...498)( nil, nil, nil, - 0, + 2, "bbb" )] ), @@ -134,7 +134,7 @@ ProgramNode(0...498)( nil, nil, nil, - 0, + 2, "c" )] ), diff --git a/test/yarp/snapshots/symbols.txt b/test/yarp/snapshots/symbols.txt index 6e8e1c0bb7517a..f53a208bcec752 100644 --- a/test/yarp/snapshots/symbols.txt +++ b/test/yarp/snapshots/symbols.txt @@ -15,7 +15,7 @@ ProgramNode(0...345)( nil, nil, nil, - 0, + 2, "var" )] ), diff --git a/test/yarp/snapshots/ternary_operator.txt b/test/yarp/snapshots/ternary_operator.txt index 11d64957837160..6055e2434ffb92 100644 --- a/test/yarp/snapshots/ternary_operator.txt +++ b/test/yarp/snapshots/ternary_operator.txt @@ -1,16 +1,16 @@ -ProgramNode(0...117)( - [], - StatementsNode(0...117)( +ProgramNode(0...131)( + [:_a], + StatementsNode(0...131)( [IfNode(0...9)( nil, - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), StatementsNode(4...5)( - [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "b")] + [CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "b")] ), ElseNode(6...9)( (6...7), StatementsNode(8...9)( - [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 0, "c")] + [CallNode(8...9)(nil, nil, (8...9), nil, nil, nil, nil, 2, "c")] ), nil ), @@ -18,11 +18,11 @@ ProgramNode(0...117)( ), IfNode(11...38)( nil, - CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 0, "a"), + CallNode(11...12)(nil, nil, (11...12), nil, nil, nil, nil, 2, "a"), StatementsNode(15...25)( [DefinedNode(15...25)( nil, - CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 0, "b"), + CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 2, "b"), nil, (15...23) )] @@ -40,7 +40,7 @@ ProgramNode(0...117)( nil, nil, nil, - 0, + 2, "c" ), nil, @@ -97,7 +97,7 @@ ProgramNode(0...117)( ), IfNode(103...117)( nil, - CallNode(103...104)(nil, nil, (103...104), nil, nil, nil, nil, 0, "a"), + CallNode(103...104)(nil, nil, (103...104), nil, nil, nil, nil, 2, "a"), StatementsNode(106...110)( [CallNode(106...110)( nil, @@ -107,7 +107,7 @@ ProgramNode(0...117)( nil, nil, nil, - 0, + 2, "var1" )] ), @@ -122,13 +122,42 @@ ProgramNode(0...117)( nil, nil, nil, - 0, + 2, "var2" )] ), nil ), nil + ), + IfNode(119...131)( + nil, + CallNode(119...123)( + nil, + nil, + (119...123), + nil, + nil, + nil, + nil, + 0, + "nil?" + ), + StatementsNode(124...129)( + [LocalVariableWriteNode(124...129)( + :_a, + 0, + IntegerNode(128...129)(), + (124...126), + (127...128) + )] + ), + ElseNode(129...131)( + (129...130), + StatementsNode(130...131)([IntegerNode(130...131)()]), + nil + ), + nil )] ) ) diff --git a/test/yarp/snapshots/unparser/corpus/literal/assignment.txt b/test/yarp/snapshots/unparser/corpus/literal/assignment.txt index 2083fb361b4e3e..4a1b5eeaf769ca 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/assignment.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/assignment.txt @@ -419,7 +419,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "index" ) ), @@ -431,7 +431,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "value" )] ), @@ -460,7 +460,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "value" )] ), @@ -496,7 +496,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "value" )] ), @@ -519,7 +519,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "index" ), CallNode(501...506)( @@ -530,7 +530,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "value" )] ), @@ -574,7 +574,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -605,7 +605,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "bar" ), (543...546) @@ -698,7 +698,7 @@ ProgramNode(0...719)( nil, nil, nil, - 0, + 2, "bar" ), (665...668) diff --git a/test/yarp/snapshots/unparser/corpus/literal/block.txt b/test/yarp/snapshots/unparser/corpus/literal/block.txt index 7d4bd2c4e6be64..787c8cb5929594 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/block.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/block.txt @@ -229,7 +229,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -248,7 +248,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (141...142), @@ -287,7 +287,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -306,7 +306,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (169...170), @@ -346,7 +346,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (189...190), @@ -386,7 +386,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (208...209), @@ -418,7 +418,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (229...230), @@ -451,7 +451,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -470,7 +470,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (249...250), @@ -507,7 +507,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -526,7 +526,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (271...272), @@ -567,7 +567,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -586,7 +586,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (295...296), @@ -628,7 +628,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -647,7 +647,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (322...323), @@ -685,7 +685,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -705,7 +705,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" ), (347...348), @@ -778,7 +778,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -823,7 +823,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -840,7 +840,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" ) )], @@ -855,7 +855,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -892,7 +892,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -909,7 +909,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" ) )], @@ -930,7 +930,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -967,7 +967,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -983,7 +983,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" ) )], @@ -998,7 +998,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -1035,7 +1035,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -1078,7 +1078,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -1094,7 +1094,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -1130,7 +1130,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -1146,7 +1146,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "bar" ) )], @@ -1167,7 +1167,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -1251,7 +1251,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "_1" ), nil, @@ -1266,7 +1266,7 @@ ProgramNode(0...737)( nil, nil, nil, - 0, + 2, "_2" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/case.txt b/test/yarp/snapshots/unparser/corpus/literal/case.txt index 3a3041c0b6cd92..8470bd39aaf631 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/case.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/case.txt @@ -13,7 +13,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" )], StatementsNode(16...19)( @@ -25,7 +25,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )] ) @@ -40,7 +40,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )], StatementsNode(31...34)( @@ -52,7 +52,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" )] ) @@ -62,7 +62,7 @@ ProgramNode(0...284)( (35...38) ), CaseNode(39...75)( - CallNode(44...47)(nil, nil, (44...47), nil, nil, nil, nil, 0, "foo"), + CallNode(44...47)(nil, nil, (44...47), nil, nil, nil, nil, 2, "foo"), [WhenNode(48...56)( (48...52), [CallNode(53...56)( @@ -73,7 +73,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" )], nil @@ -88,7 +88,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )], StatementsNode(68...71)( @@ -100,7 +100,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" )] ) @@ -110,7 +110,7 @@ ProgramNode(0...284)( (72...75) ), CaseNode(76...118)( - CallNode(81...84)(nil, nil, (81...84), nil, nil, nil, nil, 0, "foo"), + CallNode(81...84)(nil, nil, (81...84), nil, nil, nil, nil, 2, "foo"), [WhenNode(85...99)( (85...89), [CallNode(90...93)( @@ -121,7 +121,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" )], StatementsNode(96...99)( @@ -133,7 +133,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )] ) @@ -148,7 +148,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )], StatementsNode(111...114)( @@ -160,7 +160,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" )] ) @@ -178,7 +178,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "foo" ), [WhenNode(128...150)( @@ -191,7 +191,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" ), CallNode(138...141)( @@ -202,7 +202,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )], StatementsNode(144...150)( @@ -222,7 +222,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "foo" ), [WhenNode(164...182)( @@ -237,7 +237,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" ) )], @@ -258,7 +258,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "foo" ), [WhenNode(196...210)( @@ -271,7 +271,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" )], StatementsNode(207...210)( @@ -283,7 +283,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )] ) @@ -307,7 +307,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "foo" ), [WhenNode(236...251)( @@ -323,7 +323,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -338,7 +338,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -363,7 +363,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "foo" ), [WhenNode(265...280)( @@ -379,7 +379,7 @@ ProgramNode(0...284)( nil, nil, nil, - 0, + 2, "bar" ), (274...275), diff --git a/test/yarp/snapshots/unparser/corpus/literal/class.txt b/test/yarp/snapshots/unparser/corpus/literal/class.txt index eee58beb4c7094..96b50c7adf3634 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/class.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/class.txt @@ -14,7 +14,7 @@ ProgramNode(0...213)( [], (13...18), (19...21), - CallNode(22...23)(nil, nil, (22...23), nil, nil, nil, nil, 0, "a"), + CallNode(22...23)(nil, nil, (22...23), nil, nil, nil, nil, 2, "a"), nil, (24...27) ), @@ -22,9 +22,9 @@ ProgramNode(0...213)( [], (29...34), (35...37), - CallNode(38...39)(nil, nil, (38...39), nil, nil, nil, nil, 0, "a"), + CallNode(38...39)(nil, nil, (38...39), nil, nil, nil, nil, 2, "a"), StatementsNode(42...43)( - [CallNode(42...43)(nil, nil, (42...43), nil, nil, nil, nil, 0, "b")] + [CallNode(42...43)(nil, nil, (42...43), nil, nil, nil, nil, 2, "b")] ), (44...47) ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/def.txt b/test/yarp/snapshots/unparser/corpus/literal/def.txt index dab4a983c9670a..4a875be76193ce 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/def.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/def.txt @@ -8,7 +8,7 @@ ProgramNode(0...913)( BeginNode(10...46)( nil, StatementsNode(10...11)( - [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 0, "a")] + [CallNode(10...11)(nil, nil, (10...11), nil, nil, nil, nil, 2, "a")] ), RescueNode(12...22)( (12...18), @@ -24,7 +24,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -41,7 +41,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "c" )] ), @@ -58,7 +58,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -90,7 +90,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "a" ), (60...66), @@ -102,7 +102,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "b" ) )] @@ -121,7 +121,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -138,7 +138,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "c" )] ), @@ -155,7 +155,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -219,7 +219,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -246,7 +246,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -264,7 +264,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -282,7 +282,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -313,7 +313,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -330,7 +330,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -361,7 +361,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -379,7 +379,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -485,7 +485,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "baz" ), NilNode(373...376)()] @@ -603,7 +603,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "baz" ) )], @@ -674,7 +674,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -754,7 +754,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -792,7 +792,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -851,7 +851,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -897,7 +897,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "bar" ), CallNode(796...799)( @@ -908,7 +908,7 @@ ProgramNode(0...913)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/defs.txt b/test/yarp/snapshots/unparser/corpus/literal/defs.txt index 94a86678dc8287..b980c15c9e71d2 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/defs.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/defs.txt @@ -19,7 +19,7 @@ ProgramNode(0...266)( SelfNode(22...26)(), nil, StatementsNode(33...36)( - [CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 0, "bar")] + [CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 2, "bar")] ), [], (18...21), @@ -34,8 +34,8 @@ ProgramNode(0...266)( SelfNode(46...50)(), nil, StatementsNode(57...66)( - [CallNode(57...60)(nil, nil, (57...60), nil, nil, nil, nil, 0, "bar"), - CallNode(63...66)(nil, nil, (63...66), nil, nil, nil, nil, 0, "baz")] + [CallNode(57...60)(nil, nil, (57...60), nil, nil, nil, nil, 2, "bar"), + CallNode(63...66)(nil, nil, (63...66), nil, nil, nil, nil, 2, "baz")] ), [], (42...45), @@ -50,7 +50,7 @@ ProgramNode(0...266)( ConstantReadNode(76...79)(), nil, StatementsNode(86...89)( - [CallNode(86...89)(nil, nil, (86...89), nil, nil, nil, nil, 0, "bar")] + [CallNode(86...89)(nil, nil, (86...89), nil, nil, nil, nil, 2, "bar")] ), [], (72...75), @@ -106,7 +106,7 @@ ProgramNode(0...266)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -145,7 +145,7 @@ ProgramNode(0...266)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -188,7 +188,7 @@ ProgramNode(0...266)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -221,7 +221,7 @@ ProgramNode(0...266)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -246,7 +246,7 @@ ProgramNode(0...266)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -268,7 +268,7 @@ ProgramNode(0...266)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -281,7 +281,7 @@ ProgramNode(0...266)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/dstr.txt b/test/yarp/snapshots/unparser/corpus/literal/dstr.txt index 221a8939a701e8..b76f9da57d11e4 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/dstr.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/dstr.txt @@ -26,7 +26,7 @@ ProgramNode(0...299)( StringNode(47...51)(nil, (47...51), nil, "a\n" + "b\n")], (51...61) ), - CallNode(63...64)(nil, nil, (63...64), nil, nil, nil, nil, 0, "x")] + CallNode(63...64)(nil, nil, (63...64), nil, nil, nil, nil, 2, "x")] ), nil, (65...68) @@ -132,7 +132,7 @@ ProgramNode(0...299)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -167,7 +167,7 @@ ProgramNode(0...299)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt b/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt index ea875e159a0fce..b08835a4c37ad1 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/flipflop.txt @@ -5,7 +5,7 @@ ProgramNode(0...68)( (0...2), ParenthesesNode(3...23)( StatementsNode(4...22)( - [RangeNode(4...22)( + [FlipFlopNode(4...22)( ParenthesesNode(4...12)( StatementsNode(5...11)( [CallNode(5...11)( @@ -17,7 +17,7 @@ ProgramNode(0...68)( nil, nil, nil, - 0, + 2, "i" ), nil, @@ -44,7 +44,7 @@ ProgramNode(0...68)( nil, nil, nil, - 0, + 2, "i" ), nil, @@ -61,14 +61,14 @@ ProgramNode(0...68)( (21...22) ), (12...14), - 2 + 0 )] ), (3...4), (22...23) ), StatementsNode(26...29)( - [CallNode(26...29)(nil, nil, (26...29), nil, nil, nil, nil, 0, "foo")] + [CallNode(26...29)(nil, nil, (26...29), nil, nil, nil, nil, 2, "foo")] ), nil, (30...33) @@ -77,7 +77,7 @@ ProgramNode(0...68)( (34...36), ParenthesesNode(37...58)( StatementsNode(38...57)( - [RangeNode(38...57)( + [FlipFlopNode(38...57)( ParenthesesNode(38...46)( StatementsNode(39...45)( [CallNode(39...45)( @@ -89,7 +89,7 @@ ProgramNode(0...68)( nil, nil, nil, - 0, + 2, "i" ), nil, @@ -116,7 +116,7 @@ ProgramNode(0...68)( nil, nil, nil, - 0, + 2, "i" ), nil, @@ -133,14 +133,14 @@ ProgramNode(0...68)( (56...57) ), (46...49), - 3 + 1 )] ), (37...38), (57...58) ), StatementsNode(61...64)( - [CallNode(61...64)(nil, nil, (61...64), nil, nil, nil, nil, 0, "foo")] + [CallNode(61...64)(nil, nil, (61...64), nil, nil, nil, nil, 2, "foo")] ), nil, (65...68) diff --git a/test/yarp/snapshots/unparser/corpus/literal/for.txt b/test/yarp/snapshots/unparser/corpus/literal/for.txt index 4fdb3e3d73d06e..1bd6587bd7ad26 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/for.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/for.txt @@ -23,7 +23,7 @@ ProgramNode(0...119)( nil, nil, nil, - 0, + 2, "bar" ), StatementsNode(22...25)( @@ -35,7 +35,7 @@ ProgramNode(0...119)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -58,9 +58,9 @@ ProgramNode(0...119)( nil, nil ), - CallNode(40...43)(nil, nil, (40...43), nil, nil, nil, nil, 0, "bar"), + CallNode(40...43)(nil, nil, (40...43), nil, nil, nil, nil, 2, "bar"), StatementsNode(49...52)( - [CallNode(49...52)(nil, nil, (49...52), nil, nil, nil, nil, 0, "baz")] + [CallNode(49...52)(nil, nil, (49...52), nil, nil, nil, nil, 2, "baz")] ), (31...34), (37...39), @@ -79,9 +79,9 @@ ProgramNode(0...119)( (61...62), (67...68) ), - CallNode(72...75)(nil, nil, (72...75), nil, nil, nil, nil, 0, "bar"), + CallNode(72...75)(nil, nil, (72...75), nil, nil, nil, nil, 2, "bar"), StatementsNode(81...84)( - [CallNode(81...84)(nil, nil, (81...84), nil, nil, nil, nil, 0, "baz")] + [CallNode(81...84)(nil, nil, (81...84), nil, nil, nil, nil, 2, "baz")] ), (57...60), (69...71), @@ -105,7 +105,7 @@ ProgramNode(0...119)( nil, nil, nil, - 0, + 2, "bar" ), StatementsNode(112...115)( @@ -117,7 +117,7 @@ ProgramNode(0...119)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/hookexe.txt b/test/yarp/snapshots/unparser/corpus/literal/hookexe.txt index 9cd7da16bfa721..b97bd65ad1722e 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/hookexe.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/hookexe.txt @@ -3,16 +3,16 @@ ProgramNode(0...33)( StatementsNode(0...33)( [PreExecutionNode(0...15)( StatementsNode(10...13)( - [CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 0, "foo")] + [CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 2, "foo")] ), (0...5), (6...7), (14...15) ), - CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "bar"), + CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "bar"), PostExecutionNode(20...33)( StatementsNode(28...31)( - [CallNode(28...31)(nil, nil, (28...31), nil, nil, nil, nil, 0, "baz")] + [CallNode(28...31)(nil, nil, (28...31), nil, nil, nil, nil, 2, "baz")] ), (20...23), (24...25), diff --git a/test/yarp/snapshots/unparser/corpus/literal/if.txt b/test/yarp/snapshots/unparser/corpus/literal/if.txt index 32f5fed1ed1b13..8375e9acb36e52 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/if.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/if.txt @@ -5,7 +5,7 @@ ProgramNode(0...246)( (0...2), RegularExpressionNode(3...8)((3...4), (4...7), (7...8), "foo", 0), StatementsNode(11...14)( - [CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "bar")] + [CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "bar")] ), nil, (15...18) @@ -44,7 +44,7 @@ ProgramNode(0...246)( ), IfNode(90...100)( (90...92), - CallNode(93...96)(nil, nil, (93...96), nil, nil, nil, nil, 0, "foo"), + CallNode(93...96)(nil, nil, (93...96), nil, nil, nil, nil, 2, "foo"), nil, nil, (97...100) @@ -69,7 +69,7 @@ ProgramNode(0...246)( nil, nil, nil, - 0, + 2, "bar" ), (113...116), @@ -102,7 +102,7 @@ ProgramNode(0...246)( nil, nil, nil, - 0, + 2, "bar" ), (146...149), @@ -125,7 +125,7 @@ ProgramNode(0...246)( nil, nil, nil, - 0, + 2, "foo" ), StatementsNode(184...193)( @@ -140,7 +140,7 @@ ProgramNode(0...246)( nil, nil, nil, - 0, + 2, "bar" ), (184...187), diff --git a/test/yarp/snapshots/unparser/corpus/literal/kwbegin.txt b/test/yarp/snapshots/unparser/corpus/literal/kwbegin.txt index b7ed53b2764bc7..0553be37eab3f6 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/kwbegin.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/kwbegin.txt @@ -20,7 +20,7 @@ ProgramNode(0...530)( BeginNode(36...49)( (36...41), StatementsNode(44...45)( - [CallNode(44...45)(nil, nil, (44...45), nil, nil, nil, nil, 0, "a")] + [CallNode(44...45)(nil, nil, (44...45), nil, nil, nil, nil, 2, "a")] ), nil, nil, @@ -30,7 +30,7 @@ ProgramNode(0...530)( BeginNode(51...75)( (51...56), StatementsNode(59...60)( - [CallNode(59...60)(nil, nil, (59...60), nil, nil, nil, nil, 0, "a")] + [CallNode(59...60)(nil, nil, (59...60), nil, nil, nil, nil, 2, "a")] ), RescueNode(61...71)( (61...67), @@ -38,7 +38,7 @@ ProgramNode(0...530)( nil, nil, StatementsNode(70...71)( - [CallNode(70...71)(nil, nil, (70...71), nil, nil, nil, nil, 0, "b")] + [CallNode(70...71)(nil, nil, (70...71), nil, nil, nil, nil, 2, "b")] ), nil ), @@ -49,8 +49,8 @@ ProgramNode(0...530)( BeginNode(77...105)( (77...82), StatementsNode(85...90)( - [CallNode(85...86)(nil, nil, (85...86), nil, nil, nil, nil, 0, "a"), - CallNode(89...90)(nil, nil, (89...90), nil, nil, nil, nil, 0, "b")] + [CallNode(85...86)(nil, nil, (85...86), nil, nil, nil, nil, 2, "a"), + CallNode(89...90)(nil, nil, (89...90), nil, nil, nil, nil, 2, "b")] ), RescueNode(91...101)( (91...97), @@ -66,7 +66,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -117,7 +117,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -135,7 +135,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -153,7 +153,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "c" )] ), @@ -172,7 +172,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -195,7 +195,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -219,7 +219,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "baz" ), CallNode(266...269)( @@ -230,7 +230,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -267,7 +267,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "bar" ), (307...310), @@ -348,7 +348,7 @@ ProgramNode(0...530)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/literal.txt b/test/yarp/snapshots/unparser/corpus/literal/literal.txt index 01e9155ec234db..bab790a7134a27 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/literal.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/literal.txt @@ -119,7 +119,7 @@ ProgramNode(0...916)( nil, nil, nil, - 0, + 2, "baz" ), (160...162) @@ -142,7 +142,7 @@ ProgramNode(0...916)( nil, nil, nil, - 0, + 2, "baz" ), (198...200) @@ -185,29 +185,9 @@ ProgramNode(0...916)( RationalNode(234...238)(FloatNode(234...237)()), RationalNode(239...243)(FloatNode(239...242)()), ImaginaryNode(244...246)(IntegerNode(244...245)()), - CallNode(247...250)( - ImaginaryNode(248...250)(IntegerNode(248...249)()), - nil, - (247...248), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + ImaginaryNode(247...250)(IntegerNode(247...249)()), ImaginaryNode(251...255)(FloatNode(251...254)()), - CallNode(256...261)( - ImaginaryNode(257...261)(FloatNode(257...260)()), - nil, - (256...257), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + ImaginaryNode(256...261)(FloatNode(256...260)()), ImaginaryNode(262...294)(IntegerNode(262...293)()), ImaginaryNode(295...298)( RationalNode(295...297)(IntegerNode(295...296)()) @@ -230,7 +210,7 @@ ProgramNode(0...916)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -296,22 +276,10 @@ ProgramNode(0...916)( XStringNode(435...439)((435...436), (436...438), (438...439), "`"), XStringNode(440...443)((440...441), (441...442), (442...443), "\""), SymbolNode(444...448)((444...445), (445...448), nil, "foo"), - InterpolatedSymbolNode(449...455)( - (449...451), - [StringNode(451...454)(nil, (451...454), nil, "A B")], - (454...455) - ), + SymbolNode(449...455)(nil, (451...454), nil, "A B"), SymbolNode(456...460)((456...457), (457...460), nil, "foo"), - InterpolatedSymbolNode(461...467)( - (461...463), - [StringNode(463...466)(nil, (463...466), nil, "A B")], - (466...467) - ), - InterpolatedSymbolNode(468...475)( - (468...470), - [StringNode(470...474)(nil, (470...474), nil, "A\"B")], - (474...475) - ), + SymbolNode(461...467)(nil, (463...466), nil, "A B"), + SymbolNode(468...475)(nil, (470...474), nil, "A\"B"), InterpolatedSymbolNode(476...479)((476...478), [], (478...479)), RegularExpressionNode(480...485)( (480...481), @@ -408,7 +376,7 @@ ProgramNode(0...916)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -499,17 +467,7 @@ ProgramNode(0...916)( (651...653), 0 ), - CallNode(657...661)( - FloatNode(658...661)(), - nil, - (657...658), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + FloatNode(657...661)(), FloatNode(662...665)(), ArrayNode(666...672)( [IntegerNode(667...668)(), IntegerNode(670...671)()], @@ -527,7 +485,7 @@ ProgramNode(0...916)( nil, nil, nil, - 0, + 2, "n2" )], (673...674), @@ -619,7 +577,7 @@ ProgramNode(0...916)( nil, nil, nil, - 0, + 2, "foo" ) )] @@ -662,11 +620,7 @@ ProgramNode(0...916)( HashNode(828...843)( (828...829), [AssocNode(830...841)( - InterpolatedSymbolNode(830...836)( - (830...832), - [StringNode(832...835)(nil, (832...835), nil, "a b")], - (835...836) - ), + SymbolNode(830...836)(nil, (832...835), nil, "a b"), IntegerNode(840...841)(), (837...839) )], @@ -723,11 +677,7 @@ ProgramNode(0...916)( 0, "foo" ), - InterpolatedSymbolNode(893...901)( - (893...895), - [StringNode(895...900)(nil, (895...900), nil, "a\\\n" + "b")], - (900...901) - ), + SymbolNode(893...901)(nil, (895...900), nil, "a\\\n" + "b"), InterpolatedXStringNode(902...916)( (902...903), [StringNode(903...907)(nil, (903...907), nil, " x\n"), @@ -742,7 +692,7 @@ ProgramNode(0...916)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/opasgn.txt b/test/yarp/snapshots/unparser/corpus/literal/opasgn.txt index df1836e4c57e32..04f547fc9ef616 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/opasgn.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/opasgn.txt @@ -39,7 +39,7 @@ ProgramNode(0...233)( LocalVariableOperatorAndWriteNode(36...43)( (36...37), (38...41), - CallNode(42...43)(nil, nil, (42...43), nil, nil, nil, nil, 0, "b"), + CallNode(42...43)(nil, nil, (42...43), nil, nil, nil, nil, 2, "b"), :a ), LocalVariableOperatorOrWriteNode(44...51)( @@ -87,8 +87,8 @@ ProgramNode(0...233)( (76...79), (76...77), ArgumentsNode(77...83)( - [CallNode(77...78)(nil, nil, (77...78), nil, nil, nil, nil, 0, "k"), - CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 0, "v")] + [CallNode(77...78)(nil, nil, (77...78), nil, nil, nil, nil, 2, "k"), + CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 2, "v")] ), (78...79), nil, @@ -188,7 +188,7 @@ ProgramNode(0...233)( "b=" ), (134...137), - CallNode(138...139)(nil, nil, (138...139), nil, nil, nil, nil, 0, "b") + CallNode(138...139)(nil, nil, (138...139), nil, nil, nil, nil, 2, "b") ), CallOperatorOrWriteNode(140...149)( CallNode(140...143)( @@ -220,7 +220,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -248,7 +248,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -276,7 +276,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -304,7 +304,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -332,7 +332,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -360,7 +360,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -370,7 +370,7 @@ ProgramNode(0...233)( "[]=" ), (206...209), - CallNode(210...211)(nil, nil, (210...211), nil, nil, nil, nil, 0, "b") + CallNode(210...211)(nil, nil, (210...211), nil, nil, nil, nil, 2, "b") ), CallOperatorOrWriteNode(212...222)( CallNode(212...216)( @@ -387,7 +387,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -409,7 +409,7 @@ ProgramNode(0...233)( nil, nil, nil, - 0, + 2, "foo" ), (226...227), diff --git a/test/yarp/snapshots/unparser/corpus/literal/pattern.txt b/test/yarp/snapshots/unparser/corpus/literal/pattern.txt index cc8b9242d631c4..9488cc78502614 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/pattern.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/pattern.txt @@ -2,7 +2,7 @@ ProgramNode(0...408)( [:a, :x, :y], StatementsNode(0...408)( [CaseNode(0...345)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), [InNode(9...38)( ArrayPatternNode(12...26)( ConstantReadNode(12...13)(), @@ -37,7 +37,7 @@ ProgramNode(0...408)( nil, nil, nil, - 0, + 2, "y" )] ), @@ -230,7 +230,7 @@ ProgramNode(0...408)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(355...372)( @@ -262,7 +262,7 @@ ProgramNode(0...408)( nil, nil, nil, - 0, + 2, "foo" ), [InNode(386...390)( diff --git a/test/yarp/snapshots/unparser/corpus/literal/pragma.txt b/test/yarp/snapshots/unparser/corpus/literal/pragma.txt index 26e9f4c56d2ee3..86c13274335adf 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/pragma.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/pragma.txt @@ -4,6 +4,6 @@ ProgramNode(0...38)( [SourceEncodingNode(0...12)(), SourceFileNode(13...21)("unparser/corpus/literal/pragma.txt"), SourceLineNode(22...30)(), - CallNode(31...38)(nil, nil, (31...38), nil, nil, nil, nil, 0, "__dir__")] + CallNode(31...38)(nil, nil, (31...38), nil, nil, nil, nil, 2, "__dir__")] ) ) diff --git a/test/yarp/snapshots/unparser/corpus/literal/rescue.txt b/test/yarp/snapshots/unparser/corpus/literal/rescue.txt index f0018fbfad59e6..ed653b5d1362e9 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/rescue.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/rescue.txt @@ -2,12 +2,12 @@ ProgramNode(0...64)( [:x], StatementsNode(0...64)( [RescueModifierNode(0...14)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (4...10), - CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "bar") + CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "bar") ), RescueModifierNode(15...36)( - CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 0, "foo"), + CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 2, "foo"), (19...25), ReturnNode(26...36)( (26...32), @@ -20,7 +20,7 @@ ProgramNode(0...64)( nil, nil, nil, - 0, + 2, "bar" )] ) @@ -40,7 +40,7 @@ ProgramNode(0...64)( nil, nil, nil, - 0, + 2, "foo" ), (46...52), @@ -55,7 +55,7 @@ ProgramNode(0...64)( nil, nil, nil, - 0, + 2, "bar" )] ) diff --git a/test/yarp/snapshots/unparser/corpus/literal/send.txt b/test/yarp/snapshots/unparser/corpus/literal/send.txt index a91a3239142ef1..e6ba96546f22ff 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/send.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/send.txt @@ -35,7 +35,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "b" ), (20...21), @@ -162,7 +162,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "bar" )], nil @@ -190,7 +190,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), [WhenNode(179...187)( @@ -203,7 +203,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "bar" )], nil @@ -296,10 +296,11 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), - nil + nil, + 0 ), (268...269), (269...272), @@ -321,10 +322,11 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), - nil + nil, + 0 ), (286...287), (287...290), @@ -367,7 +369,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -452,7 +454,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -524,7 +526,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -572,7 +574,7 @@ ProgramNode(0...991)( "FOO" ), CallNode(417...421)( - CallNode(417...418)(nil, nil, (417...418), nil, nil, nil, nil, 0, "a"), + CallNode(417...418)(nil, nil, (417...418), nil, nil, nil, nil, 2, "a"), (418...420), (420...421), nil, @@ -583,7 +585,7 @@ ProgramNode(0...991)( "b" ), CallNode(422...427)( - CallNode(422...423)(nil, nil, (422...423), nil, nil, nil, nil, 0, "a"), + CallNode(422...423)(nil, nil, (422...423), nil, nil, nil, nil, 2, "a"), (423...424), (424...427), nil, @@ -593,7 +595,7 @@ ProgramNode(0...991)( 0, "foo" ), - CallNode(428...431)(nil, nil, (428...431), nil, nil, nil, nil, 0, "foo"), + CallNode(428...431)(nil, nil, (428...431), nil, nil, nil, nil, 2, "foo"), CallNode(432...450)( CallNode(432...435)( nil, @@ -603,7 +605,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -621,7 +623,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -636,7 +638,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -664,7 +666,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -702,7 +704,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), CallNode(477...480)( @@ -713,7 +715,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "bar" ), (474...476) @@ -745,7 +747,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "block" ), (487...488) @@ -772,7 +774,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "args" ) ), @@ -785,7 +787,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "block" ), (506...507) @@ -812,7 +814,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "arguments" ) )] @@ -849,7 +851,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -872,7 +874,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "bar" ), SplatNode(558...563)( @@ -885,7 +887,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "args" ) )] @@ -910,7 +912,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -945,7 +947,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (586...587), @@ -961,7 +963,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "baz" ), (591...592) @@ -981,7 +983,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (600...601), @@ -998,7 +1000,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "arga" ) ), @@ -1010,7 +1012,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), SplatNode(617...622)( @@ -1023,7 +1025,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "argb" ) )] @@ -1042,7 +1044,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (627...628), @@ -1059,7 +1061,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "args" ) )] @@ -1078,7 +1080,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (642...643), @@ -1095,7 +1097,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "args" ) ), @@ -1107,7 +1109,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -1125,7 +1127,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (662...663), @@ -1142,7 +1144,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "baz" ), (673...674) @@ -1162,7 +1164,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (682...683), @@ -1180,7 +1182,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "boz" ), nil @@ -1201,7 +1203,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (700...701), @@ -1216,7 +1218,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), KeywordHashNode(710...722)( @@ -1235,7 +1237,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "boz" ), (716...718) @@ -1256,7 +1258,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (727...728), @@ -1271,7 +1273,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), SplatNode(737...742)( @@ -1284,7 +1286,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "args" ) )] @@ -1303,7 +1305,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (747...748), @@ -1318,7 +1320,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), SplatNode(757...762)( @@ -1331,7 +1333,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "args" ) ), @@ -1344,7 +1346,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "block" ), (764...765) @@ -1364,7 +1366,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (775...776), @@ -1379,7 +1381,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), HashNode(785...787)((785...786), [], (786...787))] @@ -1398,7 +1400,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (792...793), @@ -1417,7 +1419,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "boz" ), nil @@ -1432,7 +1434,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "boz" )] ), @@ -1450,7 +1452,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (819...820), @@ -1481,7 +1483,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "b" ), nil @@ -1502,7 +1504,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (842...843), @@ -1520,7 +1522,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "b" ), nil @@ -1541,7 +1543,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (854...855), @@ -1558,7 +1560,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "a" ), (857...859) @@ -1579,7 +1581,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -1596,7 +1598,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "baz" ) )] @@ -1615,7 +1617,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -1638,7 +1640,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -1686,7 +1688,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "a" ), nil, @@ -1701,7 +1703,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -1729,7 +1731,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "c" ), nil, @@ -1744,7 +1746,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -1775,7 +1777,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "a" ), nil, @@ -1790,7 +1792,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -1816,7 +1818,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "c" ), (940...941), @@ -1831,7 +1833,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "e" ), CallNode(946...947)( @@ -1842,7 +1844,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "f" )] ), @@ -1869,7 +1871,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "a" ), nil, @@ -1884,7 +1886,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -1910,7 +1912,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "c" ), (960...961), @@ -1927,7 +1929,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "f" ) )] @@ -1959,7 +1961,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (969...971) @@ -1980,7 +1982,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (979...981), @@ -2001,7 +2003,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "foo" ), (986...987), @@ -2016,7 +2018,7 @@ ProgramNode(0...991)( nil, nil, nil, - 0, + 2, "b" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/since/27.txt b/test/yarp/snapshots/unparser/corpus/literal/since/27.txt index 0f2e6cc90ca358..cccfbc64b47061 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/since/27.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/since/27.txt @@ -7,7 +7,7 @@ ProgramNode(0...22)( nil, StatementsNode(7...14)( [CallNode(7...14)( - CallNode(7...9)(nil, nil, (7...9), nil, nil, nil, nil, 0, "_1"), + CallNode(7...9)(nil, nil, (7...9), nil, nil, nil, nil, 2, "_1"), nil, (10...11), nil, @@ -20,7 +20,7 @@ ProgramNode(0...22)( nil, nil, nil, - 0, + 2, "_2" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/super.txt b/test/yarp/snapshots/unparser/corpus/literal/super.txt index 6a06faa9cfafd2..191e0a5b918bfd 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/super.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/super.txt @@ -7,7 +7,7 @@ ProgramNode(0...159)( (14...19), (19...20), ArgumentsNode(20...21)( - [CallNode(20...21)(nil, nil, (20...21), nil, nil, nil, nil, 0, "a")] + [CallNode(20...21)(nil, nil, (20...21), nil, nil, nil, nil, 2, "a")] ), (21...22), nil @@ -16,8 +16,8 @@ ProgramNode(0...159)( (23...28), (28...29), ArgumentsNode(29...33)( - [CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 0, "a"), - CallNode(32...33)(nil, nil, (32...33), nil, nil, nil, nil, 0, "b")] + [CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 2, "a"), + CallNode(32...33)(nil, nil, (32...33), nil, nil, nil, nil, 2, "b")] ), (33...34), nil @@ -35,7 +35,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "block" ), (41...42) @@ -48,7 +48,7 @@ ProgramNode(0...159)( (49...54), (54...55), ArgumentsNode(55...64)( - [CallNode(55...56)(nil, nil, (55...56), nil, nil, nil, nil, 0, "a"), + [CallNode(55...56)(nil, nil, (55...56), nil, nil, nil, nil, 2, "a"), BlockArgumentNode(58...64)( CallNode(59...64)( nil, @@ -58,7 +58,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "block" ), (58...59) @@ -90,7 +90,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -117,7 +117,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -137,7 +137,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -154,7 +154,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -179,7 +179,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -199,7 +199,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "a" ), CallNode(147...148)( @@ -210,7 +210,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -227,7 +227,7 @@ ProgramNode(0...159)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/literal/unary.txt b/test/yarp/snapshots/unparser/corpus/literal/unary.txt index ac413537706cbd..d4279a42221f46 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/unary.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/unary.txt @@ -54,7 +54,7 @@ ProgramNode(0...54)( nil, nil, nil, - 0, + 2, "foo" ), CallNode(20...23)( @@ -65,7 +65,7 @@ ProgramNode(0...54)( nil, nil, nil, - 0, + 2, "bar" ), (17...19) @@ -134,7 +134,7 @@ ProgramNode(0...54)( "!" ), CallNode(36...38)( - CallNode(37...38)(nil, nil, (37...38), nil, nil, nil, nil, 0, "a"), + CallNode(37...38)(nil, nil, (37...38), nil, nil, nil, nil, 2, "a"), nil, (36...37), nil, @@ -145,7 +145,7 @@ ProgramNode(0...54)( "~" ), CallNode(39...41)( - CallNode(40...41)(nil, nil, (40...41), nil, nil, nil, nil, 0, "a"), + CallNode(40...41)(nil, nil, (40...41), nil, nil, nil, nil, 2, "a"), nil, (39...40), nil, @@ -156,7 +156,7 @@ ProgramNode(0...54)( "-@" ), CallNode(42...44)( - CallNode(43...44)(nil, nil, (43...44), nil, nil, nil, nil, 0, "a"), + CallNode(43...44)(nil, nil, (43...44), nil, nil, nil, nil, 2, "a"), nil, (42...43), nil, @@ -179,7 +179,7 @@ ProgramNode(0...54)( nil, nil, nil, - 0, + 2, "a" ), nil, diff --git a/test/yarp/snapshots/unparser/corpus/literal/variables.txt b/test/yarp/snapshots/unparser/corpus/literal/variables.txt index 1cf71a2360d2d1..b7ab14e36c35f7 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/variables.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/variables.txt @@ -1,7 +1,7 @@ ProgramNode(0...66)( [], StatementsNode(0...66)( - [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), InstanceVariableReadNode(2...4)(), ClassVariableReadNode(5...8)(), GlobalVariableReadNode(9...11)(), diff --git a/test/yarp/snapshots/unparser/corpus/literal/while.txt b/test/yarp/snapshots/unparser/corpus/literal/while.txt index a08e9696dd1565..9808846085f0c9 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/while.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/while.txt @@ -40,7 +40,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "foo" ), StatementsNode(43...52)( @@ -51,7 +51,8 @@ ProgramNode(0...620)( (43...46), (47...48) )] - ) + ), + 0 )] ), (15...16), @@ -84,7 +85,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -105,13 +106,14 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" ), (80...83), (84...85) )] - ) + ), + 0 )] ), [:foo], @@ -142,13 +144,14 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" ), (123...126), (127...128) )] - ) + ), + 0 )] ), (143...146) @@ -173,13 +176,14 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" ), (159...162), (163...164) )] - ) + ), + 0 )] ), (179...182) @@ -199,7 +203,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "foo" ), StatementsNode(209...218)( @@ -214,13 +218,14 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" ), (209...212), (213...214) )] - ) + ), + 0 )] ), (225...228) @@ -264,7 +269,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "foo" ), StatementsNode(274...283)( @@ -279,13 +284,14 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" ), (274...277), (278...279) )] - ) + ), + 0 )] ), (246...247), @@ -341,13 +347,14 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" ), (345...348), (349...350) )] - ) + ), + 0 )] ), (317...318), @@ -374,7 +381,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "baz" ), StatementsNode(376...391)( @@ -389,7 +396,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -398,7 +405,8 @@ ProgramNode(0...620)( nil, (388...391) )] - ) + ), + 1 )] ), (375...376), @@ -417,7 +425,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "baz" ), StatementsNode(403...418)( @@ -432,7 +440,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -441,7 +449,8 @@ ProgramNode(0...620)( nil, (415...418) )] - ) + ), + 1 ), UntilNode(429...460)( (451...456), @@ -453,7 +462,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "baz" ), StatementsNode(429...450)( @@ -468,7 +477,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "foo" ), CallNode(443...446)( @@ -479,7 +488,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -488,7 +497,8 @@ ProgramNode(0...620)( nil, (447...450) )] - ) + ), + 1 ), WhileNode(461...492)( (483...488), @@ -500,7 +510,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "baz" ), StatementsNode(461...482)( @@ -515,7 +525,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "foo" ), CallNode(475...478)( @@ -526,7 +536,7 @@ ProgramNode(0...620)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -535,13 +545,15 @@ ProgramNode(0...620)( nil, (479...482) )] - ) + ), + 1 ), - WhileNode(493...508)((493...498), FalseNode(499...504)(), nil), + WhileNode(493...508)((493...498), FalseNode(499...504)(), nil, 0), WhileNode(509...528)( (509...514), FalseNode(515...520)(), - StatementsNode(523...524)([IntegerNode(523...524)()]) + StatementsNode(523...524)([IntegerNode(523...524)()]), + 0 ), WhileNode(529...556)( (529...534), @@ -564,13 +576,15 @@ ProgramNode(0...620)( ), StatementsNode(547...552)( [SymbolNode(547...552)((547...548), (548...552), nil, "body")] - ) + ), + 0 ), - UntilNode(557...572)((557...562), FalseNode(563...568)(), nil), + UntilNode(557...572)((557...562), FalseNode(563...568)(), nil, 0), UntilNode(573...592)( (573...578), FalseNode(579...584)(), - StatementsNode(587...588)([IntegerNode(587...588)()]) + StatementsNode(587...588)([IntegerNode(587...588)()]), + 0 ), UntilNode(593...620)( (593...598), @@ -593,7 +607,8 @@ ProgramNode(0...620)( ), StatementsNode(611...616)( [SymbolNode(611...616)((611...612), (612...616), nil, "body")] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/unparser/corpus/literal/yield.txt b/test/yarp/snapshots/unparser/corpus/literal/yield.txt index 224659ffb17ebf..4ccd79e2dd1c22 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/yield.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/yield.txt @@ -6,7 +6,7 @@ ProgramNode(0...26)( (6...11), (11...12), ArgumentsNode(12...13)( - [CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 0, "a")] + [CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 2, "a")] ), (13...14) ), @@ -14,8 +14,8 @@ ProgramNode(0...26)( (15...20), (20...21), ArgumentsNode(21...25)( - [CallNode(21...22)(nil, nil, (21...22), nil, nil, nil, nil, 0, "a"), - CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 0, "b")] + [CallNode(21...22)(nil, nil, (21...22), nil, nil, nil, nil, 2, "a"), + CallNode(24...25)(nil, nil, (24...25), nil, nil, nil, nil, 2, "b")] ), (25...26) )] diff --git a/test/yarp/snapshots/unparser/corpus/semantic/and.txt b/test/yarp/snapshots/unparser/corpus/semantic/and.txt index b082d308f777d2..de40267054e840 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/and.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/and.txt @@ -3,14 +3,14 @@ ProgramNode(0...77)( StatementsNode(0...77)( [OrNode(0...14)( RangeNode(0...5)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "b"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "b"), (1...4), 1 ), RangeNode(9...14)( - CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 0, "c"), - CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 0, "d"), + CallNode(9...10)(nil, nil, (9...10), nil, nil, nil, nil, 2, "c"), + CallNode(13...14)(nil, nil, (13...14), nil, nil, nil, nil, 2, "d"), (10...13), 1 ), @@ -18,14 +18,14 @@ ProgramNode(0...77)( ), AndNode(15...30)( RangeNode(15...20)( - CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 0, "a"), - CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 0, "b"), + CallNode(15...16)(nil, nil, (15...16), nil, nil, nil, nil, 2, "a"), + CallNode(19...20)(nil, nil, (19...20), nil, nil, nil, nil, 2, "b"), (16...19), 1 ), RangeNode(25...30)( - CallNode(25...26)(nil, nil, (25...26), nil, nil, nil, nil, 0, "c"), - CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 0, "d"), + CallNode(25...26)(nil, nil, (25...26), nil, nil, nil, nil, 2, "c"), + CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 2, "d"), (26...29), 1 ), @@ -34,17 +34,17 @@ ProgramNode(0...77)( IfNode(32...53)( (32...34), OrNode(35...49)( - RangeNode(35...40)( - CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 0, "a"), - CallNode(39...40)(nil, nil, (39...40), nil, nil, nil, nil, 0, "b"), + FlipFlopNode(35...40)( + CallNode(35...36)(nil, nil, (35...36), nil, nil, nil, nil, 2, "a"), + CallNode(39...40)(nil, nil, (39...40), nil, nil, nil, nil, 2, "b"), (36...39), - 3 + 1 ), - RangeNode(44...49)( - CallNode(44...45)(nil, nil, (44...45), nil, nil, nil, nil, 0, "c"), - CallNode(48...49)(nil, nil, (48...49), nil, nil, nil, nil, 0, "d"), + FlipFlopNode(44...49)( + CallNode(44...45)(nil, nil, (44...45), nil, nil, nil, nil, 2, "c"), + CallNode(48...49)(nil, nil, (48...49), nil, nil, nil, nil, 2, "d"), (45...48), - 3 + 1 ), (41...43) ), @@ -55,17 +55,17 @@ ProgramNode(0...77)( IfNode(55...77)( (55...57), AndNode(58...73)( - RangeNode(58...63)( - CallNode(58...59)(nil, nil, (58...59), nil, nil, nil, nil, 0, "a"), - CallNode(62...63)(nil, nil, (62...63), nil, nil, nil, nil, 0, "b"), + FlipFlopNode(58...63)( + CallNode(58...59)(nil, nil, (58...59), nil, nil, nil, nil, 2, "a"), + CallNode(62...63)(nil, nil, (62...63), nil, nil, nil, nil, 2, "b"), (59...62), - 3 + 1 ), - RangeNode(68...73)( - CallNode(68...69)(nil, nil, (68...69), nil, nil, nil, nil, 0, "c"), - CallNode(72...73)(nil, nil, (72...73), nil, nil, nil, nil, 0, "d"), + FlipFlopNode(68...73)( + CallNode(68...69)(nil, nil, (68...69), nil, nil, nil, nil, 2, "c"), + CallNode(72...73)(nil, nil, (72...73), nil, nil, nil, nil, 2, "d"), (69...72), - 3 + 1 ), (64...67) ), diff --git a/test/yarp/snapshots/unparser/corpus/semantic/block.txt b/test/yarp/snapshots/unparser/corpus/semantic/block.txt index c4b2d1ab4ce83d..4e8eb82fe074e2 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/block.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/block.txt @@ -151,7 +151,7 @@ ProgramNode(0...148)( nil, nil, nil, - 0, + 2, "a" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/semantic/def.txt b/test/yarp/snapshots/unparser/corpus/semantic/def.txt index 922dbc5a455ea2..439ffafe1be5d2 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/def.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/def.txt @@ -17,7 +17,7 @@ ProgramNode(0...55)( nil, nil, nil, - 0, + 2, "a" ), nil, @@ -32,7 +32,7 @@ ProgramNode(0...55)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -60,7 +60,7 @@ ProgramNode(0...55)( nil, StatementsNode(33...51)( [RescueModifierNode(33...51)( - CallNode(33...34)(nil, nil, (33...34), nil, nil, nil, nil, 0, "a"), + CallNode(33...34)(nil, nil, (33...34), nil, nil, nil, nil, 2, "a"), (35...41), ConstantReadNode(42...51)() )] diff --git a/test/yarp/snapshots/unparser/corpus/semantic/kwbegin.txt b/test/yarp/snapshots/unparser/corpus/semantic/kwbegin.txt index b0ea59e21dac98..5ae3acede61319 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/kwbegin.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/kwbegin.txt @@ -20,7 +20,7 @@ ProgramNode(0...215)( BeginNode(41...54)( (41...46), StatementsNode(49...50)( - [CallNode(49...50)(nil, nil, (49...50), nil, nil, nil, nil, 0, "a")] + [CallNode(49...50)(nil, nil, (49...50), nil, nil, nil, nil, 2, "a")] ), nil, nil, @@ -30,7 +30,7 @@ ProgramNode(0...215)( BeginNode(56...80)( (56...61), StatementsNode(64...65)( - [CallNode(64...65)(nil, nil, (64...65), nil, nil, nil, nil, 0, "a")] + [CallNode(64...65)(nil, nil, (64...65), nil, nil, nil, nil, 2, "a")] ), RescueNode(66...76)( (66...72), @@ -38,7 +38,7 @@ ProgramNode(0...215)( nil, nil, StatementsNode(75...76)( - [CallNode(75...76)(nil, nil, (75...76), nil, nil, nil, nil, 0, "b")] + [CallNode(75...76)(nil, nil, (75...76), nil, nil, nil, nil, 2, "b")] ), nil ), @@ -49,8 +49,8 @@ ProgramNode(0...215)( BeginNode(82...110)( (82...87), StatementsNode(90...95)( - [CallNode(90...91)(nil, nil, (90...91), nil, nil, nil, nil, 0, "a"), - CallNode(94...95)(nil, nil, (94...95), nil, nil, nil, nil, 0, "b")] + [CallNode(90...91)(nil, nil, (90...91), nil, nil, nil, nil, 2, "a"), + CallNode(94...95)(nil, nil, (94...95), nil, nil, nil, nil, 2, "b")] ), RescueNode(96...106)( (96...102), @@ -66,7 +66,7 @@ ProgramNode(0...215)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -117,7 +117,7 @@ ProgramNode(0...215)( nil, nil, nil, - 0, + 2, "a" )] ), @@ -135,7 +135,7 @@ ProgramNode(0...215)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -153,7 +153,7 @@ ProgramNode(0...215)( nil, nil, nil, - 0, + 2, "c" )] ), @@ -172,7 +172,7 @@ ProgramNode(0...215)( nil, nil, nil, - 0, + 2, "d" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/semantic/literal.txt b/test/yarp/snapshots/unparser/corpus/semantic/literal.txt index 30225ed2ca0718..d8578058df0b35 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/literal.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/literal.txt @@ -2,32 +2,12 @@ ProgramNode(0...131)( [], StatementsNode(0...131)( [RationalNode(0...4)(FloatNode(0...3)()), - CallNode(5...8)( - RationalNode(6...8)(IntegerNode(6...7)()), - nil, - (5...6), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + RationalNode(5...8)(IntegerNode(5...7)()), IntegerNode(9...12)(), IntegerNode(13...18)(), FloatNode(19...23)(), FloatNode(24...38)(), - CallNode(39...54)( - FloatNode(40...54)(), - nil, - (39...40), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + FloatNode(39...54)(), StringNode(55...57)((55...56), (56...57), nil, "c"), RegularExpressionNode(58...63)((58...61), (61...62), (62...63), "/", 0), RegularExpressionNode(64...70)((64...67), (67...69), (69...70), ")", 0), @@ -43,17 +23,7 @@ ProgramNode(0...131)( 0 ), FloatNode(86...102)(), - CallNode(103...120)( - FloatNode(104...120)(), - nil, - (103...104), - nil, - nil, - nil, - nil, - 0, - "-@" - ), + FloatNode(103...120)(), CallNode(121...131)( nil, nil, @@ -74,7 +44,7 @@ ProgramNode(0...131)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/semantic/send.txt b/test/yarp/snapshots/unparser/corpus/semantic/send.txt index 4f2c294e9e5370..b584fa06cf94ca 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/send.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/send.txt @@ -1,7 +1,7 @@ ProgramNode(0...44)( [], StatementsNode(0...44)( - [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), CallNode(4...10)( nil, nil, @@ -16,7 +16,7 @@ ProgramNode(0...44)( CallNode(12...27)( CallNode(12...22)( CallNode(12...20)( - CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 0, "a"), + CallNode(12...13)(nil, nil, (12...13), nil, nil, nil, nil, 2, "a"), (13...14), (14...17), (17...18), @@ -29,7 +29,7 @@ ProgramNode(0...44)( nil, nil, nil, - 0, + 2, "b" )] ), @@ -51,7 +51,7 @@ ProgramNode(0...44)( (23...25), nil, ArgumentsNode(26...27)( - [CallNode(26...27)(nil, nil, (26...27), nil, nil, nil, nil, 0, "d")] + [CallNode(26...27)(nil, nil, (26...27), nil, nil, nil, nil, 2, "d")] ), nil, nil, @@ -59,7 +59,7 @@ ProgramNode(0...44)( "==" ), CallNode(29...44)( - CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 0, "a"), + CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 2, "a"), nil, (31...33), nil, @@ -74,7 +74,7 @@ ProgramNode(0...44)( nil, nil, nil, - 0, + 2, "d" ), (35...36), @@ -98,7 +98,7 @@ ProgramNode(0...44)( nil, nil, nil, - 0, + 2, "c" )] ), diff --git a/test/yarp/snapshots/unparser/corpus/semantic/while.txt b/test/yarp/snapshots/unparser/corpus/semantic/while.txt index f608e21cfb29e6..1e8be734ac1ae4 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/while.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/while.txt @@ -15,8 +15,9 @@ ProgramNode(0...188)( "b?" ), StatementsNode(0...1)( - [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a")] - ) + [CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a")] + ), + 0 ), UntilNode(15...34)( (15...20), @@ -32,8 +33,9 @@ ProgramNode(0...188)( "b?" ), StatementsNode(29...30)( - [CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 0, "a")] - ) + [CallNode(29...30)(nil, nil, (29...30), nil, nil, nil, nil, 2, "a")] + ), + 0 ), WhileNode(36...55)( (46...51), @@ -50,18 +52,19 @@ ProgramNode(0...188)( nil, nil, nil, - 0, + 2, "bar" ), (36...39), (40...41) )] - ) + ), + 0 ), UntilNode(57...75)( (59...64), AndNode(65...75)( - CallNode(65...66)(nil, nil, (65...66), nil, nil, nil, nil, 0, "b"), + CallNode(65...66)(nil, nil, (65...66), nil, nil, nil, nil, 2, "b"), CallNode(70...75)( nil, nil, @@ -76,19 +79,21 @@ ProgramNode(0...188)( (67...69) ), StatementsNode(57...58)( - [CallNode(57...58)(nil, nil, (57...58), nil, nil, nil, nil, 0, "a")] - ) + [CallNode(57...58)(nil, nil, (57...58), nil, nil, nil, nil, 2, "a")] + ), + 0 ), WhileNode(77...96)( (77...82), LocalVariableWriteNode(83...88)( :a, 0, - CallNode(87...88)(nil, nil, (87...88), nil, nil, nil, nil, 0, "b"), + CallNode(87...88)(nil, nil, (87...88), nil, nil, nil, nil, 2, "b"), (83...84), (85...86) ), - StatementsNode(91...92)([LocalVariableReadNode(91...92)(:a, 0)]) + StatementsNode(91...92)([LocalVariableReadNode(91...92)(:a, 0)]), + 0 ), UntilNode(98...130)( (100...105), @@ -113,7 +118,7 @@ ProgramNode(0...188)( nil, nil, nil, - 0, + 2, "c" )] ), @@ -123,7 +128,8 @@ ProgramNode(0...188)( 0, "b" ), - StatementsNode(98...99)([LocalVariableReadNode(98...99)(:a, 0)]) + StatementsNode(98...99)([LocalVariableReadNode(98...99)(:a, 0)]), + 0 ), ModuleNode(132...188)( [:foo], @@ -141,7 +147,7 @@ ProgramNode(0...188)( nil, nil, nil, - 0, + 2, "exp" ), (143...146), @@ -162,13 +168,14 @@ ProgramNode(0...188)( nil, nil, nil, - 0, + 2, "bar" ), (169...172), (173...174) )] - ) + ), + 0 )] ), (185...188) diff --git a/test/yarp/snapshots/until.txt b/test/yarp/snapshots/until.txt index c9ae1f6fbdfc04..3218ce2d423b1b 100644 --- a/test/yarp/snapshots/until.txt +++ b/test/yarp/snapshots/until.txt @@ -4,27 +4,32 @@ ProgramNode(0...109)( [UntilNode(0...18)( (0...5), TrueNode(6...10)(), - StatementsNode(12...13)([IntegerNode(12...13)()]) + StatementsNode(12...13)([IntegerNode(12...13)()]), + 0 ), UntilNode(20...32)( (22...27), TrueNode(28...32)(), - StatementsNode(20...21)([IntegerNode(20...21)()]) + StatementsNode(20...21)([IntegerNode(20...21)()]), + 0 ), UntilNode(34...50)( (40...45), TrueNode(46...50)(), - StatementsNode(34...39)([BreakNode(34...39)(nil, (34...39))]) + StatementsNode(34...39)([BreakNode(34...39)(nil, (34...39))]), + 0 ), UntilNode(52...67)( (57...62), TrueNode(63...67)(), - StatementsNode(52...56)([NextNode(52...56)(nil, (52...56))]) + StatementsNode(52...56)([NextNode(52...56)(nil, (52...56))]), + 0 ), UntilNode(69...86)( (76...81), TrueNode(82...86)(), - StatementsNode(69...75)([ReturnNode(69...75)((69...75), nil)]) + StatementsNode(69...75)([ReturnNode(69...75)((69...75), nil)]), + 0 ), UntilNode(88...109)( (99...104), @@ -54,7 +59,8 @@ ProgramNode(0...109)( 0, "foo" )] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/variables.txt b/test/yarp/snapshots/variables.txt index 73645e4e52fffe..a4373717f511d9 100644 --- a/test/yarp/snapshots/variables.txt +++ b/test/yarp/snapshots/variables.txt @@ -36,7 +36,7 @@ ProgramNode(0...293)( IntegerNode(79...80)(), (77...78) ), - CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 0, "a"), + CallNode(82...83)(nil, nil, (82...83), nil, nil, nil, nil, 2, "a"), LocalVariableWriteNode(85...92)( :abc, 0, @@ -173,9 +173,13 @@ ProgramNode(0...293)( LocalVariableWriteNode(260...270)( :foo, 0, - SplatNode(266...270)( - (266...267), - LocalVariableReadNode(267...270)(:bar, 0) + ArrayNode(266...270)( + [SplatNode(266...270)( + (266...267), + LocalVariableReadNode(267...270)(:bar, 0) + )], + nil, + nil ), (260...263), (264...265) @@ -199,7 +203,7 @@ ProgramNode(0...293)( nil, nil, nil, - 0, + 2, "a" ), CallNode(288...289)( @@ -210,7 +214,7 @@ ProgramNode(0...293)( nil, nil, nil, - 0, + 2, "b" ), CallNode(291...292)( @@ -221,7 +225,7 @@ ProgramNode(0...293)( nil, nil, nil, - 0, + 2, "c" )] ), diff --git a/test/yarp/snapshots/while.txt b/test/yarp/snapshots/while.txt index 4f87258cf94f41..cc0d2fbf6ebe76 100644 --- a/test/yarp/snapshots/while.txt +++ b/test/yarp/snapshots/while.txt @@ -4,27 +4,32 @@ ProgramNode(0...314)( [WhileNode(0...18)( (0...5), TrueNode(6...10)(), - StatementsNode(12...13)([IntegerNode(12...13)()]) + StatementsNode(12...13)([IntegerNode(12...13)()]), + 0 ), WhileNode(20...32)( (22...27), TrueNode(28...32)(), - StatementsNode(20...21)([IntegerNode(20...21)()]) + StatementsNode(20...21)([IntegerNode(20...21)()]), + 0 ), WhileNode(34...50)( (40...45), TrueNode(46...50)(), - StatementsNode(34...39)([BreakNode(34...39)(nil, (34...39))]) + StatementsNode(34...39)([BreakNode(34...39)(nil, (34...39))]), + 0 ), WhileNode(52...67)( (57...62), TrueNode(63...67)(), - StatementsNode(52...56)([NextNode(52...56)(nil, (52...56))]) + StatementsNode(52...56)([NextNode(52...56)(nil, (52...56))]), + 0 ), WhileNode(69...86)( (76...81), TrueNode(82...86)(), - StatementsNode(69...75)([ReturnNode(69...75)((69...75), nil)]) + StatementsNode(69...75)([ReturnNode(69...75)((69...75), nil)]), + 0 ), WhileNode(88...109)( (99...104), @@ -54,7 +59,8 @@ ProgramNode(0...314)( 0, "foo" )] - ) + ), + 0 ), WhileNode(111...161)( (111...116), @@ -94,7 +100,8 @@ ProgramNode(0...314)( nil, (146...149) ), - StatementsNode(151...156)([BreakNode(151...156)(nil, (151...156))]) + StatementsNode(151...156)([BreakNode(151...156)(nil, (151...156))]), + 0 ), WhileNode(163...210)( (163...168), @@ -125,7 +132,8 @@ ProgramNode(0...314)( ), (195...198) ), - StatementsNode(200...205)([BreakNode(200...205)(nil, (200...205))]) + StatementsNode(200...205)([BreakNode(200...205)(nil, (200...205))]), + 0 ), WhileNode(212...260)( (212...217), @@ -149,7 +157,8 @@ ProgramNode(0...314)( ), (245...248) ), - StatementsNode(250...255)([BreakNode(250...255)(nil, (250...255))]) + StatementsNode(250...255)([BreakNode(250...255)(nil, (250...255))]), + 0 ), WhileNode(262...314)( (262...267), @@ -179,7 +188,8 @@ ProgramNode(0...314)( ), (299...302) ), - StatementsNode(304...309)([BreakNode(304...309)(nil, (304...309))]) + StatementsNode(304...309)([BreakNode(304...309)(nil, (304...309))]), + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/ambiuous_quoted_label_in_ternary_operator.txt b/test/yarp/snapshots/whitequark/ambiuous_quoted_label_in_ternary_operator.txt index 481a9c5f92dbf6..5fc3ec49db1c6c 100644 --- a/test/yarp/snapshots/whitequark/ambiuous_quoted_label_in_ternary_operator.txt +++ b/test/yarp/snapshots/whitequark/ambiuous_quoted_label_in_ternary_operator.txt @@ -3,10 +3,10 @@ ProgramNode(0...15)( StatementsNode(0...15)( [IfNode(0...15)( nil, - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), StatementsNode(4...10)( [CallNode(4...10)( - CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 0, "b"), + CallNode(4...5)(nil, nil, (4...5), nil, nil, nil, nil, 2, "b"), nil, (6...7), nil, diff --git a/test/yarp/snapshots/whitequark/and.txt b/test/yarp/snapshots/whitequark/and.txt index 6a488935e0d7e0..c6641a692b991b 100644 --- a/test/yarp/snapshots/whitequark/and.txt +++ b/test/yarp/snapshots/whitequark/and.txt @@ -2,13 +2,13 @@ ProgramNode(0...23)( [], StatementsNode(0...23)( [AndNode(0...10)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "bar"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "bar"), (4...6) ), AndNode(12...23)( - CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "foo"), - CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 0, "bar"), + CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "foo"), + CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 2, "bar"), (16...19) )] ) diff --git a/test/yarp/snapshots/whitequark/and_asgn.txt b/test/yarp/snapshots/whitequark/and_asgn.txt index abbaf776174ae4..d42bcc35f3e9d6 100644 --- a/test/yarp/snapshots/whitequark/and_asgn.txt +++ b/test/yarp/snapshots/whitequark/and_asgn.txt @@ -3,7 +3,7 @@ ProgramNode(0...28)( StatementsNode(0...28)( [CallOperatorAndWriteNode(0...11)( CallNode(0...5)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...5), nil, @@ -18,7 +18,7 @@ ProgramNode(0...28)( ), CallOperatorAndWriteNode(13...28)( CallNode(13...22)( - CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo"), + CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo"), nil, (16...22), (16...17), diff --git a/test/yarp/snapshots/whitequark/and_or_masgn.txt b/test/yarp/snapshots/whitequark/and_or_masgn.txt index 7fc2e35e0472d9..eb768ac90a4731 100644 --- a/test/yarp/snapshots/whitequark/and_or_masgn.txt +++ b/test/yarp/snapshots/whitequark/and_or_masgn.txt @@ -2,7 +2,7 @@ ProgramNode(0...40)( [:a, :b], StatementsNode(0...40)( [AndNode(0...19)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), ParenthesesNode(7...19)( StatementsNode(8...18)( [MultiWriteNode(8...18)( @@ -17,7 +17,7 @@ ProgramNode(0...40)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -30,7 +30,7 @@ ProgramNode(0...40)( (4...6) ), OrNode(21...40)( - CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "foo"), + CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "foo"), ParenthesesNode(28...40)( StatementsNode(29...39)( [MultiWriteNode(29...39)( @@ -45,7 +45,7 @@ ProgramNode(0...40)( nil, nil, nil, - 0, + 2, "bar" ), nil, diff --git a/test/yarp/snapshots/whitequark/args.txt b/test/yarp/snapshots/whitequark/args.txt index fe899700d25407..37e281c5346269 100644 --- a/test/yarp/snapshots/whitequark/args.txt +++ b/test/yarp/snapshots/whitequark/args.txt @@ -644,17 +644,7 @@ ProgramNode(0...690)( nil, [KeywordParameterNode(583...590)( (583...587), - CallNode(588...590)( - IntegerNode(589...590)(), - nil, - (588...589), - nil, - nil, - nil, - nil, - 0, - "-@" - ) + IntegerNode(588...590)() )], nil, nil diff --git a/test/yarp/snapshots/whitequark/args_args_assocs.txt b/test/yarp/snapshots/whitequark/args_args_assocs.txt index ee787d08a2fb33..5363d6780d032d 100644 --- a/test/yarp/snapshots/whitequark/args_args_assocs.txt +++ b/test/yarp/snapshots/whitequark/args_args_assocs.txt @@ -7,7 +7,7 @@ ProgramNode(0...46)( (0...3), (3...4), ArgumentsNode(4...18)( - [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "foo"), + [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "foo"), KeywordHashNode(9...18)( [AssocNode(9...18)( SymbolNode(9...13)((9...10), (10...13), nil, "foo"), @@ -27,7 +27,7 @@ ProgramNode(0...46)( (21...24), (24...25), ArgumentsNode(25...45)( - [CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 0, "foo"), + [CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 2, "foo"), KeywordHashNode(30...39)( [AssocNode(30...39)( SymbolNode(30...34)((30...31), (31...34), nil, "foo"), @@ -44,7 +44,7 @@ ProgramNode(0...46)( nil, nil, nil, - 0, + 2, "baz" ), (41...42) diff --git a/test/yarp/snapshots/whitequark/args_args_assocs_comma.txt b/test/yarp/snapshots/whitequark/args_args_assocs_comma.txt index fead72a5333cb9..da9ea1bd810fd6 100644 --- a/test/yarp/snapshots/whitequark/args_args_assocs_comma.txt +++ b/test/yarp/snapshots/whitequark/args_args_assocs_comma.txt @@ -2,12 +2,12 @@ ProgramNode(0...20)( [], StatementsNode(0...20)( [CallNode(0...20)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...20), (3...4), ArgumentsNode(4...18)( - [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "bar"), + [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "bar"), KeywordHashNode(9...18)( [AssocNode(9...18)( SymbolNode(9...13)((9...10), (10...13), nil, "baz"), diff --git a/test/yarp/snapshots/whitequark/args_args_comma.txt b/test/yarp/snapshots/whitequark/args_args_comma.txt index ff53a58eca6a08..a6014eebc427f3 100644 --- a/test/yarp/snapshots/whitequark/args_args_comma.txt +++ b/test/yarp/snapshots/whitequark/args_args_comma.txt @@ -2,12 +2,12 @@ ProgramNode(0...9)( [], StatementsNode(0...9)( [CallNode(0...9)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...9), (3...4), ArgumentsNode(4...7)( - [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "bar")] + [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "bar")] ), (8...9), nil, diff --git a/test/yarp/snapshots/whitequark/args_args_star.txt b/test/yarp/snapshots/whitequark/args_args_star.txt index 52b2c4120287de..ed007cfa5afccd 100644 --- a/test/yarp/snapshots/whitequark/args_args_star.txt +++ b/test/yarp/snapshots/whitequark/args_args_star.txt @@ -7,7 +7,7 @@ ProgramNode(0...36)( (0...3), (3...4), ArgumentsNode(4...13)( - [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "foo"), + [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "foo"), SplatNode(9...13)( (9...10), CallNode(10...13)( @@ -18,7 +18,7 @@ ProgramNode(0...36)( nil, nil, nil, - 0, + 2, "bar" ) )] @@ -34,7 +34,7 @@ ProgramNode(0...36)( (16...19), (19...20), ArgumentsNode(20...35)( - [CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 0, "foo"), + [CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 2, "foo"), SplatNode(25...29)( (25...26), CallNode(26...29)( @@ -45,7 +45,7 @@ ProgramNode(0...36)( nil, nil, nil, - 0, + 2, "bar" ) ), @@ -58,7 +58,7 @@ ProgramNode(0...36)( nil, nil, nil, - 0, + 2, "baz" ), (31...32) diff --git a/test/yarp/snapshots/whitequark/args_assocs.txt b/test/yarp/snapshots/whitequark/args_assocs.txt index 8905c41d17c81b..8fa24ab4795964 100644 --- a/test/yarp/snapshots/whitequark/args_assocs.txt +++ b/test/yarp/snapshots/whitequark/args_assocs.txt @@ -42,7 +42,7 @@ ProgramNode(0...114)( nil, nil, nil, - 0, + 2, "baz" ), (31...32) @@ -59,7 +59,7 @@ ProgramNode(0...114)( (43...46), nil, ArgumentsNode(47...59)( - [CallNode(47...50)(nil, nil, (47...50), nil, nil, nil, nil, 0, "foo"), + [CallNode(47...50)(nil, nil, (47...50), nil, nil, nil, nil, 2, "foo"), KeywordHashNode(52...59)( [AssocNode(52...59)( SymbolNode(52...54)((52...53), (53...54), nil, "a"), diff --git a/test/yarp/snapshots/whitequark/args_assocs_comma.txt b/test/yarp/snapshots/whitequark/args_assocs_comma.txt index 0989a82c635f16..97de8d44ef9541 100644 --- a/test/yarp/snapshots/whitequark/args_assocs_comma.txt +++ b/test/yarp/snapshots/whitequark/args_assocs_comma.txt @@ -2,7 +2,7 @@ ProgramNode(0...15)( [], StatementsNode(0...15)( [CallNode(0...15)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...15), (3...4), diff --git a/test/yarp/snapshots/whitequark/args_assocs_legacy.txt b/test/yarp/snapshots/whitequark/args_assocs_legacy.txt index 8905c41d17c81b..8fa24ab4795964 100644 --- a/test/yarp/snapshots/whitequark/args_assocs_legacy.txt +++ b/test/yarp/snapshots/whitequark/args_assocs_legacy.txt @@ -42,7 +42,7 @@ ProgramNode(0...114)( nil, nil, nil, - 0, + 2, "baz" ), (31...32) @@ -59,7 +59,7 @@ ProgramNode(0...114)( (43...46), nil, ArgumentsNode(47...59)( - [CallNode(47...50)(nil, nil, (47...50), nil, nil, nil, nil, 0, "foo"), + [CallNode(47...50)(nil, nil, (47...50), nil, nil, nil, nil, 2, "foo"), KeywordHashNode(52...59)( [AssocNode(52...59)( SymbolNode(52...54)((52...53), (53...54), nil, "a"), diff --git a/test/yarp/snapshots/whitequark/args_block_pass.txt b/test/yarp/snapshots/whitequark/args_block_pass.txt index 548019ab2f6c96..50c51ba7b3cc56 100644 --- a/test/yarp/snapshots/whitequark/args_block_pass.txt +++ b/test/yarp/snapshots/whitequark/args_block_pass.txt @@ -8,7 +8,7 @@ ProgramNode(0...9)( (3...4), ArgumentsNode(4...8)( [BlockArgumentNode(4...8)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "bar"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "bar"), (4...5) )] ), diff --git a/test/yarp/snapshots/whitequark/args_cmd.txt b/test/yarp/snapshots/whitequark/args_cmd.txt index cbb8ec0769de46..9b0cfedb006b29 100644 --- a/test/yarp/snapshots/whitequark/args_cmd.txt +++ b/test/yarp/snapshots/whitequark/args_cmd.txt @@ -21,7 +21,7 @@ ProgramNode(0...10)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/args_star.txt b/test/yarp/snapshots/whitequark/args_star.txt index 160865108bd2f9..eaffafdd3d428f 100644 --- a/test/yarp/snapshots/whitequark/args_star.txt +++ b/test/yarp/snapshots/whitequark/args_star.txt @@ -9,7 +9,7 @@ ProgramNode(0...26)( ArgumentsNode(4...8)( [SplatNode(4...8)( (4...5), - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "bar") + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "bar") )] ), (8...9), @@ -33,7 +33,7 @@ ProgramNode(0...26)( nil, nil, nil, - 0, + 2, "bar" ) ), @@ -46,7 +46,7 @@ ProgramNode(0...26)( nil, nil, nil, - 0, + 2, "baz" ), (21...22) diff --git a/test/yarp/snapshots/whitequark/array_splat.txt b/test/yarp/snapshots/whitequark/array_splat.txt index a691e674053ba9..770e42e8143280 100644 --- a/test/yarp/snapshots/whitequark/array_splat.txt +++ b/test/yarp/snapshots/whitequark/array_splat.txt @@ -4,7 +4,7 @@ ProgramNode(0...31)( [ArrayNode(0...6)( [SplatNode(1...5)( (1...2), - CallNode(2...5)(nil, nil, (2...5), nil, nil, nil, nil, 0, "foo") + CallNode(2...5)(nil, nil, (2...5), nil, nil, nil, nil, 2, "foo") )], (0...1), (5...6) @@ -13,7 +13,7 @@ ProgramNode(0...31)( [IntegerNode(9...10)(), SplatNode(12...16)( (12...13), - CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo") + CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo") ), IntegerNode(18...19)()], (8...9), @@ -23,7 +23,7 @@ ProgramNode(0...31)( [IntegerNode(23...24)(), SplatNode(26...30)( (26...27), - CallNode(27...30)(nil, nil, (27...30), nil, nil, nil, nil, 0, "foo") + CallNode(27...30)(nil, nil, (27...30), nil, nil, nil, nil, 2, "foo") )], (22...23), (30...31) diff --git a/test/yarp/snapshots/whitequark/array_symbols_interp.txt b/test/yarp/snapshots/whitequark/array_symbols_interp.txt index 204ee1372d87cf..8488e7e9c233cb 100644 --- a/test/yarp/snapshots/whitequark/array_symbols_interp.txt +++ b/test/yarp/snapshots/whitequark/array_symbols_interp.txt @@ -16,7 +16,7 @@ ProgramNode(0...29)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -42,7 +42,7 @@ ProgramNode(0...29)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/array_words_interp.txt b/test/yarp/snapshots/whitequark/array_words_interp.txt index e90e20d5e2b4a9..e70dcc7a8908d2 100644 --- a/test/yarp/snapshots/whitequark/array_words_interp.txt +++ b/test/yarp/snapshots/whitequark/array_words_interp.txt @@ -16,7 +16,7 @@ ProgramNode(0...38)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -42,7 +42,7 @@ ProgramNode(0...38)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/asgn_mrhs.txt b/test/yarp/snapshots/whitequark/asgn_mrhs.txt index 947c8e4450d270..fddbc439e5ae05 100644 --- a/test/yarp/snapshots/whitequark/asgn_mrhs.txt +++ b/test/yarp/snapshots/whitequark/asgn_mrhs.txt @@ -4,9 +4,13 @@ ProgramNode(0...41)( [LocalVariableWriteNode(0...10)( :foo, 0, - SplatNode(6...10)( - (6...7), - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "bar") + ArrayNode(6...10)( + [SplatNode(6...10)( + (6...7), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "bar") + )], + nil, + nil ), (0...3), (4...5) @@ -15,7 +19,7 @@ ProgramNode(0...41)( :foo, 0, ArrayNode(18...24)( - [CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 0, "bar"), + [CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 2, "bar"), IntegerNode(23...24)()], nil, nil @@ -27,7 +31,7 @@ ProgramNode(0...41)( :foo, 0, ArrayNode(32...41)( - [CallNode(32...35)(nil, nil, (32...35), nil, nil, nil, nil, 0, "baz"), + [CallNode(32...35)(nil, nil, (32...35), nil, nil, nil, nil, 2, "baz"), SplatNode(37...41)( (37...38), CallNode(38...41)( @@ -38,7 +42,7 @@ ProgramNode(0...41)( nil, nil, nil, - 0, + 2, "bar" ) )], diff --git a/test/yarp/snapshots/whitequark/bang.txt b/test/yarp/snapshots/whitequark/bang.txt index 25f3da6f04e05e..65ea29dfd39010 100644 --- a/test/yarp/snapshots/whitequark/bang.txt +++ b/test/yarp/snapshots/whitequark/bang.txt @@ -2,7 +2,7 @@ ProgramNode(0...4)( [], StatementsNode(0...4)( [CallNode(0...4)( - CallNode(1...4)(nil, nil, (1...4), nil, nil, nil, nil, 0, "foo"), + CallNode(1...4)(nil, nil, (1...4), nil, nil, nil, nil, 2, "foo"), nil, (0...1), nil, diff --git a/test/yarp/snapshots/whitequark/bang_cmd.txt b/test/yarp/snapshots/whitequark/bang_cmd.txt index 3e5080cebd71ff..23921cc1b3400d 100644 --- a/test/yarp/snapshots/whitequark/bang_cmd.txt +++ b/test/yarp/snapshots/whitequark/bang_cmd.txt @@ -8,7 +8,7 @@ ProgramNode(0...6)( (1...2), nil, ArgumentsNode(3...6)( - [CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 0, "foo")] + [CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 2, "foo")] ), nil, nil, diff --git a/test/yarp/snapshots/whitequark/beginless_erange_after_newline.txt b/test/yarp/snapshots/whitequark/beginless_erange_after_newline.txt index 50383976f2b900..dbe6e585a28e36 100644 --- a/test/yarp/snapshots/whitequark/beginless_erange_after_newline.txt +++ b/test/yarp/snapshots/whitequark/beginless_erange_after_newline.txt @@ -1,7 +1,7 @@ ProgramNode(0...10)( [], StatementsNode(0...10)( - [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), RangeNode(4...10)(nil, IntegerNode(7...10)(), (4...7), 1)] ) ) diff --git a/test/yarp/snapshots/whitequark/beginless_irange_after_newline.txt b/test/yarp/snapshots/whitequark/beginless_irange_after_newline.txt index a49985c7626309..f784561012d3e0 100644 --- a/test/yarp/snapshots/whitequark/beginless_irange_after_newline.txt +++ b/test/yarp/snapshots/whitequark/beginless_irange_after_newline.txt @@ -1,7 +1,7 @@ ProgramNode(0...9)( [], StatementsNode(0...9)( - [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), RangeNode(4...9)(nil, IntegerNode(6...9)(), (4...6), 0)] ) ) diff --git a/test/yarp/snapshots/whitequark/break.txt b/test/yarp/snapshots/whitequark/break.txt index df24567c4da5e2..46d3b6a5703cf3 100644 --- a/test/yarp/snapshots/whitequark/break.txt +++ b/test/yarp/snapshots/whitequark/break.txt @@ -4,7 +4,7 @@ ProgramNode(0...37)( [BreakNode(0...5)(nil, (0...5)), BreakNode(7...16)( ArgumentsNode(13...16)( - [CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo")] + [CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo")] ), (7...12) ), @@ -26,7 +26,7 @@ ProgramNode(0...37)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/break_block.txt b/test/yarp/snapshots/whitequark/break_block.txt index 41e083f25fbbeb..ad81bcf1637c9e 100644 --- a/test/yarp/snapshots/whitequark/break_block.txt +++ b/test/yarp/snapshots/whitequark/break_block.txt @@ -17,7 +17,7 @@ ProgramNode(0...20)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/bug_452.txt b/test/yarp/snapshots/whitequark/bug_452.txt index 78fc5f28a219fa..31cf38cfc2e774 100644 --- a/test/yarp/snapshots/whitequark/bug_452.txt +++ b/test/yarp/snapshots/whitequark/bug_452.txt @@ -29,7 +29,7 @@ ProgramNode(0...37)( "td" ), CallNode(23...37)( - CallNode(23...25)(nil, nil, (23...25), nil, nil, nil, nil, 0, "td"), + CallNode(23...25)(nil, nil, (23...25), nil, nil, nil, nil, 2, "td"), (25...26), (26...29), nil, diff --git a/test/yarp/snapshots/whitequark/bug_cmdarg.txt b/test/yarp/snapshots/whitequark/bug_cmdarg.txt index bfce24878220ca..f953e561456ef8 100644 --- a/test/yarp/snapshots/whitequark/bug_cmdarg.txt +++ b/test/yarp/snapshots/whitequark/bug_cmdarg.txt @@ -34,7 +34,7 @@ ProgramNode(0...56)( nil, nil, nil, - 0, + 2, "dogs" )] ), diff --git a/test/yarp/snapshots/whitequark/bug_lambda_leakage.txt b/test/yarp/snapshots/whitequark/bug_lambda_leakage.txt index 4fac00cf3497ac..c59109d0a95c16 100644 --- a/test/yarp/snapshots/whitequark/bug_lambda_leakage.txt +++ b/test/yarp/snapshots/whitequark/bug_lambda_leakage.txt @@ -20,6 +20,6 @@ ProgramNode(0...19)( ), nil ), - CallNode(14...19)(nil, nil, (14...19), nil, nil, nil, nil, 0, "scope")] + CallNode(14...19)(nil, nil, (14...19), nil, nil, nil, nil, 2, "scope")] ) ) diff --git a/test/yarp/snapshots/whitequark/bug_while_not_parens_do.txt b/test/yarp/snapshots/whitequark/bug_while_not_parens_do.txt index 26c198608cea73..0f517f935c115f 100644 --- a/test/yarp/snapshots/whitequark/bug_while_not_parens_do.txt +++ b/test/yarp/snapshots/whitequark/bug_while_not_parens_do.txt @@ -18,7 +18,8 @@ ProgramNode(0...23)( 0, "!" ), - nil + nil, + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/case_cond.txt b/test/yarp/snapshots/whitequark/case_cond.txt index 4fbc69e3baf63f..207fbe9a48596f 100644 --- a/test/yarp/snapshots/whitequark/case_cond.txt +++ b/test/yarp/snapshots/whitequark/case_cond.txt @@ -13,7 +13,7 @@ ProgramNode(0...26)( nil, nil, nil, - 0, + 2, "foo" )], StatementsNode(16...21)( diff --git a/test/yarp/snapshots/whitequark/case_cond_else.txt b/test/yarp/snapshots/whitequark/case_cond_else.txt index c4a035f17835db..263c4d3a0812d3 100644 --- a/test/yarp/snapshots/whitequark/case_cond_else.txt +++ b/test/yarp/snapshots/whitequark/case_cond_else.txt @@ -13,7 +13,7 @@ ProgramNode(0...38)( nil, nil, nil, - 0, + 2, "foo" )], StatementsNode(16...21)( diff --git a/test/yarp/snapshots/whitequark/case_expr.txt b/test/yarp/snapshots/whitequark/case_expr.txt index 22763ee9fed2ed..8b01d8f81a5e22 100644 --- a/test/yarp/snapshots/whitequark/case_expr.txt +++ b/test/yarp/snapshots/whitequark/case_expr.txt @@ -2,7 +2,7 @@ ProgramNode(0...30)( [], StatementsNode(0...30)( [CaseNode(0...30)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), [WhenNode(10...25)( (10...14), [StringNode(15...20)((15...16), (16...19), (19...20), "bar")], @@ -15,7 +15,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "bar" )] ) diff --git a/test/yarp/snapshots/whitequark/case_expr_else.txt b/test/yarp/snapshots/whitequark/case_expr_else.txt index 9782ba04cbb65b..79356e6cf3990b 100644 --- a/test/yarp/snapshots/whitequark/case_expr_else.txt +++ b/test/yarp/snapshots/whitequark/case_expr_else.txt @@ -2,7 +2,7 @@ ProgramNode(0...40)( [], StatementsNode(0...40)( [CaseNode(0...40)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), [WhenNode(10...25)( (10...14), [StringNode(15...20)((15...16), (16...19), (19...20), "bar")], @@ -15,7 +15,7 @@ ProgramNode(0...40)( nil, nil, nil, - 0, + 2, "bar" )] ) @@ -31,7 +31,7 @@ ProgramNode(0...40)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/whitequark/class_definition_in_while_cond.txt b/test/yarp/snapshots/whitequark/class_definition_in_while_cond.txt index 95b3caf5c703c5..a7bee91d90074b 100644 --- a/test/yarp/snapshots/whitequark/class_definition_in_while_cond.txt +++ b/test/yarp/snapshots/whitequark/class_definition_in_while_cond.txt @@ -29,7 +29,8 @@ ProgramNode(0...197)( ), (37...40) ), - StatementsNode(42...47)([BreakNode(42...47)(nil, (42...47))]) + StatementsNode(42...47)([BreakNode(42...47)(nil, (42...47))]), + 0 ), WhileNode(54...102)( (54...59), @@ -53,7 +54,8 @@ ProgramNode(0...197)( ), (87...90) ), - StatementsNode(92...97)([BreakNode(92...97)(nil, (92...97))]) + StatementsNode(92...97)([BreakNode(92...97)(nil, (92...97))]), + 0 ), WhileNode(104...151)( (104...109), @@ -84,7 +86,8 @@ ProgramNode(0...197)( ), (136...139) ), - StatementsNode(141...146)([BreakNode(141...146)(nil, (141...146))]) + StatementsNode(141...146)([BreakNode(141...146)(nil, (141...146))]), + 0 ), WhileNode(153...197)( (153...158), @@ -109,7 +112,8 @@ ProgramNode(0...197)( ), (182...185) ), - StatementsNode(187...192)([BreakNode(187...192)(nil, (187...192))]) + StatementsNode(187...192)([BreakNode(187...192)(nil, (187...192))]), + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/comments_before_leading_dot__27.txt b/test/yarp/snapshots/whitequark/comments_before_leading_dot__27.txt index 08dc7c2f5cad9b..b01a481eca0a5d 100644 --- a/test/yarp/snapshots/whitequark/comments_before_leading_dot__27.txt +++ b/test/yarp/snapshots/whitequark/comments_before_leading_dot__27.txt @@ -2,7 +2,7 @@ ProgramNode(0...55)( [], StatementsNode(0...55)( [CallNode(0...13)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (8...10), (10...13), nil, @@ -13,7 +13,7 @@ ProgramNode(0...55)( "foo" ), CallNode(16...28)( - CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 0, "a"), + CallNode(16...17)(nil, nil, (16...17), nil, nil, nil, nil, 2, "a"), (24...25), (25...28), nil, @@ -24,7 +24,7 @@ ProgramNode(0...55)( "foo" ), CallNode(31...42)( - CallNode(31...32)(nil, nil, (31...32), nil, nil, nil, nil, 0, "a"), + CallNode(31...32)(nil, nil, (31...32), nil, nil, nil, nil, 2, "a"), (37...39), (39...42), nil, @@ -35,7 +35,7 @@ ProgramNode(0...55)( "foo" ), CallNode(45...55)( - CallNode(45...46)(nil, nil, (45...46), nil, nil, nil, nil, 0, "a"), + CallNode(45...46)(nil, nil, (45...46), nil, nil, nil, nil, 2, "a"), (51...52), (52...55), nil, diff --git a/test/yarp/snapshots/whitequark/cond_begin.txt b/test/yarp/snapshots/whitequark/cond_begin.txt index 0d378e24c959b9..e3e3650e484993 100644 --- a/test/yarp/snapshots/whitequark/cond_begin.txt +++ b/test/yarp/snapshots/whitequark/cond_begin.txt @@ -5,13 +5,13 @@ ProgramNode(0...18)( (0...2), ParenthesesNode(3...8)( StatementsNode(4...7)( - [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "bar")] + [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "bar")] ), (3...4), (7...8) ), StatementsNode(10...13)( - [CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 0, "foo")] + [CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 2, "foo")] ), nil, (15...18) diff --git a/test/yarp/snapshots/whitequark/cond_begin_masgn.txt b/test/yarp/snapshots/whitequark/cond_begin_masgn.txt index 17a0cd4141ac6b..10e2f5d8dc72dc 100644 --- a/test/yarp/snapshots/whitequark/cond_begin_masgn.txt +++ b/test/yarp/snapshots/whitequark/cond_begin_masgn.txt @@ -5,7 +5,7 @@ ProgramNode(0...25)( (0...2), ParenthesesNode(3...20)( StatementsNode(4...19)( - [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "bar"), + [CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "bar"), MultiWriteNode(9...19)( [LocalVariableWriteNode(9...10)(:a, 0, nil, (9...10), nil), LocalVariableWriteNode(12...13)(:b, 0, nil, (12...13), nil)], @@ -18,7 +18,7 @@ ProgramNode(0...25)( nil, nil, nil, - 0, + 2, "foo" ), nil, diff --git a/test/yarp/snapshots/whitequark/cond_eflipflop.txt b/test/yarp/snapshots/whitequark/cond_eflipflop.txt index 889d14d8f370f0..31ef52f1e95730 100644 --- a/test/yarp/snapshots/whitequark/cond_eflipflop.txt +++ b/test/yarp/snapshots/whitequark/cond_eflipflop.txt @@ -4,8 +4,8 @@ ProgramNode(0...31)( [CallNode(0...12)( ParenthesesNode(1...12)( StatementsNode(2...11)( - [RangeNode(2...11)( - CallNode(2...5)(nil, nil, (2...5), nil, nil, nil, nil, 0, "foo"), + [FlipFlopNode(2...11)( + CallNode(2...5)(nil, nil, (2...5), nil, nil, nil, nil, 2, "foo"), CallNode(8...11)( nil, nil, @@ -14,11 +14,11 @@ ProgramNode(0...31)( nil, nil, nil, - 0, + 2, "bar" ), (5...8), - 3 + 1 )] ), (1...2), @@ -35,11 +35,11 @@ ProgramNode(0...31)( ), IfNode(14...31)( (14...16), - RangeNode(17...26)( - CallNode(17...20)(nil, nil, (17...20), nil, nil, nil, nil, 0, "foo"), - CallNode(23...26)(nil, nil, (23...26), nil, nil, nil, nil, 0, "bar"), + FlipFlopNode(17...26)( + CallNode(17...20)(nil, nil, (17...20), nil, nil, nil, nil, 2, "foo"), + CallNode(23...26)(nil, nil, (23...26), nil, nil, nil, nil, 2, "bar"), (20...23), - 3 + 1 ), nil, nil, diff --git a/test/yarp/snapshots/whitequark/cond_iflipflop.txt b/test/yarp/snapshots/whitequark/cond_iflipflop.txt index 5dee6f321c2bb7..4d1d42ed82092d 100644 --- a/test/yarp/snapshots/whitequark/cond_iflipflop.txt +++ b/test/yarp/snapshots/whitequark/cond_iflipflop.txt @@ -4,8 +4,8 @@ ProgramNode(0...29)( [CallNode(0...11)( ParenthesesNode(1...11)( StatementsNode(2...10)( - [RangeNode(2...10)( - CallNode(2...5)(nil, nil, (2...5), nil, nil, nil, nil, 0, "foo"), + [FlipFlopNode(2...10)( + CallNode(2...5)(nil, nil, (2...5), nil, nil, nil, nil, 2, "foo"), CallNode(7...10)( nil, nil, @@ -14,11 +14,11 @@ ProgramNode(0...29)( nil, nil, nil, - 0, + 2, "bar" ), (5...7), - 2 + 0 )] ), (1...2), @@ -35,11 +35,11 @@ ProgramNode(0...29)( ), IfNode(13...29)( (13...15), - RangeNode(16...24)( - CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "foo"), - CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "bar"), + FlipFlopNode(16...24)( + CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "foo"), + CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "bar"), (19...21), - 2 + 0 ), nil, nil, diff --git a/test/yarp/snapshots/whitequark/dedenting_heredoc.txt b/test/yarp/snapshots/whitequark/dedenting_heredoc.txt index 8db35f722876e7..144b17bcd7b1d9 100644 --- a/test/yarp/snapshots/whitequark/dedenting_heredoc.txt +++ b/test/yarp/snapshots/whitequark/dedenting_heredoc.txt @@ -46,7 +46,7 @@ ProgramNode(0...327)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -304,7 +304,7 @@ ProgramNode(0...327)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/defined.txt b/test/yarp/snapshots/whitequark/defined.txt index 8dc2e5493ea5ff..12a30055939bca 100644 --- a/test/yarp/snapshots/whitequark/defined.txt +++ b/test/yarp/snapshots/whitequark/defined.txt @@ -9,13 +9,13 @@ ProgramNode(0...42)( ), DefinedNode(15...27)( nil, - CallNode(24...27)(nil, nil, (24...27), nil, nil, nil, nil, 0, "foo"), + CallNode(24...27)(nil, nil, (24...27), nil, nil, nil, nil, 2, "foo"), nil, (15...23) ), DefinedNode(29...42)( (37...38), - CallNode(38...41)(nil, nil, (38...41), nil, nil, nil, nil, 0, "foo"), + CallNode(38...41)(nil, nil, (38...41), nil, nil, nil, nil, 2, "foo"), (41...42), (29...37) )] diff --git a/test/yarp/snapshots/whitequark/defs.txt b/test/yarp/snapshots/whitequark/defs.txt index d27de42bf22e79..ef7d56edbb7893 100644 --- a/test/yarp/snapshots/whitequark/defs.txt +++ b/test/yarp/snapshots/whitequark/defs.txt @@ -4,7 +4,7 @@ ProgramNode(0...100)( [DefNode(0...18)( (10...13), ParenthesesNode(4...9)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), (4...5), (8...9) ), diff --git a/test/yarp/snapshots/whitequark/endless_comparison_method.txt b/test/yarp/snapshots/whitequark/endless_comparison_method.txt index 47f43e82351ded..fa83705659563d 100644 --- a/test/yarp/snapshots/whitequark/endless_comparison_method.txt +++ b/test/yarp/snapshots/whitequark/endless_comparison_method.txt @@ -22,7 +22,7 @@ ProgramNode(0...179)( nil, nil, nil, - 0, + 2, "do_something" )] ), @@ -55,7 +55,7 @@ ProgramNode(0...179)( nil, nil, nil, - 0, + 2, "do_something" )] ), @@ -88,7 +88,7 @@ ProgramNode(0...179)( nil, nil, nil, - 0, + 2, "do_something" )] ), @@ -121,7 +121,7 @@ ProgramNode(0...179)( nil, nil, nil, - 0, + 2, "do_something" )] ), @@ -154,7 +154,7 @@ ProgramNode(0...179)( nil, nil, nil, - 0, + 2, "do_something" )] ), @@ -187,7 +187,7 @@ ProgramNode(0...179)( nil, nil, nil, - 0, + 2, "do_something" )] ), diff --git a/test/yarp/snapshots/whitequark/endless_method.txt b/test/yarp/snapshots/whitequark/endless_method.txt index 24bd704d3c7640..a80e6b57db8414 100644 --- a/test/yarp/snapshots/whitequark/endless_method.txt +++ b/test/yarp/snapshots/whitequark/endless_method.txt @@ -49,7 +49,7 @@ ProgramNode(0...78)( ), DefNode(36...54)( (44...47), - CallNode(40...43)(nil, nil, (40...43), nil, nil, nil, nil, 0, "obj"), + CallNode(40...43)(nil, nil, (40...43), nil, nil, nil, nil, 2, "obj"), nil, StatementsNode(52...54)([IntegerNode(52...54)()]), [], @@ -62,7 +62,7 @@ ProgramNode(0...78)( ), DefNode(56...78)( (64...67), - CallNode(60...63)(nil, nil, (60...63), nil, nil, nil, nil, 0, "obj"), + CallNode(60...63)(nil, nil, (60...63), nil, nil, nil, nil, 2, "obj"), ParametersNode(68...69)( [RequiredParameterNode(68...69)(:x)], [], diff --git a/test/yarp/snapshots/whitequark/endless_method_command_syntax.txt b/test/yarp/snapshots/whitequark/endless_method_command_syntax.txt index 476b6f34f68c04..33c64edfed2456 100644 --- a/test/yarp/snapshots/whitequark/endless_method_command_syntax.txt +++ b/test/yarp/snapshots/whitequark/endless_method_command_syntax.txt @@ -90,7 +90,7 @@ ProgramNode(0...278)( ), DefNode(71...97)( (79...82), - CallNode(75...78)(nil, nil, (75...78), nil, nil, nil, nil, 0, "obj"), + CallNode(75...78)(nil, nil, (75...78), nil, nil, nil, nil, 2, "obj"), nil, StatementsNode(85...97)( [CallNode(85...97)( @@ -125,7 +125,7 @@ ProgramNode(0...278)( nil, nil, nil, - 0, + 2, "obj" ), nil, @@ -167,7 +167,7 @@ ProgramNode(0...278)( nil, nil, nil, - 0, + 2, "obj" ), ParametersNode(141...142)( diff --git a/test/yarp/snapshots/whitequark/ensure.txt b/test/yarp/snapshots/whitequark/ensure.txt index 2306cc754d204a..abc443a2bb2185 100644 --- a/test/yarp/snapshots/whitequark/ensure.txt +++ b/test/yarp/snapshots/whitequark/ensure.txt @@ -4,7 +4,7 @@ ProgramNode(0...29)( [BeginNode(0...29)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), nil, nil, @@ -19,7 +19,7 @@ ProgramNode(0...29)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/float.txt b/test/yarp/snapshots/whitequark/float.txt index 6ad50dfc58fd84..dfeeb286974b4f 100644 --- a/test/yarp/snapshots/whitequark/float.txt +++ b/test/yarp/snapshots/whitequark/float.txt @@ -1,17 +1,4 @@ ProgramNode(0...11)( [], - StatementsNode(0...11)( - [CallNode(0...5)( - FloatNode(1...5)(), - nil, - (0...1), - nil, - nil, - nil, - nil, - 0, - "-@" - ), - FloatNode(7...11)()] - ) + StatementsNode(0...11)([FloatNode(0...5)(), FloatNode(7...11)()]) ) diff --git a/test/yarp/snapshots/whitequark/for.txt b/test/yarp/snapshots/whitequark/for.txt index cb99b7854e3ff5..e62da36cd540fa 100644 --- a/test/yarp/snapshots/whitequark/for.txt +++ b/test/yarp/snapshots/whitequark/for.txt @@ -9,7 +9,7 @@ ProgramNode(0...48)( nil, nil ), - CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 0, "foo"), + CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 2, "foo"), StatementsNode(16...19)( [CallNode(16...19)( nil, @@ -36,7 +36,7 @@ ProgramNode(0...48)( nil, nil ), - CallNode(35...38)(nil, nil, (35...38), nil, nil, nil, nil, 0, "foo"), + CallNode(35...38)(nil, nil, (35...38), nil, nil, nil, nil, 2, "foo"), StatementsNode(40...43)( [CallNode(40...43)( nil, diff --git a/test/yarp/snapshots/whitequark/for_mlhs.txt b/test/yarp/snapshots/whitequark/for_mlhs.txt index 53e5f67750b753..07bdb0662a5b9f 100644 --- a/test/yarp/snapshots/whitequark/for_mlhs.txt +++ b/test/yarp/snapshots/whitequark/for_mlhs.txt @@ -10,7 +10,7 @@ ProgramNode(0...28)( nil, nil ), - CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "foo"), + CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "foo"), StatementsNode(17...23)( [CallNode(17...23)( nil, diff --git a/test/yarp/snapshots/whitequark/hash_kwsplat.txt b/test/yarp/snapshots/whitequark/hash_kwsplat.txt index ee338760826735..bb56b81800b047 100644 --- a/test/yarp/snapshots/whitequark/hash_kwsplat.txt +++ b/test/yarp/snapshots/whitequark/hash_kwsplat.txt @@ -9,7 +9,7 @@ ProgramNode(0...17)( nil ), AssocSplatNode(10...15)( - CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "bar"), + CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "bar"), (10...12) )], (16...17) diff --git a/test/yarp/snapshots/whitequark/hash_label_end.txt b/test/yarp/snapshots/whitequark/hash_label_end.txt index 7e208d4d84f3c4..b5d4273d5ba625 100644 --- a/test/yarp/snapshots/whitequark/hash_label_end.txt +++ b/test/yarp/snapshots/whitequark/hash_label_end.txt @@ -9,7 +9,7 @@ ProgramNode(0...50)( ArgumentsNode(2...11)( [IfNode(2...11)( nil, - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "a"), + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "a"), StatementsNode(6...9)( [StringNode(6...9)((6...7), (7...8), (8...9), "a")] ), diff --git a/test/yarp/snapshots/whitequark/if.txt b/test/yarp/snapshots/whitequark/if.txt index 4d830abafe0526..069eb07f25344a 100644 --- a/test/yarp/snapshots/whitequark/if.txt +++ b/test/yarp/snapshots/whitequark/if.txt @@ -3,18 +3,18 @@ ProgramNode(0...38)( StatementsNode(0...38)( [IfNode(0...20)( (0...2), - CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 0, "foo"), + CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 2, "foo"), StatementsNode(12...15)( - [CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "bar")] + [CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "bar")] ), nil, (17...20) ), IfNode(22...38)( (22...24), - CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 0, "foo"), + CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 2, "foo"), StatementsNode(30...33)( - [CallNode(30...33)(nil, nil, (30...33), nil, nil, nil, nil, 0, "bar")] + [CallNode(30...33)(nil, nil, (30...33), nil, nil, nil, nil, 2, "bar")] ), nil, (35...38) diff --git a/test/yarp/snapshots/whitequark/if_else.txt b/test/yarp/snapshots/whitequark/if_else.txt index 936195e8da909d..d8799a330c5284 100644 --- a/test/yarp/snapshots/whitequark/if_else.txt +++ b/test/yarp/snapshots/whitequark/if_else.txt @@ -3,9 +3,9 @@ ProgramNode(0...58)( StatementsNode(0...58)( [IfNode(0...30)( (0...2), - CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 0, "foo"), + CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 2, "foo"), StatementsNode(12...15)( - [CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "bar")] + [CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "bar")] ), ElseNode(17...30)( (17...21), @@ -18,7 +18,7 @@ ProgramNode(0...58)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -28,9 +28,9 @@ ProgramNode(0...58)( ), IfNode(32...58)( (32...34), - CallNode(35...38)(nil, nil, (35...38), nil, nil, nil, nil, 0, "foo"), + CallNode(35...38)(nil, nil, (35...38), nil, nil, nil, nil, 2, "foo"), StatementsNode(40...43)( - [CallNode(40...43)(nil, nil, (40...43), nil, nil, nil, nil, 0, "bar")] + [CallNode(40...43)(nil, nil, (40...43), nil, nil, nil, nil, 2, "bar")] ), ElseNode(45...58)( (45...49), @@ -43,7 +43,7 @@ ProgramNode(0...58)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/whitequark/if_elsif.txt b/test/yarp/snapshots/whitequark/if_elsif.txt index 35add805657a79..953d565bf62898 100644 --- a/test/yarp/snapshots/whitequark/if_elsif.txt +++ b/test/yarp/snapshots/whitequark/if_elsif.txt @@ -3,13 +3,13 @@ ProgramNode(0...38)( StatementsNode(0...38)( [IfNode(0...38)( (0...2), - CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 0, "foo"), + CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 2, "foo"), StatementsNode(8...11)( - [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 0, "bar")] + [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 2, "bar")] ), IfNode(13...38)( (13...18), - CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 0, "baz"), + CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 2, "baz"), StatementsNode(24...25)([IntegerNode(24...25)()]), ElseNode(27...38)( (27...31), diff --git a/test/yarp/snapshots/whitequark/if_masgn__24.txt b/test/yarp/snapshots/whitequark/if_masgn__24.txt index 59b556f604636b..94e63ac4f7ff99 100644 --- a/test/yarp/snapshots/whitequark/if_masgn__24.txt +++ b/test/yarp/snapshots/whitequark/if_masgn__24.txt @@ -17,7 +17,7 @@ ProgramNode(0...20)( nil, nil, nil, - 0, + 2, "foo" ), nil, diff --git a/test/yarp/snapshots/whitequark/if_mod.txt b/test/yarp/snapshots/whitequark/if_mod.txt index 5325b8660a77f4..9a6575b5d1d9b2 100644 --- a/test/yarp/snapshots/whitequark/if_mod.txt +++ b/test/yarp/snapshots/whitequark/if_mod.txt @@ -3,9 +3,9 @@ ProgramNode(0...10)( StatementsNode(0...10)( [IfNode(0...10)( (4...6), - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "foo"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "foo"), StatementsNode(0...3)( - [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "bar")] + [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "bar")] ), nil, nil diff --git a/test/yarp/snapshots/whitequark/if_nl_then.txt b/test/yarp/snapshots/whitequark/if_nl_then.txt index 0dae26ffdf42be..db1b5231ef21fc 100644 --- a/test/yarp/snapshots/whitequark/if_nl_then.txt +++ b/test/yarp/snapshots/whitequark/if_nl_then.txt @@ -3,9 +3,9 @@ ProgramNode(0...19)( StatementsNode(0...19)( [IfNode(0...19)( (0...2), - CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 0, "foo"), + CallNode(3...6)(nil, nil, (3...6), nil, nil, nil, nil, 2, "foo"), StatementsNode(12...15)( - [CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "bar")] + [CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "bar")] ), nil, (16...19) diff --git a/test/yarp/snapshots/whitequark/if_while_after_class__since_32.txt b/test/yarp/snapshots/whitequark/if_while_after_class__since_32.txt index afa047c4f867e5..77f264878d5c08 100644 --- a/test/yarp/snapshots/whitequark/if_while_after_class__since_32.txt +++ b/test/yarp/snapshots/whitequark/if_while_after_class__since_32.txt @@ -32,7 +32,8 @@ ProgramNode(0...178)( ArgumentsNode(64...70)([ConstantReadNode(64...70)()]), (58...63) )] - ) + ), + 0 ), ConstantReadNode(76...82)(), (74...76) @@ -71,7 +72,8 @@ ProgramNode(0...178)( ArgumentsNode(155...161)([ConstantReadNode(155...161)()]), (149...154) )] - ) + ), + 0 ), ConstantReadNode(167...173)(), (165...167) diff --git a/test/yarp/snapshots/whitequark/int.txt b/test/yarp/snapshots/whitequark/int.txt index c388070c417a9a..a99820ad33b395 100644 --- a/test/yarp/snapshots/whitequark/int.txt +++ b/test/yarp/snapshots/whitequark/int.txt @@ -1,18 +1,6 @@ ProgramNode(0...12)( [], StatementsNode(0...12)( - [IntegerNode(0...3)(), - CallNode(5...8)( - IntegerNode(6...8)(), - nil, - (5...6), - nil, - nil, - nil, - nil, - 0, - "-@" - ), - IntegerNode(10...12)()] + [IntegerNode(0...3)(), IntegerNode(5...8)(), IntegerNode(10...12)()] ) ) diff --git a/test/yarp/snapshots/whitequark/interp_digit_var.txt b/test/yarp/snapshots/whitequark/interp_digit_var.txt index 0cf76b470b0bfe..283ebb19f2ff9f 100644 --- a/test/yarp/snapshots/whitequark/interp_digit_var.txt +++ b/test/yarp/snapshots/whitequark/interp_digit_var.txt @@ -83,16 +83,8 @@ ProgramNode(1...444)( "\#@@1", 0 ), - InterpolatedSymbolNode(268...274)( - (268...270), - [StringNode(270...273)(nil, (270...273), nil, "\#@1")], - (273...274) - ), - InterpolatedSymbolNode(277...284)( - (277...279), - [StringNode(279...283)(nil, (279...283), nil, "\#@@1")], - (283...284) - ), + SymbolNode(268...274)(nil, (270...273), nil, "\#@1"), + SymbolNode(277...284)(nil, (279...283), nil, "\#@@1"), SymbolNode(287...293)((287...289), (289...292), (292...293), "\#@1"), SymbolNode(296...303)((296...298), (298...302), (302...303), "\#@@1"), XStringNode(306...311)((306...307), (307...310), (310...311), "\#@1"), diff --git a/test/yarp/snapshots/whitequark/lparenarg_after_lvar__since_25.txt b/test/yarp/snapshots/whitequark/lparenarg_after_lvar__since_25.txt index c55c1d3c8a8bf0..027c04f09279cf 100644 --- a/test/yarp/snapshots/whitequark/lparenarg_after_lvar__since_25.txt +++ b/test/yarp/snapshots/whitequark/lparenarg_after_lvar__since_25.txt @@ -9,19 +9,7 @@ ProgramNode(0...31)( ArgumentsNode(4...14)( [CallNode(4...14)( ParenthesesNode(4...10)( - StatementsNode(5...9)( - [CallNode(5...9)( - FloatNode(6...9)(), - nil, - (5...6), - nil, - nil, - nil, - nil, - 0, - "-@" - )] - ), + StatementsNode(5...9)([FloatNode(5...9)()]), (4...5), (9...10) ), @@ -48,19 +36,7 @@ ProgramNode(0...31)( ArgumentsNode(21...31)( [CallNode(21...31)( ParenthesesNode(21...27)( - StatementsNode(22...26)( - [CallNode(22...26)( - FloatNode(23...26)(), - nil, - (22...23), - nil, - nil, - nil, - nil, - 0, - "-@" - )] - ), + StatementsNode(22...26)([FloatNode(22...26)()]), (21...22), (26...27) ), diff --git a/test/yarp/snapshots/whitequark/lvar.txt b/test/yarp/snapshots/whitequark/lvar.txt index fc27a87f8490dd..24f27ad073dbab 100644 --- a/test/yarp/snapshots/whitequark/lvar.txt +++ b/test/yarp/snapshots/whitequark/lvar.txt @@ -1,6 +1,6 @@ ProgramNode(0...3)( [], StatementsNode(0...3)( - [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo")] + [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo")] ) ) diff --git a/test/yarp/snapshots/whitequark/masgn_nested.txt b/test/yarp/snapshots/whitequark/masgn_nested.txt index 6321eaa74a13bc..98f1c094d00e70 100644 --- a/test/yarp/snapshots/whitequark/masgn_nested.txt +++ b/test/yarp/snapshots/whitequark/masgn_nested.txt @@ -11,7 +11,7 @@ ProgramNode(2...30)( (5...6) )], (8...9), - CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 0, "foo"), + CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 2, "foo"), (0...1), (6...7) ), @@ -26,7 +26,7 @@ ProgramNode(2...30)( (23...24) )], (25...26), - CallNode(27...30)(nil, nil, (27...30), nil, nil, nil, nil, 0, "foo"), + CallNode(27...30)(nil, nil, (27...30), nil, nil, nil, nil, 2, "foo"), nil, nil )] diff --git a/test/yarp/snapshots/whitequark/masgn_splat.txt b/test/yarp/snapshots/whitequark/masgn_splat.txt index a20c9a19190e43..635e1ae6fdd25b 100644 --- a/test/yarp/snapshots/whitequark/masgn_splat.txt +++ b/test/yarp/snapshots/whitequark/masgn_splat.txt @@ -4,7 +4,7 @@ ProgramNode(0...139)( [MultiWriteNode(0...7)( [SplatNode(0...1)((0...1), nil)], (2...3), - CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "bar"), + CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "bar"), nil, nil ), @@ -19,7 +19,7 @@ ProgramNode(0...139)( LocalVariableWriteNode(12...13)(:c, 0, nil, (12...13), nil), LocalVariableWriteNode(15...16)(:d, 0, nil, (15...16), nil)], (17...18), - CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 0, "bar"), + CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 2, "bar"), nil, nil ), @@ -29,7 +29,7 @@ ProgramNode(0...139)( LocalVariableWriteNode(25...26)(:b, 0, nil, (25...26), nil) )], (27...28), - CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 0, "bar"), + CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 2, "bar"), nil, nil ), @@ -46,7 +46,7 @@ ProgramNode(0...139)( ), LocalVariableWriteNode(38...39)(:c, 0, nil, (38...39), nil)], (40...41), - CallNode(42...45)(nil, nil, (42...45), nil, nil, nil, nil, 0, "bar"), + CallNode(42...45)(nil, nil, (42...45), nil, nil, nil, nil, 2, "bar"), nil, nil ), @@ -54,9 +54,23 @@ ProgramNode(0...139)( [InstanceVariableWriteNode(47...51)((47...51), nil, nil), ClassVariableWriteNode(53...58)((53...58), nil, nil)], (59...60), - SplatNode(61...65)( - (61...62), - CallNode(62...65)(nil, nil, (62...65), nil, nil, nil, nil, 0, "foo") + ArrayNode(61...65)( + [SplatNode(61...65)( + (61...62), + CallNode(62...65)( + nil, + nil, + (62...65), + nil, + nil, + nil, + nil, + 2, + "foo" + ) + )], + nil, + nil ), nil, nil @@ -65,7 +79,7 @@ ProgramNode(0...139)( [LocalVariableWriteNode(67...68)(:a, 0, nil, (67...68), nil), SplatNode(70...71)((70...71), nil)], (72...73), - CallNode(74...77)(nil, nil, (74...77), nil, nil, nil, nil, 0, "bar"), + CallNode(74...77)(nil, nil, (74...77), nil, nil, nil, nil, 2, "bar"), nil, nil ), @@ -74,7 +88,7 @@ ProgramNode(0...139)( SplatNode(82...83)((82...83), nil), LocalVariableWriteNode(85...86)(:c, 0, nil, (85...86), nil)], (87...88), - CallNode(89...92)(nil, nil, (89...92), nil, nil, nil, nil, 0, "bar"), + CallNode(89...92)(nil, nil, (89...92), nil, nil, nil, nil, 2, "bar"), nil, nil ), @@ -93,7 +107,7 @@ ProgramNode(0...139)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -115,7 +129,7 @@ ProgramNode(0...139)( nil, nil, nil, - 0, + 2, "bar" ), nil, @@ -136,7 +150,7 @@ ProgramNode(0...139)( nil, nil, nil, - 0, + 2, "foo" ) ), @@ -148,7 +162,7 @@ ProgramNode(0...139)( nil, nil, nil, - 0, + 2, "bar" )], nil, diff --git a/test/yarp/snapshots/whitequark/method_definition_in_while_cond.txt b/test/yarp/snapshots/whitequark/method_definition_in_while_cond.txt index bf615a18e84643..3b67815c7b8647 100644 --- a/test/yarp/snapshots/whitequark/method_definition_in_while_cond.txt +++ b/test/yarp/snapshots/whitequark/method_definition_in_while_cond.txt @@ -39,7 +39,8 @@ ProgramNode(0...190)( nil, (30...33) ), - StatementsNode(35...40)([BreakNode(35...40)(nil, (35...40))]) + StatementsNode(35...40)([BreakNode(35...40)(nil, (35...40))]), + 0 ), WhileNode(47...89)( (47...52), @@ -68,7 +69,8 @@ ProgramNode(0...190)( nil, (74...77) ), - StatementsNode(79...84)([BreakNode(79...84)(nil, (79...84))]) + StatementsNode(79...84)([BreakNode(79...84)(nil, (79...84))]), + 0 ), WhileNode(91...141)( (91...96), @@ -108,7 +110,8 @@ ProgramNode(0...190)( nil, (126...129) ), - StatementsNode(131...136)([BreakNode(131...136)(nil, (131...136))]) + StatementsNode(131...136)([BreakNode(131...136)(nil, (131...136))]), + 0 ), WhileNode(143...190)( (143...148), @@ -137,7 +140,8 @@ ProgramNode(0...190)( nil, (175...178) ), - StatementsNode(180...185)([BreakNode(180...185)(nil, (180...185))]) + StatementsNode(180...185)([BreakNode(180...185)(nil, (180...185))]), + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/newline_in_hash_argument.txt b/test/yarp/snapshots/whitequark/newline_in_hash_argument.txt index e2b0456381611e..fad1c85494822b 100644 --- a/test/yarp/snapshots/whitequark/newline_in_hash_argument.txt +++ b/test/yarp/snapshots/whitequark/newline_in_hash_argument.txt @@ -2,7 +2,7 @@ ProgramNode(0...74)( [:a, :b], StatementsNode(0...74)( [CaseNode(0...40)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), [InNode(9...21)( HashPatternNode(12...14)( nil, @@ -44,7 +44,7 @@ ProgramNode(0...74)( (37...40) ), CallNode(42...58)( - CallNode(42...45)(nil, nil, (42...45), nil, nil, nil, nil, 0, "obj"), + CallNode(42...45)(nil, nil, (42...45), nil, nil, nil, nil, 2, "obj"), (45...46), (46...49), nil, @@ -63,7 +63,7 @@ ProgramNode(0...74)( "set" ), CallNode(60...74)( - CallNode(60...63)(nil, nil, (60...63), nil, nil, nil, nil, 0, "obj"), + CallNode(60...63)(nil, nil, (60...63), nil, nil, nil, nil, 2, "obj"), (63...64), (64...67), nil, diff --git a/test/yarp/snapshots/whitequark/next.txt b/test/yarp/snapshots/whitequark/next.txt index 06997e7d1afa55..07dbb690dac91d 100644 --- a/test/yarp/snapshots/whitequark/next.txt +++ b/test/yarp/snapshots/whitequark/next.txt @@ -4,7 +4,7 @@ ProgramNode(0...33)( [NextNode(0...4)(nil, (0...4)), NextNode(6...14)( ArgumentsNode(11...14)( - [CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "foo")] + [CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "foo")] ), (6...10) ), @@ -26,7 +26,7 @@ ProgramNode(0...33)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/next_block.txt b/test/yarp/snapshots/whitequark/next_block.txt index 70f102b417484d..20cbe0d837bafa 100644 --- a/test/yarp/snapshots/whitequark/next_block.txt +++ b/test/yarp/snapshots/whitequark/next_block.txt @@ -17,7 +17,7 @@ ProgramNode(0...19)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/not.txt b/test/yarp/snapshots/whitequark/not.txt index e80943ad153753..1dc7b381cd397e 100644 --- a/test/yarp/snapshots/whitequark/not.txt +++ b/test/yarp/snapshots/whitequark/not.txt @@ -2,7 +2,7 @@ ProgramNode(0...24)( [], StatementsNode(0...24)( [CallNode(0...7)( - CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 0, "foo"), + CallNode(4...7)(nil, nil, (4...7), nil, nil, nil, nil, 2, "foo"), nil, (0...3), nil, @@ -24,7 +24,7 @@ ProgramNode(0...24)( "!" ), CallNode(16...24)( - CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 0, "foo"), + CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 2, "foo"), nil, (16...19), (19...20), diff --git a/test/yarp/snapshots/whitequark/not_cmd.txt b/test/yarp/snapshots/whitequark/not_cmd.txt index b361e5b61c9449..ff2acd00f5fe49 100644 --- a/test/yarp/snapshots/whitequark/not_cmd.txt +++ b/test/yarp/snapshots/whitequark/not_cmd.txt @@ -8,7 +8,7 @@ ProgramNode(0...9)( (4...5), nil, ArgumentsNode(6...9)( - [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "foo")] + [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "foo")] ), nil, nil, diff --git a/test/yarp/snapshots/whitequark/not_masgn__24.txt b/test/yarp/snapshots/whitequark/not_masgn__24.txt index 6880ed756181be..badac67e44fb05 100644 --- a/test/yarp/snapshots/whitequark/not_masgn__24.txt +++ b/test/yarp/snapshots/whitequark/not_masgn__24.txt @@ -16,7 +16,7 @@ ProgramNode(0...13)( nil, nil, nil, - 0, + 2, "foo" ), nil, diff --git a/test/yarp/snapshots/whitequark/numbered_args_after_27.txt b/test/yarp/snapshots/whitequark/numbered_args_after_27.txt index c2cf4217e3a53f..45decfc3b708e5 100644 --- a/test/yarp/snapshots/whitequark/numbered_args_after_27.txt +++ b/test/yarp/snapshots/whitequark/numbered_args_after_27.txt @@ -7,7 +7,7 @@ ProgramNode(0...65)( nil, StatementsNode(6...13)( [CallNode(6...13)( - CallNode(6...8)(nil, nil, (6...8), nil, nil, nil, nil, 0, "_1"), + CallNode(6...8)(nil, nil, (6...8), nil, nil, nil, nil, 2, "_1"), nil, (9...10), nil, @@ -20,7 +20,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "_9" )] ), @@ -45,7 +45,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "_1" ), nil, @@ -60,7 +60,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "_9" )] ), @@ -91,7 +91,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "_1" ), nil, @@ -106,7 +106,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "_9" )] ), @@ -142,7 +142,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "_1" ), nil, @@ -157,7 +157,7 @@ ProgramNode(0...65)( nil, nil, nil, - 0, + 2, "_9" )] ), diff --git a/test/yarp/snapshots/whitequark/numparam_outside_block.txt b/test/yarp/snapshots/whitequark/numparam_outside_block.txt index f99094a3a61123..99cb79b9e2980b 100644 --- a/test/yarp/snapshots/whitequark/numparam_outside_block.txt +++ b/test/yarp/snapshots/whitequark/numparam_outside_block.txt @@ -1,14 +1,14 @@ ProgramNode(0...83)( [], StatementsNode(0...83)( - [CallNode(0...2)(nil, nil, (0...2), nil, nil, nil, nil, 0, "_1"), + [CallNode(0...2)(nil, nil, (0...2), nil, nil, nil, nil, 2, "_1"), SingletonClassNode(4...25)( [], (4...9), (10...12), - CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo"), + CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo"), StatementsNode(18...20)( - [CallNode(18...20)(nil, nil, (18...20), nil, nil, nil, nil, 0, "_1")] + [CallNode(18...20)(nil, nil, (18...20), nil, nil, nil, nil, 2, "_1")] ), (22...25) ), @@ -19,7 +19,7 @@ ProgramNode(0...83)( nil, nil, StatementsNode(36...38)( - [CallNode(36...38)(nil, nil, (36...38), nil, nil, nil, nil, 0, "_1")] + [CallNode(36...38)(nil, nil, (36...38), nil, nil, nil, nil, 2, "_1")] ), (40...43) ), @@ -28,7 +28,7 @@ ProgramNode(0...83)( SelfNode(49...53)(), nil, StatementsNode(57...59)( - [CallNode(57...59)(nil, nil, (57...59), nil, nil, nil, nil, 0, "_1")] + [CallNode(57...59)(nil, nil, (57...59), nil, nil, nil, nil, 2, "_1")] ), [], (45...48), @@ -43,7 +43,7 @@ ProgramNode(0...83)( (66...72), ConstantReadNode(73...74)(), StatementsNode(76...78)( - [CallNode(76...78)(nil, nil, (76...78), nil, nil, nil, nil, 0, "_1")] + [CallNode(76...78)(nil, nil, (76...78), nil, nil, nil, nil, 2, "_1")] ), (80...83) )] diff --git a/test/yarp/snapshots/whitequark/op_asgn.txt b/test/yarp/snapshots/whitequark/op_asgn.txt index cb4b4a662f077a..c0a4e0471fa30b 100644 --- a/test/yarp/snapshots/whitequark/op_asgn.txt +++ b/test/yarp/snapshots/whitequark/op_asgn.txt @@ -3,7 +3,7 @@ ProgramNode(0...35)( StatementsNode(0...35)( [CallOperatorWriteNode(0...10)( CallNode(0...5)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...5), nil, @@ -19,7 +19,7 @@ ProgramNode(0...35)( ), CallOperatorWriteNode(12...22)( CallNode(12...17)( - CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "foo"), + CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "foo"), (15...16), (16...17), nil, @@ -35,7 +35,7 @@ ProgramNode(0...35)( ), CallOperatorWriteNode(24...35)( CallNode(24...30)( - CallNode(24...27)(nil, nil, (24...27), nil, nil, nil, nil, 0, "foo"), + CallNode(24...27)(nil, nil, (24...27), nil, nil, nil, nil, 2, "foo"), (27...29), (29...30), nil, diff --git a/test/yarp/snapshots/whitequark/op_asgn_cmd.txt b/test/yarp/snapshots/whitequark/op_asgn_cmd.txt index e18088fc6065f8..409aa26ee25c84 100644 --- a/test/yarp/snapshots/whitequark/op_asgn_cmd.txt +++ b/test/yarp/snapshots/whitequark/op_asgn_cmd.txt @@ -3,7 +3,7 @@ ProgramNode(0...64)( StatementsNode(0...64)( [CallOperatorWriteNode(0...14)( CallNode(0...5)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...5), nil, @@ -28,7 +28,7 @@ ProgramNode(0...64)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -41,7 +41,7 @@ ProgramNode(0...64)( ), CallOperatorWriteNode(16...30)( CallNode(16...21)( - CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "foo"), + CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "foo"), (19...20), (20...21), nil, @@ -66,7 +66,7 @@ ProgramNode(0...64)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -79,7 +79,7 @@ ProgramNode(0...64)( ), ConstantPathOperatorWriteNode(32...47)( ConstantPathNode(32...38)( - CallNode(32...35)(nil, nil, (32...35), nil, nil, nil, nil, 0, "foo"), + CallNode(32...35)(nil, nil, (32...35), nil, nil, nil, nil, 2, "foo"), ConstantReadNode(37...38)(), (35...37) ), @@ -98,7 +98,7 @@ ProgramNode(0...64)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -111,7 +111,7 @@ ProgramNode(0...64)( ), CallOperatorWriteNode(49...64)( CallNode(49...55)( - CallNode(49...52)(nil, nil, (49...52), nil, nil, nil, nil, 0, "foo"), + CallNode(49...52)(nil, nil, (49...52), nil, nil, nil, nil, 2, "foo"), (52...54), (54...55), nil, @@ -136,7 +136,7 @@ ProgramNode(0...64)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/op_asgn_index.txt b/test/yarp/snapshots/whitequark/op_asgn_index.txt index 8e0bc5f7dcfb9c..9b31652ca95192 100644 --- a/test/yarp/snapshots/whitequark/op_asgn_index.txt +++ b/test/yarp/snapshots/whitequark/op_asgn_index.txt @@ -3,7 +3,7 @@ ProgramNode(0...14)( StatementsNode(0...14)( [CallOperatorWriteNode(0...14)( CallNode(0...9)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...9), (3...4), diff --git a/test/yarp/snapshots/whitequark/op_asgn_index_cmd.txt b/test/yarp/snapshots/whitequark/op_asgn_index_cmd.txt index c2e27b43537f48..031532b83fe05f 100644 --- a/test/yarp/snapshots/whitequark/op_asgn_index_cmd.txt +++ b/test/yarp/snapshots/whitequark/op_asgn_index_cmd.txt @@ -3,7 +3,7 @@ ProgramNode(0...18)( StatementsNode(0...18)( [CallOperatorWriteNode(0...18)( CallNode(0...9)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...9), (3...4), @@ -28,7 +28,7 @@ ProgramNode(0...18)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/or.txt b/test/yarp/snapshots/whitequark/or.txt index 023490e6d30c11..fb1599df1da051 100644 --- a/test/yarp/snapshots/whitequark/or.txt +++ b/test/yarp/snapshots/whitequark/or.txt @@ -2,13 +2,13 @@ ProgramNode(0...22)( [], StatementsNode(0...22)( [OrNode(0...10)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "bar"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "bar"), (4...6) ), OrNode(12...22)( - CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "foo"), - CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 0, "bar"), + CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "foo"), + CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 2, "bar"), (16...18) )] ) diff --git a/test/yarp/snapshots/whitequark/or_asgn.txt b/test/yarp/snapshots/whitequark/or_asgn.txt index 21cede138fd772..35d7d76aa6e826 100644 --- a/test/yarp/snapshots/whitequark/or_asgn.txt +++ b/test/yarp/snapshots/whitequark/or_asgn.txt @@ -3,7 +3,7 @@ ProgramNode(0...28)( StatementsNode(0...28)( [CallOperatorOrWriteNode(0...11)( CallNode(0...5)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...5), nil, @@ -18,7 +18,7 @@ ProgramNode(0...28)( ), CallOperatorOrWriteNode(13...28)( CallNode(13...22)( - CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo"), + CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo"), nil, (16...22), (16...17), diff --git a/test/yarp/snapshots/whitequark/parser_bug_525.txt b/test/yarp/snapshots/whitequark/parser_bug_525.txt index e6fc74d2f6b1fc..0b5c2a5a44f77f 100644 --- a/test/yarp/snapshots/whitequark/parser_bug_525.txt +++ b/test/yarp/snapshots/whitequark/parser_bug_525.txt @@ -18,7 +18,7 @@ ProgramNode(0...32)( nil, nil, nil, - 0, + 2, "m2" ), (6...8) diff --git a/test/yarp/snapshots/whitequark/parser_bug_604.txt b/test/yarp/snapshots/whitequark/parser_bug_604.txt index 99f5a7a71a4c2b..ff732e34c57b67 100644 --- a/test/yarp/snapshots/whitequark/parser_bug_604.txt +++ b/test/yarp/snapshots/whitequark/parser_bug_604.txt @@ -8,12 +8,12 @@ ProgramNode(0...14)( nil, ArgumentsNode(2...7)( [CallNode(2...7)( - CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 0, "a"), + CallNode(2...3)(nil, nil, (2...3), nil, nil, nil, nil, 2, "a"), nil, (4...5), nil, ArgumentsNode(6...7)( - [CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 0, "b")] + [CallNode(6...7)(nil, nil, (6...7), nil, nil, nil, nil, 2, "b")] ), nil, nil, diff --git a/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt b/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt index 7228359d395e75..2802c084e43a78 100644 --- a/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt +++ b/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt @@ -47,11 +47,7 @@ ProgramNode(0...210)( "a\n" + "b", 0 ), - InterpolatedSymbolNode(123...130)( - (123...125), - [StringNode(125...129)(nil, (125...129), nil, "a\n" + "b")], - (129...130) - ), + SymbolNode(123...130)(nil, (125...129), nil, "a\n" + "b"), SymbolNode(132...139)((132...134), (134...138), (138...139), "a\n" + "b"), InterpolatedStringNode(141...161)( (141...150), diff --git a/test/yarp/snapshots/whitequark/regex_interp.txt b/test/yarp/snapshots/whitequark/regex_interp.txt index 2819567035f4b1..d314875cc4c25f 100644 --- a/test/yarp/snapshots/whitequark/regex_interp.txt +++ b/test/yarp/snapshots/whitequark/regex_interp.txt @@ -7,7 +7,7 @@ ProgramNode(0...14)( EmbeddedStatementsNode(4...10)( (4...6), StatementsNode(6...9)( - [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "bar")] + [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "bar")] ), (9...10) ), diff --git a/test/yarp/snapshots/whitequark/resbody_list.txt b/test/yarp/snapshots/whitequark/resbody_list.txt index 772a0a55f7a3c7..a3f80a0f22989d 100644 --- a/test/yarp/snapshots/whitequark/resbody_list.txt +++ b/test/yarp/snapshots/whitequark/resbody_list.txt @@ -4,7 +4,7 @@ ProgramNode(0...39)( [BeginNode(0...39)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...34)( (13...19), @@ -20,7 +20,7 @@ ProgramNode(0...39)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/resbody_list_mrhs.txt b/test/yarp/snapshots/whitequark/resbody_list_mrhs.txt index 29e4ae792b6e59..4969f5929ba1d2 100644 --- a/test/yarp/snapshots/whitequark/resbody_list_mrhs.txt +++ b/test/yarp/snapshots/whitequark/resbody_list_mrhs.txt @@ -4,7 +4,7 @@ ProgramNode(0...44)( [BeginNode(0...44)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...39)( (13...19), @@ -17,7 +17,7 @@ ProgramNode(0...44)( nil, nil, nil, - 0, + 2, "foo" )], nil, @@ -31,7 +31,7 @@ ProgramNode(0...44)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/resbody_list_var.txt b/test/yarp/snapshots/whitequark/resbody_list_var.txt index aca812cd011c02..7552914e005237 100644 --- a/test/yarp/snapshots/whitequark/resbody_list_var.txt +++ b/test/yarp/snapshots/whitequark/resbody_list_var.txt @@ -4,7 +4,7 @@ ProgramNode(0...39)( [BeginNode(0...39)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...34)( (13...19), @@ -16,7 +16,7 @@ ProgramNode(0...39)( nil, nil, nil, - 0, + 2, "foo" )], (24...26), @@ -30,7 +30,7 @@ ProgramNode(0...39)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/resbody_var.txt b/test/yarp/snapshots/whitequark/resbody_var.txt index 0acad7e908eab2..8e2d566c19642f 100644 --- a/test/yarp/snapshots/whitequark/resbody_var.txt +++ b/test/yarp/snapshots/whitequark/resbody_var.txt @@ -4,7 +4,7 @@ ProgramNode(0...73)( [BeginNode(0...36)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...31)( (13...19), @@ -20,7 +20,7 @@ ProgramNode(0...73)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -41,7 +41,7 @@ ProgramNode(0...73)( nil, nil, nil, - 0, + 2, "meth" )] ), @@ -59,7 +59,7 @@ ProgramNode(0...73)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/rescue.txt b/test/yarp/snapshots/whitequark/rescue.txt index ae9063361a06bc..6a14aa0803248c 100644 --- a/test/yarp/snapshots/whitequark/rescue.txt +++ b/test/yarp/snapshots/whitequark/rescue.txt @@ -4,7 +4,7 @@ ProgramNode(0...29)( [BeginNode(0...29)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...24)( (13...19), @@ -20,7 +20,7 @@ ProgramNode(0...29)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/rescue_else.txt b/test/yarp/snapshots/whitequark/rescue_else.txt index 4c4e9ab987e785..5359bb2a626b4d 100644 --- a/test/yarp/snapshots/whitequark/rescue_else.txt +++ b/test/yarp/snapshots/whitequark/rescue_else.txt @@ -4,7 +4,7 @@ ProgramNode(0...40)( [BeginNode(0...40)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...24)( (13...19), @@ -20,7 +20,7 @@ ProgramNode(0...40)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -37,7 +37,7 @@ ProgramNode(0...40)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/rescue_else_ensure.txt b/test/yarp/snapshots/whitequark/rescue_else_ensure.txt index 0d44b99b704116..89fc12478464a1 100644 --- a/test/yarp/snapshots/whitequark/rescue_else_ensure.txt +++ b/test/yarp/snapshots/whitequark/rescue_else_ensure.txt @@ -4,7 +4,7 @@ ProgramNode(0...51)( [BeginNode(0...51)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...24)( (13...19), @@ -20,7 +20,7 @@ ProgramNode(0...51)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -37,7 +37,7 @@ ProgramNode(0...51)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -54,7 +54,7 @@ ProgramNode(0...51)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/rescue_ensure.txt b/test/yarp/snapshots/whitequark/rescue_ensure.txt index 6f9b287c1c7e7b..719ed167fec916 100644 --- a/test/yarp/snapshots/whitequark/rescue_ensure.txt +++ b/test/yarp/snapshots/whitequark/rescue_ensure.txt @@ -4,7 +4,7 @@ ProgramNode(0...42)( [BeginNode(0...42)( (0...5), StatementsNode(7...11)( - [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth")] + [CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth")] ), RescueNode(13...24)( (13...19), @@ -20,7 +20,7 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -38,7 +38,7 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/rescue_mod.txt b/test/yarp/snapshots/whitequark/rescue_mod.txt index baae026bb845ea..e755977e7decfa 100644 --- a/test/yarp/snapshots/whitequark/rescue_mod.txt +++ b/test/yarp/snapshots/whitequark/rescue_mod.txt @@ -2,9 +2,9 @@ ProgramNode(0...15)( [], StatementsNode(0...15)( [RescueModifierNode(0...15)( - CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 0, "meth"), + CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 2, "meth"), (5...11), - CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 0, "bar") + CallNode(12...15)(nil, nil, (12...15), nil, nil, nil, nil, 2, "bar") )] ) ) diff --git a/test/yarp/snapshots/whitequark/rescue_mod_asgn.txt b/test/yarp/snapshots/whitequark/rescue_mod_asgn.txt index 39ddc02f3bbdc6..c0c1b20cef787c 100644 --- a/test/yarp/snapshots/whitequark/rescue_mod_asgn.txt +++ b/test/yarp/snapshots/whitequark/rescue_mod_asgn.txt @@ -5,9 +5,9 @@ ProgramNode(0...21)( :foo, 0, RescueModifierNode(6...21)( - CallNode(6...10)(nil, nil, (6...10), nil, nil, nil, nil, 0, "meth"), + CallNode(6...10)(nil, nil, (6...10), nil, nil, nil, nil, 2, "meth"), (11...17), - CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 0, "bar") + CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 2, "bar") ), (0...3), (4...5) diff --git a/test/yarp/snapshots/whitequark/rescue_mod_masgn.txt b/test/yarp/snapshots/whitequark/rescue_mod_masgn.txt index f027de1f737143..60464244f58dbc 100644 --- a/test/yarp/snapshots/whitequark/rescue_mod_masgn.txt +++ b/test/yarp/snapshots/whitequark/rescue_mod_masgn.txt @@ -6,7 +6,7 @@ ProgramNode(0...29)( LocalVariableWriteNode(5...8)(:bar, 0, nil, (5...8), nil)], (9...10), RescueModifierNode(11...29)( - CallNode(11...15)(nil, nil, (11...15), nil, nil, nil, nil, 0, "meth"), + CallNode(11...15)(nil, nil, (11...15), nil, nil, nil, nil, 2, "meth"), (16...22), ArrayNode(23...29)( [IntegerNode(24...25)(), IntegerNode(27...28)()], diff --git a/test/yarp/snapshots/whitequark/rescue_mod_op_assign.txt b/test/yarp/snapshots/whitequark/rescue_mod_op_assign.txt index 9f846f792e0267..051ead127c090d 100644 --- a/test/yarp/snapshots/whitequark/rescue_mod_op_assign.txt +++ b/test/yarp/snapshots/whitequark/rescue_mod_op_assign.txt @@ -5,9 +5,9 @@ ProgramNode(0...22)( (0...3), (4...6), RescueModifierNode(7...22)( - CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 0, "meth"), + CallNode(7...11)(nil, nil, (7...11), nil, nil, nil, nil, 2, "meth"), (12...18), - CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 0, "bar") + CallNode(19...22)(nil, nil, (19...22), nil, nil, nil, nil, 2, "bar") ), :foo, :+ diff --git a/test/yarp/snapshots/whitequark/rescue_without_begin_end.txt b/test/yarp/snapshots/whitequark/rescue_without_begin_end.txt index bc290f265b3160..038219dc1fc636 100644 --- a/test/yarp/snapshots/whitequark/rescue_without_begin_end.txt +++ b/test/yarp/snapshots/whitequark/rescue_without_begin_end.txt @@ -22,7 +22,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "foo" )] ), @@ -40,7 +40,7 @@ ProgramNode(0...30)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/return.txt b/test/yarp/snapshots/whitequark/return.txt index da8c8a6f0fba0c..0afc3de823e8ca 100644 --- a/test/yarp/snapshots/whitequark/return.txt +++ b/test/yarp/snapshots/whitequark/return.txt @@ -5,7 +5,7 @@ ProgramNode(0...41)( ReturnNode(8...18)( (8...14), ArgumentsNode(15...18)( - [CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 0, "foo")] + [CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 2, "foo")] ) ), ReturnNode(20...28)( @@ -27,7 +27,7 @@ ProgramNode(0...41)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/return_block.txt b/test/yarp/snapshots/whitequark/return_block.txt index 87b2028abe7a0f..60f24062954bc0 100644 --- a/test/yarp/snapshots/whitequark/return_block.txt +++ b/test/yarp/snapshots/whitequark/return_block.txt @@ -18,7 +18,7 @@ ProgramNode(0...21)( nil, nil, nil, - 0, + 2, "foo" )] ), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_11873.txt b/test/yarp/snapshots/whitequark/ruby_bug_11873.txt index fa2e919f6ea994..5c63deed0850b3 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_11873.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_11873.txt @@ -27,7 +27,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -75,7 +75,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -129,7 +129,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -183,7 +183,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -231,7 +231,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -285,7 +285,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -344,7 +344,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -398,7 +398,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -458,7 +458,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -518,7 +518,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -572,7 +572,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -632,7 +632,7 @@ ProgramNode(0...272)( nil, nil, nil, - 0, + 2, "d" )] ), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_11873_a.txt b/test/yarp/snapshots/whitequark/ruby_bug_11873_a.txt index 4cb06f16cd03b0..5cdffe39b18bcb 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_11873_a.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_11873_a.txt @@ -27,7 +27,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -75,7 +75,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -123,7 +123,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -171,7 +171,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -219,7 +219,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -267,7 +267,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -315,7 +315,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -363,7 +363,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -411,7 +411,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -459,7 +459,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -512,7 +512,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -566,7 +566,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -620,7 +620,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -674,7 +674,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -728,7 +728,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -782,7 +782,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -836,7 +836,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -890,7 +890,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -944,7 +944,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), @@ -998,7 +998,7 @@ ProgramNode(0...444)( nil, nil, nil, - 0, + 2, "d" )] ), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_11873_b.txt b/test/yarp/snapshots/whitequark/ruby_bug_11873_b.txt index b84ec0e5b1a8db..f1a840a8923abb 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_11873_b.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_11873_b.txt @@ -32,7 +32,7 @@ ProgramNode(0...25)( nil, nil, nil, - 0, + 2, "p" )] ), @@ -55,7 +55,7 @@ ProgramNode(0...25)( nil, nil, nil, - 0, + 2, "p" )] ), @@ -71,7 +71,7 @@ ProgramNode(0...25)( 0, "p" ), - CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 0, "tap")] + CallNode(15...18)(nil, nil, (15...18), nil, nil, nil, nil, 2, "tap")] ), nil, BlockNode(19...25)([], nil, nil, (19...21), (22...25)), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_12402.txt b/test/yarp/snapshots/whitequark/ruby_bug_12402.txt index f68c8dc46bec82..fb00d826a21a57 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_12402.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_12402.txt @@ -19,7 +19,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" ), (17...23), @@ -52,7 +52,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -85,7 +85,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" ), (75...81), @@ -118,7 +118,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -161,7 +161,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" ), (135...141), @@ -203,7 +203,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -245,7 +245,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" ), (198...204), @@ -287,7 +287,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -323,7 +323,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" ), (263...269), @@ -358,7 +358,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -399,7 +399,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" ), (329...335), @@ -441,7 +441,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -483,7 +483,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" ), (394...400), @@ -525,7 +525,7 @@ ProgramNode(0...437)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_12686.txt b/test/yarp/snapshots/whitequark/ruby_bug_12686.txt index 6e23f383551a11..f0ae6d107494fd 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_12686.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_12686.txt @@ -18,7 +18,7 @@ ProgramNode(0...16)( nil, nil, nil, - 0, + 2, "g" ), (5...11), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_13547.txt b/test/yarp/snapshots/whitequark/ruby_bug_13547.txt index 42592cfc6ad633..c0e5ccd927151e 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_13547.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_13547.txt @@ -2,7 +2,7 @@ ProgramNode(0...9)( [], StatementsNode(0...9)( [CallNode(0...9)( - CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 0, "meth"), + CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 2, "meth"), nil, (4...6), (4...5), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_14690.txt b/test/yarp/snapshots/whitequark/ruby_bug_14690.txt index 65a6cb57377f80..743cf8b7b6e1b7 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_14690.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_14690.txt @@ -26,7 +26,7 @@ ProgramNode(0...23)( nil, nil, nil, - 0, + 2, "a" )] ), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_15789.txt b/test/yarp/snapshots/whitequark/ruby_bug_15789.txt index 705992927f1aa4..331c1e5cd858ad 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_15789.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_15789.txt @@ -30,7 +30,7 @@ ProgramNode(0...41)( nil, nil, nil, - 0, + 2, "_1" )] ) @@ -84,7 +84,7 @@ ProgramNode(0...41)( nil, nil, nil, - 0, + 2, "_1" )] ) diff --git a/test/yarp/snapshots/whitequark/sclass.txt b/test/yarp/snapshots/whitequark/sclass.txt index 1f032b1cf0b9bc..a8beb303ebf774 100644 --- a/test/yarp/snapshots/whitequark/sclass.txt +++ b/test/yarp/snapshots/whitequark/sclass.txt @@ -5,7 +5,7 @@ ProgramNode(0...22)( [], (0...5), (6...8), - CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 0, "foo"), + CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 2, "foo"), StatementsNode(14...17)([NilNode(14...17)()]), (19...22) )] diff --git a/test/yarp/snapshots/whitequark/send_attr_asgn.txt b/test/yarp/snapshots/whitequark/send_attr_asgn.txt index a220143a977871..9d70f90f9a51f4 100644 --- a/test/yarp/snapshots/whitequark/send_attr_asgn.txt +++ b/test/yarp/snapshots/whitequark/send_attr_asgn.txt @@ -2,7 +2,7 @@ ProgramNode(0...44)( [], StatementsNode(0...44)( [CallNode(0...9)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...5), nil, @@ -13,7 +13,7 @@ ProgramNode(0...44)( "A=" ), CallNode(11...20)( - CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "foo"), + CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "foo"), (14...15), (15...16), nil, @@ -25,7 +25,7 @@ ProgramNode(0...44)( ), ConstantPathWriteNode(22...32)( ConstantPathNode(22...28)( - CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 0, "foo"), + CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 2, "foo"), ConstantReadNode(27...28)(), (25...27) ), @@ -33,7 +33,7 @@ ProgramNode(0...44)( IntegerNode(31...32)() ), CallNode(34...44)( - CallNode(34...37)(nil, nil, (34...37), nil, nil, nil, nil, 0, "foo"), + CallNode(34...37)(nil, nil, (34...37), nil, nil, nil, nil, 2, "foo"), (37...39), (39...40), nil, diff --git a/test/yarp/snapshots/whitequark/send_attr_asgn_conditional.txt b/test/yarp/snapshots/whitequark/send_attr_asgn_conditional.txt index fabbcb5ca70849..a48f189f41a122 100644 --- a/test/yarp/snapshots/whitequark/send_attr_asgn_conditional.txt +++ b/test/yarp/snapshots/whitequark/send_attr_asgn_conditional.txt @@ -2,7 +2,7 @@ ProgramNode(0...8)( [], StatementsNode(0...8)( [CallNode(0...8)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/whitequark/send_binary_op.txt b/test/yarp/snapshots/whitequark/send_binary_op.txt index c8f2682cf1e2cd..aadcb1fcb9dea3 100644 --- a/test/yarp/snapshots/whitequark/send_binary_op.txt +++ b/test/yarp/snapshots/whitequark/send_binary_op.txt @@ -2,7 +2,7 @@ ProgramNode(0...200)( [], StatementsNode(0...200)( [CallNode(0...8)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (4...6), nil, @@ -13,7 +13,7 @@ ProgramNode(0...200)( "!=" ), CallNode(10...18)( - CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 0, "foo"), + CallNode(10...13)(nil, nil, (10...13), nil, nil, nil, nil, 2, "foo"), nil, (14...16), nil, @@ -24,7 +24,7 @@ ProgramNode(0...200)( "!~" ), CallNode(20...27)( - CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 0, "foo"), + CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 2, "foo"), nil, (24...25), nil, @@ -35,7 +35,7 @@ ProgramNode(0...200)( "%" ), CallNode(29...36)( - CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 0, "foo"), + CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 2, "foo"), nil, (33...34), nil, @@ -46,7 +46,7 @@ ProgramNode(0...200)( "&" ), CallNode(38...45)( - CallNode(38...41)(nil, nil, (38...41), nil, nil, nil, nil, 0, "foo"), + CallNode(38...41)(nil, nil, (38...41), nil, nil, nil, nil, 2, "foo"), nil, (42...43), nil, @@ -57,7 +57,7 @@ ProgramNode(0...200)( "*" ), CallNode(47...55)( - CallNode(47...50)(nil, nil, (47...50), nil, nil, nil, nil, 0, "foo"), + CallNode(47...50)(nil, nil, (47...50), nil, nil, nil, nil, 2, "foo"), nil, (51...53), nil, @@ -68,7 +68,7 @@ ProgramNode(0...200)( "**" ), CallNode(57...64)( - CallNode(57...60)(nil, nil, (57...60), nil, nil, nil, nil, 0, "foo"), + CallNode(57...60)(nil, nil, (57...60), nil, nil, nil, nil, 2, "foo"), nil, (61...62), nil, @@ -79,7 +79,7 @@ ProgramNode(0...200)( "+" ), CallNode(66...73)( - CallNode(66...69)(nil, nil, (66...69), nil, nil, nil, nil, 0, "foo"), + CallNode(66...69)(nil, nil, (66...69), nil, nil, nil, nil, 2, "foo"), nil, (70...71), nil, @@ -90,7 +90,7 @@ ProgramNode(0...200)( "-" ), CallNode(75...82)( - CallNode(75...78)(nil, nil, (75...78), nil, nil, nil, nil, 0, "foo"), + CallNode(75...78)(nil, nil, (75...78), nil, nil, nil, nil, 2, "foo"), nil, (79...80), nil, @@ -101,7 +101,7 @@ ProgramNode(0...200)( "/" ), CallNode(84...91)( - CallNode(84...87)(nil, nil, (84...87), nil, nil, nil, nil, 0, "foo"), + CallNode(84...87)(nil, nil, (84...87), nil, nil, nil, nil, 2, "foo"), nil, (88...89), nil, @@ -112,7 +112,7 @@ ProgramNode(0...200)( "<" ), CallNode(93...101)( - CallNode(93...96)(nil, nil, (93...96), nil, nil, nil, nil, 0, "foo"), + CallNode(93...96)(nil, nil, (93...96), nil, nil, nil, nil, 2, "foo"), nil, (97...99), nil, @@ -131,7 +131,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -152,7 +152,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -173,7 +173,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -194,7 +194,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -215,7 +215,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -236,7 +236,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -257,7 +257,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -278,7 +278,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -299,7 +299,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, @@ -320,7 +320,7 @@ ProgramNode(0...200)( nil, nil, nil, - 0, + 2, "foo" ), nil, diff --git a/test/yarp/snapshots/whitequark/send_block_chain_cmd.txt b/test/yarp/snapshots/whitequark/send_block_chain_cmd.txt index 15e364b82950c4..c9d9a3662887eb 100644 --- a/test/yarp/snapshots/whitequark/send_block_chain_cmd.txt +++ b/test/yarp/snapshots/whitequark/send_block_chain_cmd.txt @@ -17,7 +17,7 @@ ProgramNode(0...173)( (14...17), nil, ArgumentsNode(18...21)( - [CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 0, "bar")] + [CallNode(18...21)(nil, nil, (18...21), nil, nil, nil, nil, 2, "bar")] ), nil, nil, @@ -40,7 +40,7 @@ ProgramNode(0...173)( (37...40), nil, ArgumentsNode(41...44)( - [CallNode(41...44)(nil, nil, (41...44), nil, nil, nil, nil, 0, "bar")] + [CallNode(41...44)(nil, nil, (41...44), nil, nil, nil, nil, 2, "bar")] ), nil, BlockNode(45...51)([], nil, nil, (45...47), (48...51)), @@ -84,7 +84,7 @@ ProgramNode(0...173)( (89...92), (92...93), ArgumentsNode(93...96)( - [CallNode(93...96)(nil, nil, (93...96), nil, nil, nil, nil, 0, "bar")] + [CallNode(93...96)(nil, nil, (93...96), nil, nil, nil, nil, 2, "bar")] ), (96...97), nil, @@ -115,7 +115,7 @@ ProgramNode(0...173)( nil, nil, nil, - 0, + 2, "bar" )] ), @@ -137,7 +137,7 @@ ProgramNode(0...173)( "meth" ), (139...141), - (145...148), + (141...144), nil, ArgumentsNode(145...148)( [CallNode(145...148)( @@ -148,14 +148,14 @@ ProgramNode(0...173)( nil, nil, nil, - 0, + 2, "bar" )] ), nil, nil, 0, - "bar" + "fun" ), CallNode(150...173)( CallNode(150...163)( @@ -170,7 +170,7 @@ ProgramNode(0...173)( "meth" ), (163...165), - (172...173), + (165...168), (168...169), ArgumentsNode(169...172)( [CallNode(169...172)( @@ -181,14 +181,14 @@ ProgramNode(0...173)( nil, nil, nil, - 0, + 2, "bar" )] ), (172...173), nil, 0, - ")" + "fun" )] ) ) diff --git a/test/yarp/snapshots/whitequark/send_block_conditional.txt b/test/yarp/snapshots/whitequark/send_block_conditional.txt index a25fb4ac4eb890..3ac7347f7ab21b 100644 --- a/test/yarp/snapshots/whitequark/send_block_conditional.txt +++ b/test/yarp/snapshots/whitequark/send_block_conditional.txt @@ -2,7 +2,7 @@ ProgramNode(0...11)( [], StatementsNode(0...11)( [CallNode(0...11)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...5), (5...8), nil, diff --git a/test/yarp/snapshots/whitequark/send_call.txt b/test/yarp/snapshots/whitequark/send_call.txt index 6c52bec0fe0b9f..4280323078034f 100644 --- a/test/yarp/snapshots/whitequark/send_call.txt +++ b/test/yarp/snapshots/whitequark/send_call.txt @@ -2,7 +2,7 @@ ProgramNode(0...17)( [], StatementsNode(0...17)( [CallNode(0...7)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (0...0), (4...5), @@ -13,7 +13,7 @@ ProgramNode(0...17)( "call" ), CallNode(9...17)( - CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 0, "foo"), + CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 2, "foo"), (12...14), (0...0), (14...15), diff --git a/test/yarp/snapshots/whitequark/send_conditional.txt b/test/yarp/snapshots/whitequark/send_conditional.txt index 1621715838b418..d170db0f559f59 100644 --- a/test/yarp/snapshots/whitequark/send_conditional.txt +++ b/test/yarp/snapshots/whitequark/send_conditional.txt @@ -2,7 +2,7 @@ ProgramNode(0...4)( [], StatementsNode(0...4)( [CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/whitequark/send_index.txt b/test/yarp/snapshots/whitequark/send_index.txt index f09270736f48eb..75f8c0ff876ec5 100644 --- a/test/yarp/snapshots/whitequark/send_index.txt +++ b/test/yarp/snapshots/whitequark/send_index.txt @@ -2,7 +2,7 @@ ProgramNode(0...9)( [], StatementsNode(0...9)( [CallNode(0...9)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...9), (3...4), diff --git a/test/yarp/snapshots/whitequark/send_index_asgn.txt b/test/yarp/snapshots/whitequark/send_index_asgn.txt index d6cfd22a29dfe8..d38af8fb52cadd 100644 --- a/test/yarp/snapshots/whitequark/send_index_asgn.txt +++ b/test/yarp/snapshots/whitequark/send_index_asgn.txt @@ -2,7 +2,7 @@ ProgramNode(0...13)( [], StatementsNode(0...13)( [CallNode(0...13)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...9), (3...4), diff --git a/test/yarp/snapshots/whitequark/send_index_asgn_legacy.txt b/test/yarp/snapshots/whitequark/send_index_asgn_legacy.txt index d6cfd22a29dfe8..d38af8fb52cadd 100644 --- a/test/yarp/snapshots/whitequark/send_index_asgn_legacy.txt +++ b/test/yarp/snapshots/whitequark/send_index_asgn_legacy.txt @@ -2,7 +2,7 @@ ProgramNode(0...13)( [], StatementsNode(0...13)( [CallNode(0...13)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...9), (3...4), diff --git a/test/yarp/snapshots/whitequark/send_index_cmd.txt b/test/yarp/snapshots/whitequark/send_index_cmd.txt index cf982040738fc5..38c69392b3d943 100644 --- a/test/yarp/snapshots/whitequark/send_index_cmd.txt +++ b/test/yarp/snapshots/whitequark/send_index_cmd.txt @@ -2,7 +2,7 @@ ProgramNode(0...10)( [], StatementsNode(0...10)( [CallNode(0...10)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...10), (3...4), @@ -21,7 +21,7 @@ ProgramNode(0...10)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/send_index_legacy.txt b/test/yarp/snapshots/whitequark/send_index_legacy.txt index f09270736f48eb..75f8c0ff876ec5 100644 --- a/test/yarp/snapshots/whitequark/send_index_legacy.txt +++ b/test/yarp/snapshots/whitequark/send_index_legacy.txt @@ -2,7 +2,7 @@ ProgramNode(0...9)( [], StatementsNode(0...9)( [CallNode(0...9)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), nil, (3...9), (3...4), diff --git a/test/yarp/snapshots/whitequark/send_op_asgn_conditional.txt b/test/yarp/snapshots/whitequark/send_op_asgn_conditional.txt index db30a2a0ee28d6..8403b1c7afb2e0 100644 --- a/test/yarp/snapshots/whitequark/send_op_asgn_conditional.txt +++ b/test/yarp/snapshots/whitequark/send_op_asgn_conditional.txt @@ -3,7 +3,7 @@ ProgramNode(0...10)( StatementsNode(0...10)( [CallOperatorAndWriteNode(0...10)( CallNode(0...4)( - CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 0, "a"), + CallNode(0...1)(nil, nil, (0...1), nil, nil, nil, nil, 2, "a"), (1...3), (3...4), nil, diff --git a/test/yarp/snapshots/whitequark/send_plain.txt b/test/yarp/snapshots/whitequark/send_plain.txt index 892e30696c2d26..2272355126da7c 100644 --- a/test/yarp/snapshots/whitequark/send_plain.txt +++ b/test/yarp/snapshots/whitequark/send_plain.txt @@ -2,7 +2,7 @@ ProgramNode(0...29)( [], StatementsNode(0...29)( [CallNode(0...7)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...7), nil, @@ -13,7 +13,7 @@ ProgramNode(0...29)( "fun" ), CallNode(9...19)( - CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 0, "foo"), + CallNode(9...12)(nil, nil, (9...12), nil, nil, nil, nil, 2, "foo"), (12...14), (14...17), (17...18), @@ -24,7 +24,7 @@ ProgramNode(0...29)( "Fun" ), CallNode(21...29)( - CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "foo"), + CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "foo"), (24...26), (26...29), nil, diff --git a/test/yarp/snapshots/whitequark/send_plain_cmd.txt b/test/yarp/snapshots/whitequark/send_plain_cmd.txt index 0b13828cb448e7..4fc9fcb730700a 100644 --- a/test/yarp/snapshots/whitequark/send_plain_cmd.txt +++ b/test/yarp/snapshots/whitequark/send_plain_cmd.txt @@ -2,12 +2,12 @@ ProgramNode(0...39)( [], StatementsNode(0...39)( [CallNode(0...11)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...7), nil, ArgumentsNode(8...11)( - [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 0, "bar")] + [CallNode(8...11)(nil, nil, (8...11), nil, nil, nil, nil, 2, "bar")] ), nil, nil, @@ -15,12 +15,12 @@ ProgramNode(0...39)( "fun" ), CallNode(13...25)( - CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo"), + CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo"), (16...18), (18...21), nil, ArgumentsNode(22...25)( - [CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 0, "bar")] + [CallNode(22...25)(nil, nil, (22...25), nil, nil, nil, nil, 2, "bar")] ), nil, nil, @@ -28,17 +28,17 @@ ProgramNode(0...39)( "Fun" ), CallNode(27...39)( - CallNode(27...30)(nil, nil, (27...30), nil, nil, nil, nil, 0, "foo"), + CallNode(27...30)(nil, nil, (27...30), nil, nil, nil, nil, 2, "foo"), (30...32), - (36...39), + (32...35), nil, ArgumentsNode(36...39)( - [CallNode(36...39)(nil, nil, (36...39), nil, nil, nil, nil, 0, "bar")] + [CallNode(36...39)(nil, nil, (36...39), nil, nil, nil, nil, 2, "bar")] ), nil, nil, 0, - "bar" + "fun" )] ) ) diff --git a/test/yarp/snapshots/whitequark/send_self.txt b/test/yarp/snapshots/whitequark/send_self.txt index e12291d277d92c..6f24c1ba8963ba 100644 --- a/test/yarp/snapshots/whitequark/send_self.txt +++ b/test/yarp/snapshots/whitequark/send_self.txt @@ -1,7 +1,7 @@ ProgramNode(0...17)( [], StatementsNode(0...17)( - [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "fun"), + [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "fun"), CallNode(5...9)(nil, nil, (5...9), nil, nil, nil, nil, 0, "fun!"), CallNode(11...17)( nil, diff --git a/test/yarp/snapshots/whitequark/send_unary_op.txt b/test/yarp/snapshots/whitequark/send_unary_op.txt index 6e1a3315b965be..6906d49ae0acad 100644 --- a/test/yarp/snapshots/whitequark/send_unary_op.txt +++ b/test/yarp/snapshots/whitequark/send_unary_op.txt @@ -2,7 +2,7 @@ ProgramNode(0...16)( [], StatementsNode(0...16)( [CallNode(0...4)( - CallNode(1...4)(nil, nil, (1...4), nil, nil, nil, nil, 0, "foo"), + CallNode(1...4)(nil, nil, (1...4), nil, nil, nil, nil, 2, "foo"), nil, (0...1), nil, @@ -13,7 +13,7 @@ ProgramNode(0...16)( "+@" ), CallNode(6...10)( - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "foo"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "foo"), nil, (6...7), nil, @@ -24,7 +24,7 @@ ProgramNode(0...16)( "-@" ), CallNode(12...16)( - CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo"), + CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo"), nil, (12...13), nil, diff --git a/test/yarp/snapshots/whitequark/space_args_arg_block.txt b/test/yarp/snapshots/whitequark/space_args_arg_block.txt index 4ac9d1d7e4488e..d17aae90cd237b 100644 --- a/test/yarp/snapshots/whitequark/space_args_arg_block.txt +++ b/test/yarp/snapshots/whitequark/space_args_arg_block.txt @@ -2,7 +2,7 @@ ProgramNode(0...43)( [], StatementsNode(0...43)( [CallNode(0...14)( - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), (3...4), (4...7), nil, @@ -19,9 +19,9 @@ ProgramNode(0...43)( "fun" ), CallNode(16...31)( - CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "foo"), + CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "foo"), (19...21), - (30...31), + (21...24), nil, ArgumentsNode(25...28)( [ParenthesesNode(25...28)( @@ -33,7 +33,7 @@ ProgramNode(0...43)( nil, BlockNode(29...31)([], nil, nil, (29...30), (30...31)), 0, - "}" + "fun" ), CallNode(33...43)( nil, diff --git a/test/yarp/snapshots/whitequark/space_args_cmd.txt b/test/yarp/snapshots/whitequark/space_args_cmd.txt index 289ef54f8cb000..84493c09a946dd 100644 --- a/test/yarp/snapshots/whitequark/space_args_cmd.txt +++ b/test/yarp/snapshots/whitequark/space_args_cmd.txt @@ -23,7 +23,7 @@ ProgramNode(0...11)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/string_interp.txt b/test/yarp/snapshots/whitequark/string_interp.txt index 20a4555ae2ab26..cd41265c99b133 100644 --- a/test/yarp/snapshots/whitequark/string_interp.txt +++ b/test/yarp/snapshots/whitequark/string_interp.txt @@ -7,7 +7,7 @@ ProgramNode(0...14)( EmbeddedStatementsNode(4...10)( (4...6), StatementsNode(6...9)( - [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "bar")] + [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "bar")] ), (9...10) ), diff --git a/test/yarp/snapshots/whitequark/super.txt b/test/yarp/snapshots/whitequark/super.txt index 0724119add6a41..65eb72d5f5ba1e 100644 --- a/test/yarp/snapshots/whitequark/super.txt +++ b/test/yarp/snapshots/whitequark/super.txt @@ -5,7 +5,7 @@ ProgramNode(0...30)( (0...5), nil, ArgumentsNode(6...9)( - [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "foo")] + [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "foo")] ), nil, nil @@ -15,7 +15,7 @@ ProgramNode(0...30)( (20...25), (25...26), ArgumentsNode(26...29)( - [CallNode(26...29)(nil, nil, (26...29), nil, nil, nil, nil, 0, "foo")] + [CallNode(26...29)(nil, nil, (26...29), nil, nil, nil, nil, 2, "foo")] ), (29...30), nil diff --git a/test/yarp/snapshots/whitequark/super_block.txt b/test/yarp/snapshots/whitequark/super_block.txt index e2af525f24b9a7..a26dad1b37b4f7 100644 --- a/test/yarp/snapshots/whitequark/super_block.txt +++ b/test/yarp/snapshots/whitequark/super_block.txt @@ -8,8 +8,8 @@ ProgramNode(0...35)( (14...19), nil, ArgumentsNode(20...28)( - [CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 0, "foo"), - CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 0, "bar")] + [CallNode(20...23)(nil, nil, (20...23), nil, nil, nil, nil, 2, "foo"), + CallNode(25...28)(nil, nil, (25...28), nil, nil, nil, nil, 2, "bar")] ), nil, BlockNode(29...35)([], nil, nil, (29...31), (32...35)) diff --git a/test/yarp/snapshots/whitequark/symbol_interp.txt b/test/yarp/snapshots/whitequark/symbol_interp.txt index cc6da96739a1eb..5fd0375ae6a122 100644 --- a/test/yarp/snapshots/whitequark/symbol_interp.txt +++ b/test/yarp/snapshots/whitequark/symbol_interp.txt @@ -15,7 +15,7 @@ ProgramNode(0...15)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/snapshots/whitequark/ternary.txt b/test/yarp/snapshots/whitequark/ternary.txt index 58bccdd8bef9af..c975e93c7eff00 100644 --- a/test/yarp/snapshots/whitequark/ternary.txt +++ b/test/yarp/snapshots/whitequark/ternary.txt @@ -3,7 +3,7 @@ ProgramNode(0...11)( StatementsNode(0...11)( [IfNode(0...11)( nil, - CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "foo"), + CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "foo"), StatementsNode(6...7)([IntegerNode(6...7)()]), ElseNode(8...11)( (8...9), diff --git a/test/yarp/snapshots/whitequark/ternary_ambiguous_symbol.txt b/test/yarp/snapshots/whitequark/ternary_ambiguous_symbol.txt index 012b77a3d23226..245f8a07fe6656 100644 --- a/test/yarp/snapshots/whitequark/ternary_ambiguous_symbol.txt +++ b/test/yarp/snapshots/whitequark/ternary_ambiguous_symbol.txt @@ -12,7 +12,7 @@ ProgramNode(0...13)( nil, ParenthesesNode(4...9)( StatementsNode(5...8)( - [CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo")] + [CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo")] ), (4...5), (8...9) diff --git a/test/yarp/snapshots/whitequark/unless.txt b/test/yarp/snapshots/whitequark/unless.txt index 291a636f995d94..2c0a7aa062545f 100644 --- a/test/yarp/snapshots/whitequark/unless.txt +++ b/test/yarp/snapshots/whitequark/unless.txt @@ -3,18 +3,18 @@ ProgramNode(0...46)( StatementsNode(0...46)( [UnlessNode(0...24)( (0...6), - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "foo"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "foo"), StatementsNode(16...19)( - [CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "bar")] + [CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "bar")] ), nil, (21...24) ), UnlessNode(26...46)( (26...32), - CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 0, "foo"), + CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 2, "foo"), StatementsNode(38...41)( - [CallNode(38...41)(nil, nil, (38...41), nil, nil, nil, nil, 0, "bar")] + [CallNode(38...41)(nil, nil, (38...41), nil, nil, nil, nil, 2, "bar")] ), nil, (43...46) diff --git a/test/yarp/snapshots/whitequark/unless_else.txt b/test/yarp/snapshots/whitequark/unless_else.txt index a3564a0c296a94..d08e1294e1f60a 100644 --- a/test/yarp/snapshots/whitequark/unless_else.txt +++ b/test/yarp/snapshots/whitequark/unless_else.txt @@ -3,9 +3,9 @@ ProgramNode(0...66)( StatementsNode(0...66)( [UnlessNode(0...34)( (0...6), - CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 0, "foo"), + CallNode(7...10)(nil, nil, (7...10), nil, nil, nil, nil, 2, "foo"), StatementsNode(16...19)( - [CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 0, "bar")] + [CallNode(16...19)(nil, nil, (16...19), nil, nil, nil, nil, 2, "bar")] ), ElseNode(21...34)( (21...25), @@ -18,7 +18,7 @@ ProgramNode(0...66)( nil, nil, nil, - 0, + 2, "baz" )] ), @@ -28,9 +28,9 @@ ProgramNode(0...66)( ), UnlessNode(36...66)( (36...42), - CallNode(43...46)(nil, nil, (43...46), nil, nil, nil, nil, 0, "foo"), + CallNode(43...46)(nil, nil, (43...46), nil, nil, nil, nil, 2, "foo"), StatementsNode(48...51)( - [CallNode(48...51)(nil, nil, (48...51), nil, nil, nil, nil, 0, "bar")] + [CallNode(48...51)(nil, nil, (48...51), nil, nil, nil, nil, 2, "bar")] ), ElseNode(53...66)( (53...57), @@ -43,7 +43,7 @@ ProgramNode(0...66)( nil, nil, nil, - 0, + 2, "baz" )] ), diff --git a/test/yarp/snapshots/whitequark/unless_mod.txt b/test/yarp/snapshots/whitequark/unless_mod.txt index 37e4f4888157b6..8f2306aa6cd9ba 100644 --- a/test/yarp/snapshots/whitequark/unless_mod.txt +++ b/test/yarp/snapshots/whitequark/unless_mod.txt @@ -3,9 +3,9 @@ ProgramNode(0...14)( StatementsNode(0...14)( [UnlessNode(0...14)( (4...10), - CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "foo"), + CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "foo"), StatementsNode(0...3)( - [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 0, "bar")] + [CallNode(0...3)(nil, nil, (0...3), nil, nil, nil, nil, 2, "bar")] ), nil, nil diff --git a/test/yarp/snapshots/whitequark/until.txt b/test/yarp/snapshots/whitequark/until.txt index 46632a67344e75..2eae2d5307f9b7 100644 --- a/test/yarp/snapshots/whitequark/until.txt +++ b/test/yarp/snapshots/whitequark/until.txt @@ -3,7 +3,7 @@ ProgramNode(0...42)( StatementsNode(0...42)( [UntilNode(0...21)( (0...5), - CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "foo"), + CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "foo"), StatementsNode(13...17)( [CallNode(13...17)( nil, @@ -13,14 +13,15 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "meth" )] - ) + ), + 0 ), UntilNode(23...42)( (23...28), - CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 0, "foo"), + CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 2, "foo"), StatementsNode(34...38)( [CallNode(34...38)( nil, @@ -30,10 +31,11 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "meth" )] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/until_mod.txt b/test/yarp/snapshots/whitequark/until_mod.txt index 604dc3d9ec02d6..62f9d4992e8a93 100644 --- a/test/yarp/snapshots/whitequark/until_mod.txt +++ b/test/yarp/snapshots/whitequark/until_mod.txt @@ -3,10 +3,11 @@ ProgramNode(0...14)( StatementsNode(0...14)( [UntilNode(0...14)( (5...10), - CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "foo"), + CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "foo"), StatementsNode(0...4)( - [CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 0, "meth")] - ) + [CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 2, "meth")] + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/until_post.txt b/test/yarp/snapshots/whitequark/until_post.txt index 0c2a28ab5c4301..27e0a60e407e5f 100644 --- a/test/yarp/snapshots/whitequark/until_post.txt +++ b/test/yarp/snapshots/whitequark/until_post.txt @@ -3,7 +3,7 @@ ProgramNode(0...24)( StatementsNode(0...24)( [UntilNode(0...24)( (15...20), - CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "foo"), + CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "foo"), StatementsNode(0...14)( [BeginNode(0...14)( (0...5), @@ -16,7 +16,7 @@ ProgramNode(0...24)( nil, nil, nil, - 0, + 2, "meth" )] ), @@ -25,7 +25,8 @@ ProgramNode(0...24)( nil, (11...14) )] - ) + ), + 1 )] ) ) diff --git a/test/yarp/snapshots/whitequark/when_multi.txt b/test/yarp/snapshots/whitequark/when_multi.txt index d81232ad20211e..7a5c41f7479863 100644 --- a/test/yarp/snapshots/whitequark/when_multi.txt +++ b/test/yarp/snapshots/whitequark/when_multi.txt @@ -2,7 +2,7 @@ ProgramNode(0...37)( [], StatementsNode(0...37)( [CaseNode(0...37)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), [WhenNode(10...32)( (10...14), [StringNode(15...20)((15...16), (16...19), (19...20), "bar"), @@ -16,7 +16,7 @@ ProgramNode(0...37)( nil, nil, nil, - 0, + 2, "bar" )] ) diff --git a/test/yarp/snapshots/whitequark/when_splat.txt b/test/yarp/snapshots/whitequark/when_splat.txt index 428ea20d6e3a8b..88d2115eb44de4 100644 --- a/test/yarp/snapshots/whitequark/when_splat.txt +++ b/test/yarp/snapshots/whitequark/when_splat.txt @@ -2,7 +2,7 @@ ProgramNode(0...43)( [], StatementsNode(0...43)( [CaseNode(0...43)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), [WhenNode(10...27)( (10...14), [IntegerNode(15...16)(), @@ -16,7 +16,7 @@ ProgramNode(0...43)( nil, nil, nil, - 0, + 2, "baz" ) )], @@ -29,7 +29,7 @@ ProgramNode(0...43)( nil, nil, nil, - 0, + 2, "bar" )] ) @@ -46,7 +46,7 @@ ProgramNode(0...43)( nil, nil, nil, - 0, + 2, "foo" ) )], diff --git a/test/yarp/snapshots/whitequark/when_then.txt b/test/yarp/snapshots/whitequark/when_then.txt index 3880028b7f47bf..8c08e6d8e50e38 100644 --- a/test/yarp/snapshots/whitequark/when_then.txt +++ b/test/yarp/snapshots/whitequark/when_then.txt @@ -2,7 +2,7 @@ ProgramNode(0...34)( [], StatementsNode(0...34)( [CaseNode(0...34)( - CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 0, "foo"), + CallNode(5...8)(nil, nil, (5...8), nil, nil, nil, nil, 2, "foo"), [WhenNode(10...29)( (10...14), [StringNode(15...20)((15...16), (16...19), (19...20), "bar")], @@ -15,7 +15,7 @@ ProgramNode(0...34)( nil, nil, nil, - 0, + 2, "bar" )] ) diff --git a/test/yarp/snapshots/whitequark/while.txt b/test/yarp/snapshots/whitequark/while.txt index 9cd21ff1540df7..7d95f466c8c0d5 100644 --- a/test/yarp/snapshots/whitequark/while.txt +++ b/test/yarp/snapshots/whitequark/while.txt @@ -3,7 +3,7 @@ ProgramNode(0...42)( StatementsNode(0...42)( [WhileNode(0...21)( (0...5), - CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "foo"), + CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "foo"), StatementsNode(13...17)( [CallNode(13...17)( nil, @@ -13,14 +13,15 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "meth" )] - ) + ), + 0 ), WhileNode(23...42)( (23...28), - CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 0, "foo"), + CallNode(29...32)(nil, nil, (29...32), nil, nil, nil, nil, 2, "foo"), StatementsNode(34...38)( [CallNode(34...38)( nil, @@ -30,10 +31,11 @@ ProgramNode(0...42)( nil, nil, nil, - 0, + 2, "meth" )] - ) + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/while_mod.txt b/test/yarp/snapshots/whitequark/while_mod.txt index b39baf15c12a16..b1a0203da3d19f 100644 --- a/test/yarp/snapshots/whitequark/while_mod.txt +++ b/test/yarp/snapshots/whitequark/while_mod.txt @@ -3,10 +3,11 @@ ProgramNode(0...14)( StatementsNode(0...14)( [WhileNode(0...14)( (5...10), - CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 0, "foo"), + CallNode(11...14)(nil, nil, (11...14), nil, nil, nil, nil, 2, "foo"), StatementsNode(0...4)( - [CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 0, "meth")] - ) + [CallNode(0...4)(nil, nil, (0...4), nil, nil, nil, nil, 2, "meth")] + ), + 0 )] ) ) diff --git a/test/yarp/snapshots/whitequark/while_post.txt b/test/yarp/snapshots/whitequark/while_post.txt index 94adefedc7223a..28a423e1562b6e 100644 --- a/test/yarp/snapshots/whitequark/while_post.txt +++ b/test/yarp/snapshots/whitequark/while_post.txt @@ -3,7 +3,7 @@ ProgramNode(0...24)( StatementsNode(0...24)( [WhileNode(0...24)( (15...20), - CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 0, "foo"), + CallNode(21...24)(nil, nil, (21...24), nil, nil, nil, nil, 2, "foo"), StatementsNode(0...14)( [BeginNode(0...14)( (0...5), @@ -16,7 +16,7 @@ ProgramNode(0...24)( nil, nil, nil, - 0, + 2, "meth" )] ), @@ -25,7 +25,8 @@ ProgramNode(0...24)( nil, (11...14) )] - ) + ), + 1 )] ) ) diff --git a/test/yarp/snapshots/whitequark/xstring_interp.txt b/test/yarp/snapshots/whitequark/xstring_interp.txt index 0b7c91cf7f1d49..39d4a12c9830d0 100644 --- a/test/yarp/snapshots/whitequark/xstring_interp.txt +++ b/test/yarp/snapshots/whitequark/xstring_interp.txt @@ -7,7 +7,7 @@ ProgramNode(0...14)( EmbeddedStatementsNode(4...10)( (4...6), StatementsNode(6...9)( - [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 0, "bar")] + [CallNode(6...9)(nil, nil, (6...9), nil, nil, nil, nil, 2, "bar")] ), (9...10) ), diff --git a/test/yarp/snapshots/whitequark/yield.txt b/test/yarp/snapshots/whitequark/yield.txt index 89b53914b6ad96..ae0c2140a3d6c1 100644 --- a/test/yarp/snapshots/whitequark/yield.txt +++ b/test/yarp/snapshots/whitequark/yield.txt @@ -6,7 +6,7 @@ ProgramNode(0...37)( (7...12), nil, ArgumentsNode(13...16)( - [CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 0, "foo")] + [CallNode(13...16)(nil, nil, (13...16), nil, nil, nil, nil, 2, "foo")] ), nil ), @@ -15,7 +15,7 @@ ProgramNode(0...37)( (27...32), (32...33), ArgumentsNode(33...36)( - [CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 0, "foo")] + [CallNode(33...36)(nil, nil, (33...36), nil, nil, nil, nil, 2, "foo")] ), (36...37) )] diff --git a/test/yarp/snapshots/xstring.txt b/test/yarp/snapshots/xstring.txt index 5bc0e9be56cdf2..fe7d5de5a0a987 100644 --- a/test/yarp/snapshots/xstring.txt +++ b/test/yarp/snapshots/xstring.txt @@ -16,7 +16,7 @@ ProgramNode(0...40)( nil, nil, nil, - 0, + 2, "bar" )] ), diff --git a/test/yarp/unescape_test.rb b/test/yarp/unescape_test.rb index 1288a128bdaf99..3b9e6652481a92 100644 --- a/test/yarp/unescape_test.rb +++ b/test/yarp/unescape_test.rb @@ -2,6 +2,8 @@ require "yarp_test_helper" +return if YARP::BACKEND == :FFI + module UnescapeTest class UnescapeNoneTest < Test::Unit::TestCase def test_backslash diff --git a/test/yarp/yarp_test_helper.rb b/test/yarp/yarp_test_helper.rb index 666bc337c764cd..0be0f51651f03b 100644 --- a/test/yarp/yarp_test_helper.rb +++ b/test/yarp/yarp_test_helper.rb @@ -6,6 +6,8 @@ require "test/unit" require "tempfile" +puts "Using YARP backend: #{YARP::BACKEND}" if ENV["YARP_FFI_BACKEND"] + module YARP module Assertions private diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index f0f091e1c50902..8f2f3b5df0e12a 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -627,7 +627,7 @@ def sync_default_gems_with_commits(gem, ranges, edit: nil) puts "Remove files added to toplevel: #{toplevels.join(', ')}" system(*%w"git rm -r --", *toplevels) end - tools = changed.select {|f|f.start_with?("test/lib/", "tool/")} + tools = changed.select {|f|f.start_with?("test/fixtures/", "test/lib/", "tool/")} unless tools.empty? system(*%W"git rm -r --", *tools) system(*%W"git checkout HEAD~ --", *tools) diff --git a/yarp/api_node.c b/yarp/api_node.c index 65a7816eb4c1d0..9ebd1d6673a310 100644 --- a/yarp/api_node.c +++ b/yarp/api_node.c @@ -9,2399 +9,3704 @@ #include "yarp/extension.h" extern VALUE rb_cYARP; +extern VALUE rb_cYARPNode; extern VALUE rb_cYARPSource; extern VALUE rb_cYARPToken; extern VALUE rb_cYARPLocation; +static VALUE rb_cYARPAliasNode; +static VALUE rb_cYARPAlternationPatternNode; +static VALUE rb_cYARPAndNode; +static VALUE rb_cYARPArgumentsNode; +static VALUE rb_cYARPArrayNode; +static VALUE rb_cYARPArrayPatternNode; +static VALUE rb_cYARPAssocNode; +static VALUE rb_cYARPAssocSplatNode; +static VALUE rb_cYARPBackReferenceReadNode; +static VALUE rb_cYARPBeginNode; +static VALUE rb_cYARPBlockArgumentNode; +static VALUE rb_cYARPBlockNode; +static VALUE rb_cYARPBlockParameterNode; +static VALUE rb_cYARPBlockParametersNode; +static VALUE rb_cYARPBreakNode; +static VALUE rb_cYARPCallNode; +static VALUE rb_cYARPCallOperatorAndWriteNode; +static VALUE rb_cYARPCallOperatorOrWriteNode; +static VALUE rb_cYARPCallOperatorWriteNode; +static VALUE rb_cYARPCapturePatternNode; +static VALUE rb_cYARPCaseNode; +static VALUE rb_cYARPClassNode; +static VALUE rb_cYARPClassVariableOperatorAndWriteNode; +static VALUE rb_cYARPClassVariableOperatorOrWriteNode; +static VALUE rb_cYARPClassVariableOperatorWriteNode; +static VALUE rb_cYARPClassVariableReadNode; +static VALUE rb_cYARPClassVariableWriteNode; +static VALUE rb_cYARPConstantOperatorAndWriteNode; +static VALUE rb_cYARPConstantOperatorOrWriteNode; +static VALUE rb_cYARPConstantOperatorWriteNode; +static VALUE rb_cYARPConstantPathNode; +static VALUE rb_cYARPConstantPathOperatorAndWriteNode; +static VALUE rb_cYARPConstantPathOperatorOrWriteNode; +static VALUE rb_cYARPConstantPathOperatorWriteNode; +static VALUE rb_cYARPConstantPathWriteNode; +static VALUE rb_cYARPConstantReadNode; +static VALUE rb_cYARPConstantWriteNode; +static VALUE rb_cYARPDefNode; +static VALUE rb_cYARPDefinedNode; +static VALUE rb_cYARPElseNode; +static VALUE rb_cYARPEmbeddedStatementsNode; +static VALUE rb_cYARPEmbeddedVariableNode; +static VALUE rb_cYARPEnsureNode; +static VALUE rb_cYARPFalseNode; +static VALUE rb_cYARPFindPatternNode; +static VALUE rb_cYARPFlipFlopNode; +static VALUE rb_cYARPFloatNode; +static VALUE rb_cYARPForNode; +static VALUE rb_cYARPForwardingArgumentsNode; +static VALUE rb_cYARPForwardingParameterNode; +static VALUE rb_cYARPForwardingSuperNode; +static VALUE rb_cYARPGlobalVariableOperatorAndWriteNode; +static VALUE rb_cYARPGlobalVariableOperatorOrWriteNode; +static VALUE rb_cYARPGlobalVariableOperatorWriteNode; +static VALUE rb_cYARPGlobalVariableReadNode; +static VALUE rb_cYARPGlobalVariableWriteNode; +static VALUE rb_cYARPHashNode; +static VALUE rb_cYARPHashPatternNode; +static VALUE rb_cYARPIfNode; +static VALUE rb_cYARPImaginaryNode; +static VALUE rb_cYARPInNode; +static VALUE rb_cYARPInstanceVariableOperatorAndWriteNode; +static VALUE rb_cYARPInstanceVariableOperatorOrWriteNode; +static VALUE rb_cYARPInstanceVariableOperatorWriteNode; +static VALUE rb_cYARPInstanceVariableReadNode; +static VALUE rb_cYARPInstanceVariableWriteNode; +static VALUE rb_cYARPIntegerNode; +static VALUE rb_cYARPInterpolatedRegularExpressionNode; +static VALUE rb_cYARPInterpolatedStringNode; +static VALUE rb_cYARPInterpolatedSymbolNode; +static VALUE rb_cYARPInterpolatedXStringNode; +static VALUE rb_cYARPKeywordHashNode; +static VALUE rb_cYARPKeywordParameterNode; +static VALUE rb_cYARPKeywordRestParameterNode; +static VALUE rb_cYARPLambdaNode; +static VALUE rb_cYARPLocalVariableOperatorAndWriteNode; +static VALUE rb_cYARPLocalVariableOperatorOrWriteNode; +static VALUE rb_cYARPLocalVariableOperatorWriteNode; +static VALUE rb_cYARPLocalVariableReadNode; +static VALUE rb_cYARPLocalVariableWriteNode; +static VALUE rb_cYARPMatchPredicateNode; +static VALUE rb_cYARPMatchRequiredNode; +static VALUE rb_cYARPMissingNode; +static VALUE rb_cYARPModuleNode; +static VALUE rb_cYARPMultiWriteNode; +static VALUE rb_cYARPNextNode; +static VALUE rb_cYARPNilNode; +static VALUE rb_cYARPNoKeywordsParameterNode; +static VALUE rb_cYARPNumberedReferenceReadNode; +static VALUE rb_cYARPOptionalParameterNode; +static VALUE rb_cYARPOrNode; +static VALUE rb_cYARPParametersNode; +static VALUE rb_cYARPParenthesesNode; +static VALUE rb_cYARPPinnedExpressionNode; +static VALUE rb_cYARPPinnedVariableNode; +static VALUE rb_cYARPPostExecutionNode; +static VALUE rb_cYARPPreExecutionNode; +static VALUE rb_cYARPProgramNode; +static VALUE rb_cYARPRangeNode; +static VALUE rb_cYARPRationalNode; +static VALUE rb_cYARPRedoNode; +static VALUE rb_cYARPRegularExpressionNode; +static VALUE rb_cYARPRequiredDestructuredParameterNode; +static VALUE rb_cYARPRequiredParameterNode; +static VALUE rb_cYARPRescueModifierNode; +static VALUE rb_cYARPRescueNode; +static VALUE rb_cYARPRestParameterNode; +static VALUE rb_cYARPRetryNode; +static VALUE rb_cYARPReturnNode; +static VALUE rb_cYARPSelfNode; +static VALUE rb_cYARPSingletonClassNode; +static VALUE rb_cYARPSourceEncodingNode; +static VALUE rb_cYARPSourceFileNode; +static VALUE rb_cYARPSourceLineNode; +static VALUE rb_cYARPSplatNode; +static VALUE rb_cYARPStatementsNode; +static VALUE rb_cYARPStringConcatNode; +static VALUE rb_cYARPStringNode; +static VALUE rb_cYARPSuperNode; +static VALUE rb_cYARPSymbolNode; +static VALUE rb_cYARPTrueNode; +static VALUE rb_cYARPUndefNode; +static VALUE rb_cYARPUnlessNode; +static VALUE rb_cYARPUntilNode; +static VALUE rb_cYARPWhenNode; +static VALUE rb_cYARPWhileNode; +static VALUE rb_cYARPXStringNode; +static VALUE rb_cYARPYieldNode; + static VALUE -location_new(yp_parser_t *parser, const char *start, const char *end, VALUE source) { +yp_location_new(yp_parser_t *parser, const char *start, const char *end, VALUE source) { VALUE argv[] = { source, LONG2FIX(start - parser->start), LONG2FIX(end - start) }; return rb_class_new_instance(3, argv, rb_cYARPLocation); } +VALUE +yp_token_new(yp_parser_t *parser, yp_token_t *token, rb_encoding *encoding, VALUE source) { + ID type = rb_intern(yp_token_type_to_str(token->type)); + VALUE location = yp_location_new(parser, token->start, token->end, source); + + VALUE argv[] = { + ID2SYM(type), + rb_enc_str_new(token->start, token->end - token->start, encoding), + location + }; + + return rb_class_new_instance(3, argv, rb_cYARPToken); +} + static VALUE yp_string_new(yp_string_t *string, rb_encoding *encoding) { return rb_enc_str_new(yp_string_source(string), yp_string_length(string), encoding); } -static VALUE -yp_node_new(yp_parser_t *parser, yp_node_t *node, VALUE source, rb_encoding *encoding, ID *constants) { - switch (node->type) { -#line 25 "api_node.c.erb" - case YP_NODE_ALIAS_NODE: { - yp_alias_node_t *cast = (yp_alias_node_t *) node; - VALUE argv[4]; - - // new_name - argv[0] = yp_node_new(parser, (yp_node_t *) cast->new_name, source, encoding, constants); - - // old_name - argv[1] = yp_node_new(parser, (yp_node_t *) cast->old_name, source, encoding, constants); - - // keyword_loc - argv[2] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("AliasNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ALTERNATION_PATTERN_NODE: { - yp_alternation_pattern_node_t *cast = (yp_alternation_pattern_node_t *) node; - VALUE argv[4]; - - // left - argv[0] = yp_node_new(parser, (yp_node_t *) cast->left, source, encoding, constants); - - // right - argv[1] = yp_node_new(parser, (yp_node_t *) cast->right, source, encoding, constants); - - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("AlternationPatternNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_AND_NODE: { - yp_and_node_t *cast = (yp_and_node_t *) node; - VALUE argv[4]; - - // left - argv[0] = yp_node_new(parser, (yp_node_t *) cast->left, source, encoding, constants); - - // right - argv[1] = yp_node_new(parser, (yp_node_t *) cast->right, source, encoding, constants); - - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("AndNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ARGUMENTS_NODE: { - yp_arguments_node_t *cast = (yp_arguments_node_t *) node; - VALUE argv[2]; - - // arguments - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->arguments.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->arguments.nodes[index], source, encoding, constants)); - } - - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("ArgumentsNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ARRAY_NODE: { - yp_array_node_t *cast = (yp_array_node_t *) node; - VALUE argv[4]; - - // elements - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->elements.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->elements.nodes[index], source, encoding, constants)); - } - - // opening_loc - argv[1] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // closing_loc - argv[2] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ArrayNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ARRAY_PATTERN_NODE: { - yp_array_pattern_node_t *cast = (yp_array_pattern_node_t *) node; - VALUE argv[7]; - - // constant - argv[0] = cast->constant == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->constant, source, encoding, constants); - - // requireds - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->requireds.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->requireds.nodes[index], source, encoding, constants)); - } - - // rest - argv[2] = cast->rest == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->rest, source, encoding, constants); - - // posts - argv[3] = rb_ary_new(); - for (size_t index = 0; index < cast->posts.size; index++) { - rb_ary_push(argv[3], yp_node_new(parser, cast->posts.nodes[index], source, encoding, constants)); - } - - // opening_loc - argv[4] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // closing_loc - argv[5] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // location - argv[6] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(7, argv, rb_const_get_at(rb_cYARP, rb_intern("ArrayPatternNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ASSOC_NODE: { - yp_assoc_node_t *cast = (yp_assoc_node_t *) node; - VALUE argv[4]; - - // key - argv[0] = yp_node_new(parser, (yp_node_t *) cast->key, source, encoding, constants); - - // value - argv[1] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // operator_loc - argv[2] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("AssocNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ASSOC_SPLAT_NODE: { - yp_assoc_splat_node_t *cast = (yp_assoc_splat_node_t *) node; - VALUE argv[3]; - - // value - argv[0] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("AssocSplatNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_BACK_REFERENCE_READ_NODE: { - VALUE argv[1]; - - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("BackReferenceReadNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_BEGIN_NODE: { - yp_begin_node_t *cast = (yp_begin_node_t *) node; - VALUE argv[7]; - - // begin_keyword_loc - argv[0] = cast->begin_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->begin_keyword_loc.start, cast->begin_keyword_loc.end, source); - - // statements - argv[1] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // rescue_clause - argv[2] = cast->rescue_clause == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->rescue_clause, source, encoding, constants); - - // else_clause - argv[3] = cast->else_clause == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->else_clause, source, encoding, constants); - - // ensure_clause - argv[4] = cast->ensure_clause == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->ensure_clause, source, encoding, constants); - - // end_keyword_loc - argv[5] = cast->end_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - - // location - argv[6] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(7, argv, rb_const_get_at(rb_cYARP, rb_intern("BeginNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_BLOCK_ARGUMENT_NODE: { - yp_block_argument_node_t *cast = (yp_block_argument_node_t *) node; - VALUE argv[3]; - - // expression - argv[0] = cast->expression == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->expression, source, encoding, constants); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("BlockArgumentNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_BLOCK_NODE: { - yp_block_node_t *cast = (yp_block_node_t *) node; - VALUE argv[6]; - - // locals - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); - } - - // parameters - argv[1] = cast->parameters == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->parameters, source, encoding, constants); - - // statements - argv[2] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // opening_loc - argv[3] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // closing_loc - argv[4] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("BlockNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_BLOCK_PARAMETER_NODE: { - yp_block_parameter_node_t *cast = (yp_block_parameter_node_t *) node; - VALUE argv[3]; - - // name_loc - argv[0] = cast->name_loc.start == NULL ? Qnil : location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("BlockParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_BLOCK_PARAMETERS_NODE: { - yp_block_parameters_node_t *cast = (yp_block_parameters_node_t *) node; - VALUE argv[5]; - - // parameters - argv[0] = cast->parameters == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->parameters, source, encoding, constants); - - // locals - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - yp_location_t location = cast->locals.locations[index]; - rb_ary_push(argv[1], location_new(parser, location.start, location.end, source)); - } - - // opening_loc - argv[2] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // closing_loc - argv[3] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("BlockParametersNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_BREAK_NODE: { - yp_break_node_t *cast = (yp_break_node_t *) node; - VALUE argv[3]; - - // arguments - argv[0] = cast->arguments == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->arguments, source, encoding, constants); - - // keyword_loc - argv[1] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("BreakNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CALL_NODE: { - yp_call_node_t *cast = (yp_call_node_t *) node; - VALUE argv[10]; - - // receiver - argv[0] = cast->receiver == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->receiver, source, encoding, constants); - - // operator_loc - argv[1] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // message_loc - argv[2] = cast->message_loc.start == NULL ? Qnil : location_new(parser, cast->message_loc.start, cast->message_loc.end, source); - - // opening_loc - argv[3] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // arguments - argv[4] = cast->arguments == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->arguments, source, encoding, constants); - - // closing_loc - argv[5] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // block - argv[6] = cast->block == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->block, source, encoding, constants); - - // flags - argv[7] = ULONG2NUM(cast->flags); - - // name - argv[8] = yp_string_new(&cast->name, encoding); - - // location - argv[9] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(10, argv, rb_const_get_at(rb_cYARP, rb_intern("CallNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CALL_OPERATOR_AND_WRITE_NODE: { - yp_call_operator_and_write_node_t *cast = (yp_call_operator_and_write_node_t *) node; - VALUE argv[4]; - - // target - argv[0] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("CallOperatorAndWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CALL_OPERATOR_OR_WRITE_NODE: { - yp_call_operator_or_write_node_t *cast = (yp_call_operator_or_write_node_t *) node; - VALUE argv[4]; - - // target - argv[0] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); - - // value - argv[1] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("CallOperatorOrWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CALL_OPERATOR_WRITE_NODE: { - yp_call_operator_write_node_t *cast = (yp_call_operator_write_node_t *) node; - VALUE argv[5]; - - // target - argv[0] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // operator_id - argv[3] = rb_id2sym(constants[cast->operator_id - 1]); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("CallOperatorWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CAPTURE_PATTERN_NODE: { - yp_capture_pattern_node_t *cast = (yp_capture_pattern_node_t *) node; - VALUE argv[4]; - - // value - argv[0] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // target - argv[1] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); - - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("CapturePatternNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CASE_NODE: { - yp_case_node_t *cast = (yp_case_node_t *) node; - VALUE argv[6]; - - // predicate - argv[0] = cast->predicate == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->predicate, source, encoding, constants); - - // conditions - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->conditions.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->conditions.nodes[index], source, encoding, constants)); - } - - // consequent - argv[2] = cast->consequent == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->consequent, source, encoding, constants); - - // case_keyword_loc - argv[3] = location_new(parser, cast->case_keyword_loc.start, cast->case_keyword_loc.end, source); - - // end_keyword_loc - argv[4] = location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("CaseNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CLASS_NODE: { - yp_class_node_t *cast = (yp_class_node_t *) node; - VALUE argv[8]; - - // locals - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); - } - - // class_keyword_loc - argv[1] = location_new(parser, cast->class_keyword_loc.start, cast->class_keyword_loc.end, source); - - // constant_path - argv[2] = yp_node_new(parser, (yp_node_t *) cast->constant_path, source, encoding, constants); - - // inheritance_operator_loc - argv[3] = cast->inheritance_operator_loc.start == NULL ? Qnil : location_new(parser, cast->inheritance_operator_loc.start, cast->inheritance_operator_loc.end, source); - - // superclass - argv[4] = cast->superclass == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->superclass, source, encoding, constants); - - // statements - argv[5] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // end_keyword_loc - argv[6] = location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - - // location - argv[7] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(8, argv, rb_const_get_at(rb_cYARP, rb_intern("ClassNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CLASS_VARIABLE_OPERATOR_AND_WRITE_NODE: { - yp_class_variable_operator_and_write_node_t *cast = (yp_class_variable_operator_and_write_node_t *) node; - VALUE argv[4]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ClassVariableOperatorAndWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CLASS_VARIABLE_OPERATOR_OR_WRITE_NODE: { - yp_class_variable_operator_or_write_node_t *cast = (yp_class_variable_operator_or_write_node_t *) node; - VALUE argv[4]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ClassVariableOperatorOrWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { - yp_class_variable_operator_write_node_t *cast = (yp_class_variable_operator_write_node_t *) node; - VALUE argv[5]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // operator - argv[3] = rb_id2sym(constants[cast->operator - 1]); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("ClassVariableOperatorWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CLASS_VARIABLE_READ_NODE: { - VALUE argv[1]; - - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("ClassVariableReadNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CLASS_VARIABLE_WRITE_NODE: { - yp_class_variable_write_node_t *cast = (yp_class_variable_write_node_t *) node; - VALUE argv[4]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // value - argv[1] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // operator_loc - argv[2] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ClassVariableWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_OPERATOR_AND_WRITE_NODE: { - yp_constant_operator_and_write_node_t *cast = (yp_constant_operator_and_write_node_t *) node; - VALUE argv[4]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantOperatorAndWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_OPERATOR_OR_WRITE_NODE: { - yp_constant_operator_or_write_node_t *cast = (yp_constant_operator_or_write_node_t *) node; - VALUE argv[4]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantOperatorOrWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_OPERATOR_WRITE_NODE: { - yp_constant_operator_write_node_t *cast = (yp_constant_operator_write_node_t *) node; - VALUE argv[5]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // operator - argv[3] = rb_id2sym(constants[cast->operator - 1]); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantOperatorWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_PATH_NODE: { - yp_constant_path_node_t *cast = (yp_constant_path_node_t *) node; - VALUE argv[4]; - - // parent - argv[0] = cast->parent == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->parent, source, encoding, constants); - - // child - argv[1] = yp_node_new(parser, (yp_node_t *) cast->child, source, encoding, constants); - - // delimiter_loc - argv[2] = location_new(parser, cast->delimiter_loc.start, cast->delimiter_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantPathNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_PATH_OPERATOR_AND_WRITE_NODE: { - yp_constant_path_operator_and_write_node_t *cast = (yp_constant_path_operator_and_write_node_t *) node; - VALUE argv[4]; - - // target - argv[0] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantPathOperatorAndWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_PATH_OPERATOR_OR_WRITE_NODE: { - yp_constant_path_operator_or_write_node_t *cast = (yp_constant_path_operator_or_write_node_t *) node; - VALUE argv[4]; - - // target - argv[0] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); - - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantPathOperatorOrWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_PATH_OPERATOR_WRITE_NODE: { - yp_constant_path_operator_write_node_t *cast = (yp_constant_path_operator_write_node_t *) node; - VALUE argv[5]; - - // target - argv[0] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); +// Create a YARP::Source object from the given parser. +VALUE +yp_source_new(yp_parser_t *parser) { + VALUE source = rb_str_new(parser->start, parser->end - parser->start); + VALUE offsets = rb_ary_new_capa(parser->newline_list.size); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + for (size_t index = 0; index < parser->newline_list.size; index++) { + rb_ary_push(offsets, INT2FIX(parser->newline_list.offsets[index])); + } - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + VALUE source_argv[] = { source, offsets }; + return rb_class_new_instance(2, source_argv, rb_cYARPSource); +} - // operator - argv[3] = rb_id2sym(constants[cast->operator - 1]); +typedef struct yp_node_stack_node { + struct yp_node_stack_node *prev; + yp_node_t *visit; + bool visited; +} yp_node_stack_node_t; + +static void +yp_node_stack_push(yp_node_stack_node_t **stack, yp_node_t *visit) { + yp_node_stack_node_t *node = malloc(sizeof(yp_node_stack_node_t)); + node->prev = *stack; + node->visit = visit; + node->visited = false; + *stack = node; +} - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantPathOperatorWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_PATH_WRITE_NODE: { - yp_constant_path_write_node_t *cast = (yp_constant_path_write_node_t *) node; - VALUE argv[4]; +static yp_node_t * +yp_node_stack_pop(yp_node_stack_node_t **stack) { + yp_node_stack_node_t *current = *stack; + yp_node_t *visit = current->visit; - // target - argv[0] = yp_node_new(parser, (yp_node_t *) cast->target, source, encoding, constants); + *stack = current->prev; + free(current); - // operator_loc - argv[1] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + return visit; +} - // value - argv[2] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); +VALUE +yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { + VALUE source = yp_source_new(parser); + ID *constants = calloc(parser->constant_pool.size, sizeof(ID)); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantPathWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_CONSTANT_READ_NODE: { - VALUE argv[1]; + for (size_t index = 0; index < parser->constant_pool.capacity; index++) { + yp_constant_t constant = parser->constant_pool.constants[index]; - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("ConstantReadNode"))); + if (constant.id != 0) { + constants[constant.id - 1] = rb_intern3(constant.start, constant.length, encoding); } -#line 25 "api_node.c.erb" - case YP_NODE_DEF_NODE: { - yp_def_node_t *cast = (yp_def_node_t *) node; - VALUE argv[12]; - - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - - // receiver - argv[1] = cast->receiver == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->receiver, source, encoding, constants); - - // parameters - argv[2] = cast->parameters == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->parameters, source, encoding, constants); + } - // statements - argv[3] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + yp_node_stack_node_t *node_stack = NULL; + yp_node_stack_push(&node_stack, node); + VALUE value_stack = rb_ary_new(); - // locals - argv[4] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - rb_ary_push(argv[4], rb_id2sym(constants[cast->locals.ids[index] - 1])); + while (node_stack != NULL) { + if (!node_stack->visited) { + if (node_stack->visit == NULL) { + yp_node_stack_pop(&node_stack); + rb_ary_push(value_stack, Qnil); + continue; } - // def_keyword_loc - argv[5] = location_new(parser, cast->def_keyword_loc.start, cast->def_keyword_loc.end, source); - - // operator_loc - argv[6] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // lparen_loc - argv[7] = cast->lparen_loc.start == NULL ? Qnil : location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); - - // rparen_loc - argv[8] = cast->rparen_loc.start == NULL ? Qnil : location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); - - // equal_loc - argv[9] = cast->equal_loc.start == NULL ? Qnil : location_new(parser, cast->equal_loc.start, cast->equal_loc.end, source); - - // end_keyword_loc - argv[10] = cast->end_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - - // location - argv[11] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(12, argv, rb_const_get_at(rb_cYARP, rb_intern("DefNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_DEFINED_NODE: { - yp_defined_node_t *cast = (yp_defined_node_t *) node; - VALUE argv[5]; - - // lparen_loc - argv[0] = cast->lparen_loc.start == NULL ? Qnil : location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); - - // value - argv[1] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); - - // rparen_loc - argv[2] = cast->rparen_loc.start == NULL ? Qnil : location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); - - // keyword_loc - argv[3] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("DefinedNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ELSE_NODE: { - yp_else_node_t *cast = (yp_else_node_t *) node; - VALUE argv[4]; - - // else_keyword_loc - argv[0] = location_new(parser, cast->else_keyword_loc.start, cast->else_keyword_loc.end, source); - - // statements - argv[1] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // end_keyword_loc - argv[2] = cast->end_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ElseNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_EMBEDDED_STATEMENTS_NODE: { - yp_embedded_statements_node_t *cast = (yp_embedded_statements_node_t *) node; - VALUE argv[4]; - - // opening_loc - argv[0] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // statements - argv[1] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("EmbeddedStatementsNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_EMBEDDED_VARIABLE_NODE: { - yp_embedded_variable_node_t *cast = (yp_embedded_variable_node_t *) node; - VALUE argv[3]; - - // operator_loc - argv[0] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - - // variable - argv[1] = yp_node_new(parser, (yp_node_t *) cast->variable, source, encoding, constants); - - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("EmbeddedVariableNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_ENSURE_NODE: { - yp_ensure_node_t *cast = (yp_ensure_node_t *) node; - VALUE argv[4]; - - // ensure_keyword_loc - argv[0] = location_new(parser, cast->ensure_keyword_loc.start, cast->ensure_keyword_loc.end, source); - - // statements - argv[1] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // end_keyword_loc - argv[2] = location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("EnsureNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_FALSE_NODE: { - VALUE argv[1]; - - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("FalseNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_FIND_PATTERN_NODE: { - yp_find_pattern_node_t *cast = (yp_find_pattern_node_t *) node; - VALUE argv[7]; - - // constant - argv[0] = cast->constant == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->constant, source, encoding, constants); - - // left - argv[1] = yp_node_new(parser, (yp_node_t *) cast->left, source, encoding, constants); - - // requireds - argv[2] = rb_ary_new(); - for (size_t index = 0; index < cast->requireds.size; index++) { - rb_ary_push(argv[2], yp_node_new(parser, cast->requireds.nodes[index], source, encoding, constants)); + yp_node_t *node = node_stack->visit; + node_stack->visited = true; + + switch (YP_NODE_TYPE(node)) { +#line 111 "api_node.c.erb" + case YP_NODE_ALIAS_NODE: { + yp_alias_node_t *cast = (yp_alias_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->new_name); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->old_name); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ALTERNATION_PATTERN_NODE: { + yp_alternation_pattern_node_t *cast = (yp_alternation_pattern_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->left); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->right); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_AND_NODE: { + yp_and_node_t *cast = (yp_and_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->left); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->right); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ARGUMENTS_NODE: { + yp_arguments_node_t *cast = (yp_arguments_node_t *) node; + for (size_t index = 0; index < cast->arguments.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->arguments.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ARRAY_NODE: { + yp_array_node_t *cast = (yp_array_node_t *) node; + for (size_t index = 0; index < cast->elements.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->elements.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ARRAY_PATTERN_NODE: { + yp_array_pattern_node_t *cast = (yp_array_pattern_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->constant); + for (size_t index = 0; index < cast->requireds.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->requireds.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->rest); + for (size_t index = 0; index < cast->posts.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->posts.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ASSOC_NODE: { + yp_assoc_node_t *cast = (yp_assoc_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->key); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ASSOC_SPLAT_NODE: { + yp_assoc_splat_node_t *cast = (yp_assoc_splat_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_BEGIN_NODE: { + yp_begin_node_t *cast = (yp_begin_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->rescue_clause); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->else_clause); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->ensure_clause); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_BLOCK_ARGUMENT_NODE: { + yp_block_argument_node_t *cast = (yp_block_argument_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->expression); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_BLOCK_NODE: { + yp_block_node_t *cast = (yp_block_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parameters); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_BLOCK_PARAMETERS_NODE: { + yp_block_parameters_node_t *cast = (yp_block_parameters_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parameters); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_BREAK_NODE: { + yp_break_node_t *cast = (yp_break_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->arguments); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CALL_NODE: { + yp_call_node_t *cast = (yp_call_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->receiver); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->arguments); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->block); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CALL_OPERATOR_AND_WRITE_NODE: { + yp_call_operator_and_write_node_t *cast = (yp_call_operator_and_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CALL_OPERATOR_OR_WRITE_NODE: { + yp_call_operator_or_write_node_t *cast = (yp_call_operator_or_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CALL_OPERATOR_WRITE_NODE: { + yp_call_operator_write_node_t *cast = (yp_call_operator_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CAPTURE_PATTERN_NODE: { + yp_capture_pattern_node_t *cast = (yp_capture_pattern_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CASE_NODE: { + yp_case_node_t *cast = (yp_case_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->predicate); + for (size_t index = 0; index < cast->conditions.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->conditions.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->consequent); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CLASS_NODE: { + yp_class_node_t *cast = (yp_class_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->constant_path); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->superclass); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_class_variable_operator_and_write_node_t *cast = (yp_class_variable_operator_and_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_class_variable_operator_or_write_node_t *cast = (yp_class_variable_operator_or_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { + yp_class_variable_operator_write_node_t *cast = (yp_class_variable_operator_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_WRITE_NODE: { + yp_class_variable_write_node_t *cast = (yp_class_variable_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_OPERATOR_AND_WRITE_NODE: { + yp_constant_operator_and_write_node_t *cast = (yp_constant_operator_and_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_OPERATOR_OR_WRITE_NODE: { + yp_constant_operator_or_write_node_t *cast = (yp_constant_operator_or_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_OPERATOR_WRITE_NODE: { + yp_constant_operator_write_node_t *cast = (yp_constant_operator_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_NODE: { + yp_constant_path_node_t *cast = (yp_constant_path_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parent); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->child); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_OPERATOR_AND_WRITE_NODE: { + yp_constant_path_operator_and_write_node_t *cast = (yp_constant_path_operator_and_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_OPERATOR_OR_WRITE_NODE: { + yp_constant_path_operator_or_write_node_t *cast = (yp_constant_path_operator_or_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_OPERATOR_WRITE_NODE: { + yp_constant_path_operator_write_node_t *cast = (yp_constant_path_operator_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_WRITE_NODE: { + yp_constant_path_write_node_t *cast = (yp_constant_path_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->target); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_CONSTANT_WRITE_NODE: { + yp_constant_write_node_t *cast = (yp_constant_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_DEF_NODE: { + yp_def_node_t *cast = (yp_def_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->receiver); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parameters); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_DEFINED_NODE: { + yp_defined_node_t *cast = (yp_defined_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ELSE_NODE: { + yp_else_node_t *cast = (yp_else_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_EMBEDDED_STATEMENTS_NODE: { + yp_embedded_statements_node_t *cast = (yp_embedded_statements_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_EMBEDDED_VARIABLE_NODE: { + yp_embedded_variable_node_t *cast = (yp_embedded_variable_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->variable); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_ENSURE_NODE: { + yp_ensure_node_t *cast = (yp_ensure_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_FIND_PATTERN_NODE: { + yp_find_pattern_node_t *cast = (yp_find_pattern_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->constant); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->left); + for (size_t index = 0; index < cast->requireds.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->requireds.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->right); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_FLIP_FLOP_NODE: { + yp_flip_flop_node_t *cast = (yp_flip_flop_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->left); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->right); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_FOR_NODE: { + yp_for_node_t *cast = (yp_for_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->index); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->collection); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_FORWARDING_SUPER_NODE: { + yp_forwarding_super_node_t *cast = (yp_forwarding_super_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->block); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_global_variable_operator_and_write_node_t *cast = (yp_global_variable_operator_and_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_global_variable_operator_or_write_node_t *cast = (yp_global_variable_operator_or_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: { + yp_global_variable_operator_write_node_t *cast = (yp_global_variable_operator_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_WRITE_NODE: { + yp_global_variable_write_node_t *cast = (yp_global_variable_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_HASH_NODE: { + yp_hash_node_t *cast = (yp_hash_node_t *) node; + for (size_t index = 0; index < cast->elements.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->elements.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_HASH_PATTERN_NODE: { + yp_hash_pattern_node_t *cast = (yp_hash_pattern_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->constant); + for (size_t index = 0; index < cast->assocs.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->assocs.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->kwrest); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_IF_NODE: { + yp_if_node_t *cast = (yp_if_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->predicate); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->consequent); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_IMAGINARY_NODE: { + yp_imaginary_node_t *cast = (yp_imaginary_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->numeric); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_IN_NODE: { + yp_in_node_t *cast = (yp_in_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->pattern); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_instance_variable_operator_and_write_node_t *cast = (yp_instance_variable_operator_and_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_instance_variable_operator_or_write_node_t *cast = (yp_instance_variable_operator_or_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: { + yp_instance_variable_operator_write_node_t *cast = (yp_instance_variable_operator_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_WRITE_NODE: { + yp_instance_variable_write_node_t *cast = (yp_instance_variable_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INTERPOLATED_REGULAR_EXPRESSION_NODE: { + yp_interpolated_regular_expression_node_t *cast = (yp_interpolated_regular_expression_node_t *) node; + for (size_t index = 0; index < cast->parts.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parts.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INTERPOLATED_STRING_NODE: { + yp_interpolated_string_node_t *cast = (yp_interpolated_string_node_t *) node; + for (size_t index = 0; index < cast->parts.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parts.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INTERPOLATED_SYMBOL_NODE: { + yp_interpolated_symbol_node_t *cast = (yp_interpolated_symbol_node_t *) node; + for (size_t index = 0; index < cast->parts.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parts.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_INTERPOLATED_X_STRING_NODE: { + yp_interpolated_x_string_node_t *cast = (yp_interpolated_x_string_node_t *) node; + for (size_t index = 0; index < cast->parts.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parts.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_KEYWORD_HASH_NODE: { + yp_keyword_hash_node_t *cast = (yp_keyword_hash_node_t *) node; + for (size_t index = 0; index < cast->elements.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->elements.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_KEYWORD_PARAMETER_NODE: { + yp_keyword_parameter_node_t *cast = (yp_keyword_parameter_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_LAMBDA_NODE: { + yp_lambda_node_t *cast = (yp_lambda_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parameters); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_local_variable_operator_and_write_node_t *cast = (yp_local_variable_operator_and_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_local_variable_operator_or_write_node_t *cast = (yp_local_variable_operator_or_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { + yp_local_variable_operator_write_node_t *cast = (yp_local_variable_operator_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_WRITE_NODE: { + yp_local_variable_write_node_t *cast = (yp_local_variable_write_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_MATCH_PREDICATE_NODE: { + yp_match_predicate_node_t *cast = (yp_match_predicate_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->pattern); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_MATCH_REQUIRED_NODE: { + yp_match_required_node_t *cast = (yp_match_required_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->pattern); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_MODULE_NODE: { + yp_module_node_t *cast = (yp_module_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->constant_path); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_MULTI_WRITE_NODE: { + yp_multi_write_node_t *cast = (yp_multi_write_node_t *) node; + for (size_t index = 0; index < cast->targets.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->targets.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_NEXT_NODE: { + yp_next_node_t *cast = (yp_next_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->arguments); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_OPTIONAL_PARAMETER_NODE: { + yp_optional_parameter_node_t *cast = (yp_optional_parameter_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->value); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_OR_NODE: { + yp_or_node_t *cast = (yp_or_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->left); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->right); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_PARAMETERS_NODE: { + yp_parameters_node_t *cast = (yp_parameters_node_t *) node; + for (size_t index = 0; index < cast->requireds.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->requireds.nodes[index]); + } + for (size_t index = 0; index < cast->optionals.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->optionals.nodes[index]); + } + for (size_t index = 0; index < cast->posts.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->posts.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->rest); + for (size_t index = 0; index < cast->keywords.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->keywords.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->keyword_rest); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->block); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_PARENTHESES_NODE: { + yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_PINNED_EXPRESSION_NODE: { + yp_pinned_expression_node_t *cast = (yp_pinned_expression_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->expression); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_PINNED_VARIABLE_NODE: { + yp_pinned_variable_node_t *cast = (yp_pinned_variable_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->variable); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_POST_EXECUTION_NODE: { + yp_post_execution_node_t *cast = (yp_post_execution_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_PRE_EXECUTION_NODE: { + yp_pre_execution_node_t *cast = (yp_pre_execution_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_PROGRAM_NODE: { + yp_program_node_t *cast = (yp_program_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_RANGE_NODE: { + yp_range_node_t *cast = (yp_range_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->left); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->right); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_RATIONAL_NODE: { + yp_rational_node_t *cast = (yp_rational_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->numeric); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { + yp_required_destructured_parameter_node_t *cast = (yp_required_destructured_parameter_node_t *) node; + for (size_t index = 0; index < cast->parameters.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->parameters.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_RESCUE_MODIFIER_NODE: { + yp_rescue_modifier_node_t *cast = (yp_rescue_modifier_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->expression); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->rescue_expression); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_RESCUE_NODE: { + yp_rescue_node_t *cast = (yp_rescue_node_t *) node; + for (size_t index = 0; index < cast->exceptions.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->exceptions.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->reference); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->consequent); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_RETURN_NODE: { + yp_return_node_t *cast = (yp_return_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->arguments); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_SINGLETON_CLASS_NODE: { + yp_singleton_class_node_t *cast = (yp_singleton_class_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->expression); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_SPLAT_NODE: { + yp_splat_node_t *cast = (yp_splat_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->expression); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_STATEMENTS_NODE: { + yp_statements_node_t *cast = (yp_statements_node_t *) node; + for (size_t index = 0; index < cast->body.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->body.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_STRING_CONCAT_NODE: { + yp_string_concat_node_t *cast = (yp_string_concat_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->left); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->right); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_SUPER_NODE: { + yp_super_node_t *cast = (yp_super_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->arguments); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->block); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_UNDEF_NODE: { + yp_undef_node_t *cast = (yp_undef_node_t *) node; + for (size_t index = 0; index < cast->names.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->names.nodes[index]); + } + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_UNLESS_NODE: { + yp_unless_node_t *cast = (yp_unless_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->predicate); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->consequent); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_UNTIL_NODE: { + yp_until_node_t *cast = (yp_until_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->predicate); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_WHEN_NODE: { + yp_when_node_t *cast = (yp_when_node_t *) node; + for (size_t index = 0; index < cast->conditions.size; index++) { + yp_node_stack_push(&node_stack, (yp_node_t *) cast->conditions.nodes[index]); + } + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_WHILE_NODE: { + yp_while_node_t *cast = (yp_while_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->predicate); + yp_node_stack_push(&node_stack, (yp_node_t *) cast->statements); + break; + } +#line 111 "api_node.c.erb" + case YP_NODE_YIELD_NODE: { + yp_yield_node_t *cast = (yp_yield_node_t *) node; + yp_node_stack_push(&node_stack, (yp_node_t *) cast->arguments); + break; + } + default: + break; } +#line 131 "api_node.c.erb" + } else { + yp_node_t *node = yp_node_stack_pop(&node_stack); + + switch (YP_NODE_TYPE(node)) { +#line 137 "api_node.c.erb" + case YP_NODE_ALIAS_NODE: { + yp_alias_node_t *cast = (yp_alias_node_t *) node; + VALUE argv[4]; + + // new_name + argv[0] = rb_ary_pop(value_stack); + + // old_name + argv[1] = rb_ary_pop(value_stack); + + // keyword_loc + argv[2] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPAliasNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ALTERNATION_PATTERN_NODE: { + yp_alternation_pattern_node_t *cast = (yp_alternation_pattern_node_t *) node; + VALUE argv[4]; + + // left + argv[0] = rb_ary_pop(value_stack); + + // right + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPAlternationPatternNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_AND_NODE: { + yp_and_node_t *cast = (yp_and_node_t *) node; + VALUE argv[4]; + + // left + argv[0] = rb_ary_pop(value_stack); + + // right + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPAndNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ARGUMENTS_NODE: { + yp_arguments_node_t *cast = (yp_arguments_node_t *) node; + VALUE argv[2]; + + // arguments + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->arguments.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } + + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPArgumentsNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ARRAY_NODE: { + yp_array_node_t *cast = (yp_array_node_t *) node; + VALUE argv[4]; + + // elements + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->elements.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } + + // opening_loc + argv[1] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // closing_loc + argv[2] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPArrayNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ARRAY_PATTERN_NODE: { + yp_array_pattern_node_t *cast = (yp_array_pattern_node_t *) node; + VALUE argv[7]; + + // constant + argv[0] = rb_ary_pop(value_stack); + + // requireds + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->requireds.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // rest + argv[2] = rb_ary_pop(value_stack); + + // posts + argv[3] = rb_ary_new(); + for (size_t index = 0; index < cast->posts.size; index++) { + rb_ary_push(argv[3], rb_ary_pop(value_stack)); + } + + // opening_loc + argv[4] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // closing_loc + argv[5] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[6] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(7, argv, rb_cYARPArrayPatternNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ASSOC_NODE: { + yp_assoc_node_t *cast = (yp_assoc_node_t *) node; + VALUE argv[4]; + + // key + argv[0] = rb_ary_pop(value_stack); + + // value + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPAssocNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ASSOC_SPLAT_NODE: { + yp_assoc_splat_node_t *cast = (yp_assoc_splat_node_t *) node; + VALUE argv[3]; + + // value + argv[0] = rb_ary_pop(value_stack); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPAssocSplatNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_BACK_REFERENCE_READ_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPBackReferenceReadNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_BEGIN_NODE: { + yp_begin_node_t *cast = (yp_begin_node_t *) node; + VALUE argv[7]; + + // begin_keyword_loc + argv[0] = cast->begin_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->begin_keyword_loc.start, cast->begin_keyword_loc.end, source); + + // statements + argv[1] = rb_ary_pop(value_stack); + + // rescue_clause + argv[2] = rb_ary_pop(value_stack); + + // else_clause + argv[3] = rb_ary_pop(value_stack); + + // ensure_clause + argv[4] = rb_ary_pop(value_stack); + + // end_keyword_loc + argv[5] = cast->end_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + + // location + argv[6] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(7, argv, rb_cYARPBeginNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_BLOCK_ARGUMENT_NODE: { + yp_block_argument_node_t *cast = (yp_block_argument_node_t *) node; + VALUE argv[3]; + + // expression + argv[0] = rb_ary_pop(value_stack); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPBlockArgumentNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_BLOCK_NODE: { + yp_block_node_t *cast = (yp_block_node_t *) node; + VALUE argv[6]; + + // locals + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); + } - // right - argv[3] = yp_node_new(parser, (yp_node_t *) cast->right, source, encoding, constants); + // parameters + argv[1] = rb_ary_pop(value_stack); - // opening_loc - argv[4] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + // statements + argv[2] = rb_ary_pop(value_stack); - // closing_loc - argv[5] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // opening_loc + argv[3] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - // location - argv[6] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(7, argv, rb_const_get_at(rb_cYARP, rb_intern("FindPatternNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_FLOAT_NODE: { - VALUE argv[1]; + // closing_loc + argv[4] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("FloatNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_FOR_NODE: { - yp_for_node_t *cast = (yp_for_node_t *) node; - VALUE argv[8]; + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); - // index - argv[0] = yp_node_new(parser, (yp_node_t *) cast->index, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPBlockNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_BLOCK_PARAMETER_NODE: { + yp_block_parameter_node_t *cast = (yp_block_parameter_node_t *) node; + VALUE argv[3]; - // collection - argv[1] = yp_node_new(parser, (yp_node_t *) cast->collection, source, encoding, constants); + // name_loc + argv[0] = cast->name_loc.start == NULL ? Qnil : yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // statements - argv[2] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // for_keyword_loc - argv[3] = location_new(parser, cast->for_keyword_loc.start, cast->for_keyword_loc.end, source); + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); - // in_keyword_loc - argv[4] = location_new(parser, cast->in_keyword_loc.start, cast->in_keyword_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPBlockParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_BLOCK_PARAMETERS_NODE: { + yp_block_parameters_node_t *cast = (yp_block_parameters_node_t *) node; + VALUE argv[5]; - // do_keyword_loc - argv[5] = cast->do_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->do_keyword_loc.start, cast->do_keyword_loc.end, source); + // parameters + argv[0] = rb_ary_pop(value_stack); - // end_keyword_loc - argv[6] = location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + // locals + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + yp_location_t location = cast->locals.locations[index]; + rb_ary_push(argv[1], yp_location_new(parser, location.start, location.end, source)); + } - // location - argv[7] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(8, argv, rb_const_get_at(rb_cYARP, rb_intern("ForNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_FORWARDING_ARGUMENTS_NODE: { - VALUE argv[1]; + // opening_loc + argv[2] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("ForwardingArgumentsNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_FORWARDING_PARAMETER_NODE: { - VALUE argv[1]; + // closing_loc + argv[3] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("ForwardingParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_FORWARDING_SUPER_NODE: { - yp_forwarding_super_node_t *cast = (yp_forwarding_super_node_t *) node; - VALUE argv[2]; + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // block - argv[0] = cast->block == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->block, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPBlockParametersNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_BREAK_NODE: { + yp_break_node_t *cast = (yp_break_node_t *) node; + VALUE argv[3]; + + // arguments + argv[0] = rb_ary_pop(value_stack); + + // keyword_loc + argv[1] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("ForwardingSuperNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE: { - yp_global_variable_operator_and_write_node_t *cast = (yp_global_variable_operator_and_write_node_t *) node; - VALUE argv[4]; + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPBreakNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CALL_NODE: { + yp_call_node_t *cast = (yp_call_node_t *) node; + VALUE argv[10]; + + // receiver + argv[0] = rb_ary_pop(value_stack); + + // operator_loc + argv[1] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // message_loc + argv[2] = cast->message_loc.start == NULL ? Qnil : yp_location_new(parser, cast->message_loc.start, cast->message_loc.end, source); - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // opening_loc + argv[3] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("GlobalVariableOperatorAndWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE: { - yp_global_variable_operator_or_write_node_t *cast = (yp_global_variable_operator_or_write_node_t *) node; - VALUE argv[4]; + // arguments + argv[4] = rb_ary_pop(value_stack); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // closing_loc + argv[5] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // block + argv[6] = rb_ary_pop(value_stack); - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // flags + argv[7] = ULONG2NUM(node->flags >> 1); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("GlobalVariableOperatorOrWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: { - yp_global_variable_operator_write_node_t *cast = (yp_global_variable_operator_write_node_t *) node; - VALUE argv[5]; + // name + argv[8] = yp_string_new(&cast->name, encoding); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // location + argv[9] = yp_location_new(parser, node->location.start, node->location.end, source); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(10, argv, rb_cYARPCallNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CALL_OPERATOR_AND_WRITE_NODE: { + yp_call_operator_and_write_node_t *cast = (yp_call_operator_and_write_node_t *) node; + VALUE argv[4]; - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // target + argv[0] = rb_ary_pop(value_stack); - // operator - argv[3] = rb_id2sym(constants[cast->operator - 1]); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("GlobalVariableOperatorWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_GLOBAL_VARIABLE_READ_NODE: { - VALUE argv[1]; + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("GlobalVariableReadNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_GLOBAL_VARIABLE_WRITE_NODE: { - yp_global_variable_write_node_t *cast = (yp_global_variable_write_node_t *) node; - VALUE argv[4]; + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPCallOperatorAndWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CALL_OPERATOR_OR_WRITE_NODE: { + yp_call_operator_or_write_node_t *cast = (yp_call_operator_or_write_node_t *) node; + VALUE argv[4]; - // operator_loc - argv[1] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // target + argv[0] = rb_ary_pop(value_stack); - // value - argv[2] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // value + argv[1] = rb_ary_pop(value_stack); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("GlobalVariableWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_HASH_NODE: { - yp_hash_node_t *cast = (yp_hash_node_t *) node; - VALUE argv[4]; - - // opening_loc - argv[0] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // elements - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->elements.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->elements.nodes[index], source, encoding, constants)); - } + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("HashNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_HASH_PATTERN_NODE: { - yp_hash_pattern_node_t *cast = (yp_hash_pattern_node_t *) node; - VALUE argv[6]; - - // constant - argv[0] = cast->constant == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->constant, source, encoding, constants); - - // assocs - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->assocs.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->assocs.nodes[index], source, encoding, constants)); - } + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPCallOperatorOrWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CALL_OPERATOR_WRITE_NODE: { + yp_call_operator_write_node_t *cast = (yp_call_operator_write_node_t *) node; + VALUE argv[5]; - // kwrest - argv[2] = cast->kwrest == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->kwrest, source, encoding, constants); + // target + argv[0] = rb_ary_pop(value_stack); - // opening_loc - argv[3] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // closing_loc - argv[4] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("HashPatternNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_IF_NODE: { - yp_if_node_t *cast = (yp_if_node_t *) node; - VALUE argv[6]; + // operator_id + argv[3] = rb_id2sym(constants[cast->operator_id - 1]); - // if_keyword_loc - argv[0] = cast->if_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->if_keyword_loc.start, cast->if_keyword_loc.end, source); + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // predicate - argv[1] = yp_node_new(parser, (yp_node_t *) cast->predicate, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPCallOperatorWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CAPTURE_PATTERN_NODE: { + yp_capture_pattern_node_t *cast = (yp_capture_pattern_node_t *) node; + VALUE argv[4]; - // statements - argv[2] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // value + argv[0] = rb_ary_pop(value_stack); - // consequent - argv[3] = cast->consequent == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->consequent, source, encoding, constants); + // target + argv[1] = rb_ary_pop(value_stack); - // end_keyword_loc - argv[4] = cast->end_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("IfNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_IMAGINARY_NODE: { - yp_imaginary_node_t *cast = (yp_imaginary_node_t *) node; - VALUE argv[2]; + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // numeric - argv[0] = yp_node_new(parser, (yp_node_t *) cast->numeric, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPCapturePatternNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CASE_NODE: { + yp_case_node_t *cast = (yp_case_node_t *) node; + VALUE argv[6]; - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("ImaginaryNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_IN_NODE: { - yp_in_node_t *cast = (yp_in_node_t *) node; - VALUE argv[5]; + // predicate + argv[0] = rb_ary_pop(value_stack); - // pattern - argv[0] = yp_node_new(parser, (yp_node_t *) cast->pattern, source, encoding, constants); + // conditions + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->conditions.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } - // statements - argv[1] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // consequent + argv[2] = rb_ary_pop(value_stack); - // in_loc - argv[2] = location_new(parser, cast->in_loc.start, cast->in_loc.end, source); + // case_keyword_loc + argv[3] = yp_location_new(parser, cast->case_keyword_loc.start, cast->case_keyword_loc.end, source); - // then_loc - argv[3] = cast->then_loc.start == NULL ? Qnil : location_new(parser, cast->then_loc.start, cast->then_loc.end, source); + // end_keyword_loc + argv[4] = yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("InNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE: { - yp_instance_variable_operator_and_write_node_t *cast = (yp_instance_variable_operator_and_write_node_t *) node; - VALUE argv[4]; + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPCaseNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CLASS_NODE: { + yp_class_node_t *cast = (yp_class_node_t *) node; + VALUE argv[8]; - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // locals + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); + } - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // class_keyword_loc + argv[1] = yp_location_new(parser, cast->class_keyword_loc.start, cast->class_keyword_loc.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("InstanceVariableOperatorAndWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE: { - yp_instance_variable_operator_or_write_node_t *cast = (yp_instance_variable_operator_or_write_node_t *) node; - VALUE argv[4]; + // constant_path + argv[2] = rb_ary_pop(value_stack); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // inheritance_operator_loc + argv[3] = cast->inheritance_operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->inheritance_operator_loc.start, cast->inheritance_operator_loc.end, source); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // superclass + argv[4] = rb_ary_pop(value_stack); - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // statements + argv[5] = rb_ary_pop(value_stack); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("InstanceVariableOperatorOrWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: { - yp_instance_variable_operator_write_node_t *cast = (yp_instance_variable_operator_write_node_t *) node; - VALUE argv[5]; + // end_keyword_loc + argv[6] = yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // location + argv[7] = yp_location_new(parser, node->location.start, node->location.end, source); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(8, argv, rb_cYARPClassNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_class_variable_operator_and_write_node_t *cast = (yp_class_variable_operator_and_write_node_t *) node; + VALUE argv[4]; - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // operator - argv[3] = rb_id2sym(constants[cast->operator - 1]); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("InstanceVariableOperatorWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INSTANCE_VARIABLE_READ_NODE: { - VALUE argv[1]; + // value + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPClassVariableOperatorAndWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_class_variable_operator_or_write_node_t *cast = (yp_class_variable_operator_or_write_node_t *) node; + VALUE argv[4]; - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("InstanceVariableReadNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INSTANCE_VARIABLE_WRITE_NODE: { - yp_instance_variable_write_node_t *cast = (yp_instance_variable_write_node_t *) node; - VALUE argv[4]; + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // value - argv[1] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // value + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPClassVariableOperatorOrWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_OPERATOR_WRITE_NODE: { + yp_class_variable_operator_write_node_t *cast = (yp_class_variable_operator_write_node_t *) node; + VALUE argv[5]; - // operator_loc - argv[2] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("InstanceVariableWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INTEGER_NODE: { - VALUE argv[1]; + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("IntegerNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INTERPOLATED_REGULAR_EXPRESSION_NODE: { - yp_interpolated_regular_expression_node_t *cast = (yp_interpolated_regular_expression_node_t *) node; - VALUE argv[5]; - - // opening_loc - argv[0] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // parts - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->parts.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->parts.nodes[index], source, encoding, constants)); - } + // value + argv[2] = rb_ary_pop(value_stack); - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // operator + argv[3] = rb_id2sym(constants[cast->operator - 1]); - // flags - argv[3] = ULONG2NUM(cast->flags); + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPClassVariableOperatorWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_READ_NODE: { + VALUE argv[1]; - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("InterpolatedRegularExpressionNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INTERPOLATED_STRING_NODE: { - yp_interpolated_string_node_t *cast = (yp_interpolated_string_node_t *) node; - VALUE argv[4]; - - // opening_loc - argv[0] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // parts - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->parts.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->parts.nodes[index], source, encoding, constants)); - } + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); - // closing_loc - argv[2] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPClassVariableReadNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CLASS_VARIABLE_WRITE_NODE: { + yp_class_variable_write_node_t *cast = (yp_class_variable_write_node_t *) node; + VALUE argv[4]; - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("InterpolatedStringNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INTERPOLATED_SYMBOL_NODE: { - yp_interpolated_symbol_node_t *cast = (yp_interpolated_symbol_node_t *) node; - VALUE argv[4]; - - // opening_loc - argv[0] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // parts - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->parts.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->parts.nodes[index], source, encoding, constants)); - } + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // closing_loc - argv[2] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // value + argv[1] = rb_ary_pop(value_stack); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("InterpolatedSymbolNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_INTERPOLATED_X_STRING_NODE: { - yp_interpolated_x_string_node_t *cast = (yp_interpolated_x_string_node_t *) node; - VALUE argv[4]; - - // opening_loc - argv[0] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // parts - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->parts.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->parts.nodes[index], source, encoding, constants)); - } + // operator_loc + argv[2] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("InterpolatedXStringNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_KEYWORD_HASH_NODE: { - yp_keyword_hash_node_t *cast = (yp_keyword_hash_node_t *) node; - VALUE argv[2]; - - // elements - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->elements.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->elements.nodes[index], source, encoding, constants)); - } + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPClassVariableWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_OPERATOR_AND_WRITE_NODE: { + yp_constant_operator_and_write_node_t *cast = (yp_constant_operator_and_write_node_t *) node; + VALUE argv[4]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("KeywordHashNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_KEYWORD_PARAMETER_NODE: { - yp_keyword_parameter_node_t *cast = (yp_keyword_parameter_node_t *) node; - VALUE argv[3]; + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // value + argv[2] = rb_ary_pop(value_stack); - // value - argv[1] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("KeywordParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_KEYWORD_REST_PARAMETER_NODE: { - yp_keyword_rest_parameter_node_t *cast = (yp_keyword_rest_parameter_node_t *) node; - VALUE argv[3]; + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPConstantOperatorAndWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_OPERATOR_OR_WRITE_NODE: { + yp_constant_operator_or_write_node_t *cast = (yp_constant_operator_or_write_node_t *) node; + VALUE argv[4]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // operator_loc - argv[0] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // name_loc - argv[1] = cast->name_loc.start == NULL ? Qnil : location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("KeywordRestParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_LAMBDA_NODE: { - yp_lambda_node_t *cast = (yp_lambda_node_t *) node; - VALUE argv[5]; - - // locals - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); - } + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // opening_loc - argv[1] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPConstantOperatorOrWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_OPERATOR_WRITE_NODE: { + yp_constant_operator_write_node_t *cast = (yp_constant_operator_write_node_t *) node; + VALUE argv[5]; - // parameters - argv[2] = cast->parameters == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->parameters, source, encoding, constants); + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // statements - argv[3] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("LambdaNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE: { - yp_local_variable_operator_and_write_node_t *cast = (yp_local_variable_operator_and_write_node_t *) node; - VALUE argv[5]; + // value + argv[2] = rb_ary_pop(value_stack); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // operator + argv[3] = rb_id2sym(constants[cast->operator - 1]); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPConstantOperatorWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_NODE: { + yp_constant_path_node_t *cast = (yp_constant_path_node_t *) node; + VALUE argv[4]; + + // parent + argv[0] = rb_ary_pop(value_stack); - // constant_id - argv[3] = rb_id2sym(constants[cast->constant_id - 1]); + // child + argv[1] = rb_ary_pop(value_stack); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("LocalVariableOperatorAndWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE: { - yp_local_variable_operator_or_write_node_t *cast = (yp_local_variable_operator_or_write_node_t *) node; - VALUE argv[5]; + // delimiter_loc + argv[2] = yp_location_new(parser, cast->delimiter_loc.start, cast->delimiter_loc.end, source); - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPConstantPathNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_OPERATOR_AND_WRITE_NODE: { + yp_constant_path_operator_and_write_node_t *cast = (yp_constant_path_operator_and_write_node_t *) node; + VALUE argv[4]; - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // target + argv[0] = rb_ary_pop(value_stack); - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // constant_id - argv[3] = rb_id2sym(constants[cast->constant_id - 1]); + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("LocalVariableOperatorOrWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { - yp_local_variable_operator_write_node_t *cast = (yp_local_variable_operator_write_node_t *) node; - VALUE argv[6]; + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPConstantPathOperatorAndWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_OPERATOR_OR_WRITE_NODE: { + yp_constant_path_operator_or_write_node_t *cast = (yp_constant_path_operator_or_write_node_t *) node; + VALUE argv[4]; - // name_loc - argv[0] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // target + argv[0] = rb_ary_pop(value_stack); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // value - argv[2] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // value + argv[2] = rb_ary_pop(value_stack); - // constant_id - argv[3] = rb_id2sym(constants[cast->constant_id - 1]); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // operator_id - argv[4] = rb_id2sym(constants[cast->operator_id - 1]); + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPConstantPathOperatorOrWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_OPERATOR_WRITE_NODE: { + yp_constant_path_operator_write_node_t *cast = (yp_constant_path_operator_write_node_t *) node; + VALUE argv[5]; - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("LocalVariableOperatorWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_LOCAL_VARIABLE_READ_NODE: { - yp_local_variable_read_node_t *cast = (yp_local_variable_read_node_t *) node; - VALUE argv[3]; + // target + argv[0] = rb_ary_pop(value_stack); - // constant_id - argv[0] = rb_id2sym(constants[cast->constant_id - 1]); + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // depth - argv[1] = ULONG2NUM(cast->depth); + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("LocalVariableReadNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_LOCAL_VARIABLE_WRITE_NODE: { - yp_local_variable_write_node_t *cast = (yp_local_variable_write_node_t *) node; - VALUE argv[6]; + // operator + argv[3] = rb_id2sym(constants[cast->operator - 1]); - // constant_id - argv[0] = rb_id2sym(constants[cast->constant_id - 1]); + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // depth - argv[1] = ULONG2NUM(cast->depth); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPConstantPathOperatorWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_PATH_WRITE_NODE: { + yp_constant_path_write_node_t *cast = (yp_constant_path_write_node_t *) node; + VALUE argv[4]; - // value - argv[2] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // target + argv[0] = rb_ary_pop(value_stack); - // name_loc - argv[3] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // operator_loc + argv[1] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // operator_loc - argv[4] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("LocalVariableWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_MATCH_PREDICATE_NODE: { - yp_match_predicate_node_t *cast = (yp_match_predicate_node_t *) node; - VALUE argv[4]; + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // value - argv[0] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPConstantPathWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_READ_NODE: { + VALUE argv[1]; - // pattern - argv[1] = yp_node_new(parser, (yp_node_t *) cast->pattern, source, encoding, constants); + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPConstantReadNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_CONSTANT_WRITE_NODE: { + yp_constant_write_node_t *cast = (yp_constant_write_node_t *) node; + VALUE argv[4]; - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("MatchPredicateNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_MATCH_REQUIRED_NODE: { - yp_match_required_node_t *cast = (yp_match_required_node_t *) node; - VALUE argv[4]; + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // value - argv[0] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // value + argv[1] = rb_ary_pop(value_stack); - // pattern - argv[1] = yp_node_new(parser, (yp_node_t *) cast->pattern, source, encoding, constants); + // operator_loc + argv[2] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("MatchRequiredNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_MISSING_NODE: { - VALUE argv[1]; + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPConstantWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_DEF_NODE: { + yp_def_node_t *cast = (yp_def_node_t *) node; + VALUE argv[12]; - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("MissingNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_MODULE_NODE: { - yp_module_node_t *cast = (yp_module_node_t *) node; - VALUE argv[6]; - - // locals - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); - } + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // module_keyword_loc - argv[1] = location_new(parser, cast->module_keyword_loc.start, cast->module_keyword_loc.end, source); + // receiver + argv[1] = rb_ary_pop(value_stack); - // constant_path - argv[2] = yp_node_new(parser, (yp_node_t *) cast->constant_path, source, encoding, constants); + // parameters + argv[2] = rb_ary_pop(value_stack); - // statements - argv[3] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // statements + argv[3] = rb_ary_pop(value_stack); - // end_keyword_loc - argv[4] = location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + // locals + argv[4] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + rb_ary_push(argv[4], rb_id2sym(constants[cast->locals.ids[index] - 1])); + } - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("ModuleNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_MULTI_WRITE_NODE: { - yp_multi_write_node_t *cast = (yp_multi_write_node_t *) node; - VALUE argv[6]; - - // targets - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->targets.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->targets.nodes[index], source, encoding, constants)); - } + // def_keyword_loc + argv[5] = yp_location_new(parser, cast->def_keyword_loc.start, cast->def_keyword_loc.end, source); - // operator_loc - argv[1] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // operator_loc + argv[6] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // value - argv[2] = cast->value == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // lparen_loc + argv[7] = cast->lparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); - // lparen_loc - argv[3] = cast->lparen_loc.start == NULL ? Qnil : location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); + // rparen_loc + argv[8] = cast->rparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); - // rparen_loc - argv[4] = cast->rparen_loc.start == NULL ? Qnil : location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); + // equal_loc + argv[9] = cast->equal_loc.start == NULL ? Qnil : yp_location_new(parser, cast->equal_loc.start, cast->equal_loc.end, source); - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("MultiWriteNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_NEXT_NODE: { - yp_next_node_t *cast = (yp_next_node_t *) node; - VALUE argv[3]; + // end_keyword_loc + argv[10] = cast->end_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - // arguments - argv[0] = cast->arguments == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->arguments, source, encoding, constants); + // location + argv[11] = yp_location_new(parser, node->location.start, node->location.end, source); - // keyword_loc - argv[1] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(12, argv, rb_cYARPDefNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_DEFINED_NODE: { + yp_defined_node_t *cast = (yp_defined_node_t *) node; + VALUE argv[5]; - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("NextNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_NIL_NODE: { - VALUE argv[1]; + // lparen_loc + argv[0] = cast->lparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("NilNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_NO_KEYWORDS_PARAMETER_NODE: { - yp_no_keywords_parameter_node_t *cast = (yp_no_keywords_parameter_node_t *) node; - VALUE argv[3]; + // value + argv[1] = rb_ary_pop(value_stack); - // operator_loc - argv[0] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // rparen_loc + argv[2] = cast->rparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); - // keyword_loc - argv[1] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + // keyword_loc + argv[3] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("NoKeywordsParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_NUMBERED_REFERENCE_READ_NODE: { - VALUE argv[1]; + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("NumberedReferenceReadNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_OPTIONAL_PARAMETER_NODE: { - yp_optional_parameter_node_t *cast = (yp_optional_parameter_node_t *) node; - VALUE argv[5]; + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPDefinedNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ELSE_NODE: { + yp_else_node_t *cast = (yp_else_node_t *) node; + VALUE argv[4]; - // constant_id - argv[0] = rb_id2sym(constants[cast->constant_id - 1]); + // else_keyword_loc + argv[0] = yp_location_new(parser, cast->else_keyword_loc.start, cast->else_keyword_loc.end, source); - // name_loc - argv[1] = location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // statements + argv[1] = rb_ary_pop(value_stack); - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // end_keyword_loc + argv[2] = cast->end_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - // value - argv[3] = yp_node_new(parser, (yp_node_t *) cast->value, source, encoding, constants); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("OptionalParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_OR_NODE: { - yp_or_node_t *cast = (yp_or_node_t *) node; - VALUE argv[4]; + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPElseNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_EMBEDDED_STATEMENTS_NODE: { + yp_embedded_statements_node_t *cast = (yp_embedded_statements_node_t *) node; + VALUE argv[4]; - // left - argv[0] = yp_node_new(parser, (yp_node_t *) cast->left, source, encoding, constants); + // opening_loc + argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - // right - argv[1] = yp_node_new(parser, (yp_node_t *) cast->right, source, encoding, constants); + // statements + argv[1] = rb_ary_pop(value_stack); - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("OrNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_PARAMETERS_NODE: { - yp_parameters_node_t *cast = (yp_parameters_node_t *) node; - VALUE argv[8]; - - // requireds - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->requireds.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->requireds.nodes[index], source, encoding, constants)); - } + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // optionals - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->optionals.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->optionals.nodes[index], source, encoding, constants)); - } + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPEmbeddedStatementsNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_EMBEDDED_VARIABLE_NODE: { + yp_embedded_variable_node_t *cast = (yp_embedded_variable_node_t *) node; + VALUE argv[3]; - // posts - argv[2] = rb_ary_new(); - for (size_t index = 0; index < cast->posts.size; index++) { - rb_ary_push(argv[2], yp_node_new(parser, cast->posts.nodes[index], source, encoding, constants)); - } + // operator_loc + argv[0] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // rest - argv[3] = cast->rest == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->rest, source, encoding, constants); + // variable + argv[1] = rb_ary_pop(value_stack); - // keywords - argv[4] = rb_ary_new(); - for (size_t index = 0; index < cast->keywords.size; index++) { - rb_ary_push(argv[4], yp_node_new(parser, cast->keywords.nodes[index], source, encoding, constants)); - } + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); - // keyword_rest - argv[5] = cast->keyword_rest == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->keyword_rest, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPEmbeddedVariableNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_ENSURE_NODE: { + yp_ensure_node_t *cast = (yp_ensure_node_t *) node; + VALUE argv[4]; - // block - argv[6] = cast->block == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->block, source, encoding, constants); + // ensure_keyword_loc + argv[0] = yp_location_new(parser, cast->ensure_keyword_loc.start, cast->ensure_keyword_loc.end, source); - // location - argv[7] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(8, argv, rb_const_get_at(rb_cYARP, rb_intern("ParametersNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_PARENTHESES_NODE: { - yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node; - VALUE argv[4]; + // statements + argv[1] = rb_ary_pop(value_stack); - // statements - argv[0] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // end_keyword_loc + argv[2] = yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - // opening_loc - argv[1] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPEnsureNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FALSE_NODE: { + VALUE argv[1]; - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("ParenthesesNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_PINNED_EXPRESSION_NODE: { - yp_pinned_expression_node_t *cast = (yp_pinned_expression_node_t *) node; - VALUE argv[5]; + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); - // expression - argv[0] = yp_node_new(parser, (yp_node_t *) cast->expression, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPFalseNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FIND_PATTERN_NODE: { + yp_find_pattern_node_t *cast = (yp_find_pattern_node_t *) node; + VALUE argv[7]; - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // constant + argv[0] = rb_ary_pop(value_stack); + + // left + argv[1] = rb_ary_pop(value_stack); + + // requireds + argv[2] = rb_ary_new(); + for (size_t index = 0; index < cast->requireds.size; index++) { + rb_ary_push(argv[2], rb_ary_pop(value_stack)); + } - // lparen_loc - argv[2] = location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); + // right + argv[3] = rb_ary_pop(value_stack); + + // opening_loc + argv[4] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // closing_loc + argv[5] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[6] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(7, argv, rb_cYARPFindPatternNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FLIP_FLOP_NODE: { + yp_flip_flop_node_t *cast = (yp_flip_flop_node_t *) node; + VALUE argv[5]; + + // left + argv[0] = rb_ary_pop(value_stack); + + // right + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // flags + argv[3] = ULONG2NUM(node->flags >> 1); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPFlipFlopNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FLOAT_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPFloatNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FOR_NODE: { + yp_for_node_t *cast = (yp_for_node_t *) node; + VALUE argv[8]; + + // index + argv[0] = rb_ary_pop(value_stack); + + // collection + argv[1] = rb_ary_pop(value_stack); + + // statements + argv[2] = rb_ary_pop(value_stack); + + // for_keyword_loc + argv[3] = yp_location_new(parser, cast->for_keyword_loc.start, cast->for_keyword_loc.end, source); + + // in_keyword_loc + argv[4] = yp_location_new(parser, cast->in_keyword_loc.start, cast->in_keyword_loc.end, source); + + // do_keyword_loc + argv[5] = cast->do_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->do_keyword_loc.start, cast->do_keyword_loc.end, source); + + // end_keyword_loc + argv[6] = yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - // rparen_loc - argv[3] = location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); + // location + argv[7] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("PinnedExpressionNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_PINNED_VARIABLE_NODE: { - yp_pinned_variable_node_t *cast = (yp_pinned_variable_node_t *) node; - VALUE argv[3]; + rb_ary_push(value_stack, rb_class_new_instance(8, argv, rb_cYARPForNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FORWARDING_ARGUMENTS_NODE: { + VALUE argv[1]; - // variable - argv[0] = yp_node_new(parser, (yp_node_t *) cast->variable, source, encoding, constants); + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); - // operator_loc - argv[1] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPForwardingArgumentsNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FORWARDING_PARAMETER_NODE: { + VALUE argv[1]; - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("PinnedVariableNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_POST_EXECUTION_NODE: { - yp_post_execution_node_t *cast = (yp_post_execution_node_t *) node; - VALUE argv[5]; + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); - // statements - argv[0] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPForwardingParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_FORWARDING_SUPER_NODE: { + VALUE argv[2]; - // keyword_loc - argv[1] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + // block + argv[0] = rb_ary_pop(value_stack); + + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPForwardingSuperNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_global_variable_operator_and_write_node_t *cast = (yp_global_variable_operator_and_write_node_t *) node; + VALUE argv[4]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPGlobalVariableOperatorAndWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_global_variable_operator_or_write_node_t *cast = (yp_global_variable_operator_or_write_node_t *) node; + VALUE argv[4]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPGlobalVariableOperatorOrWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: { + yp_global_variable_operator_write_node_t *cast = (yp_global_variable_operator_write_node_t *) node; + VALUE argv[5]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); + + // operator + argv[3] = rb_id2sym(constants[cast->operator - 1]); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPGlobalVariableOperatorWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_READ_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPGlobalVariableReadNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_GLOBAL_VARIABLE_WRITE_NODE: { + yp_global_variable_write_node_t *cast = (yp_global_variable_write_node_t *) node; + VALUE argv[4]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // opening_loc - argv[2] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + // operator_loc + argv[1] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPGlobalVariableWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_HASH_NODE: { + yp_hash_node_t *cast = (yp_hash_node_t *) node; + VALUE argv[4]; + + // opening_loc + argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - // closing_loc - argv[3] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // elements + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->elements.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("PostExecutionNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_PRE_EXECUTION_NODE: { - yp_pre_execution_node_t *cast = (yp_pre_execution_node_t *) node; - VALUE argv[5]; + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPHashNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_HASH_PATTERN_NODE: { + yp_hash_pattern_node_t *cast = (yp_hash_pattern_node_t *) node; + VALUE argv[6]; - // statements - argv[0] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // keyword_loc - argv[1] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // opening_loc - argv[2] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // closing_loc - argv[3] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("PreExecutionNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_PROGRAM_NODE: { - yp_program_node_t *cast = (yp_program_node_t *) node; - VALUE argv[3]; - - // locals - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); - } + // constant + argv[0] = rb_ary_pop(value_stack); - // statements - argv[1] = yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // assocs + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->assocs.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // kwrest + argv[2] = rb_ary_pop(value_stack); + + // opening_loc + argv[3] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // closing_loc + argv[4] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("ProgramNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_RANGE_NODE: { - yp_range_node_t *cast = (yp_range_node_t *) node; - VALUE argv[5]; + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPHashPatternNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_IF_NODE: { + yp_if_node_t *cast = (yp_if_node_t *) node; + VALUE argv[6]; + + // if_keyword_loc + argv[0] = cast->if_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->if_keyword_loc.start, cast->if_keyword_loc.end, source); + + // predicate + argv[1] = rb_ary_pop(value_stack); + + // statements + argv[2] = rb_ary_pop(value_stack); + + // consequent + argv[3] = rb_ary_pop(value_stack); + + // end_keyword_loc + argv[4] = cast->end_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); - // left - argv[0] = cast->left == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->left, source, encoding, constants); + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); - // right - argv[1] = cast->right == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->right, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPIfNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_IMAGINARY_NODE: { + VALUE argv[2]; - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // numeric + argv[0] = rb_ary_pop(value_stack); - // flags - argv[3] = ULONG2NUM(cast->flags); + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("RangeNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_RATIONAL_NODE: { - yp_rational_node_t *cast = (yp_rational_node_t *) node; - VALUE argv[2]; + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPImaginaryNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_IN_NODE: { + yp_in_node_t *cast = (yp_in_node_t *) node; + VALUE argv[5]; + + // pattern + argv[0] = rb_ary_pop(value_stack); + + // statements + argv[1] = rb_ary_pop(value_stack); - // numeric - argv[0] = yp_node_new(parser, (yp_node_t *) cast->numeric, source, encoding, constants); + // in_loc + argv[2] = yp_location_new(parser, cast->in_loc.start, cast->in_loc.end, source); - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("RationalNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_REDO_NODE: { - VALUE argv[1]; + // then_loc + argv[3] = cast->then_loc.start == NULL ? Qnil : yp_location_new(parser, cast->then_loc.start, cast->then_loc.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("RedoNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_REGULAR_EXPRESSION_NODE: { - yp_regular_expression_node_t *cast = (yp_regular_expression_node_t *) node; - VALUE argv[6]; + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // opening_loc - argv[0] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPInNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_instance_variable_operator_and_write_node_t *cast = (yp_instance_variable_operator_and_write_node_t *) node; + VALUE argv[4]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // content_loc - argv[1] = location_new(parser, cast->content_loc.start, cast->content_loc.end, source); + // value + argv[2] = rb_ary_pop(value_stack); - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // unescaped - argv[3] = yp_string_new(&cast->unescaped, encoding); + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPInstanceVariableOperatorAndWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_instance_variable_operator_or_write_node_t *cast = (yp_instance_variable_operator_or_write_node_t *) node; + VALUE argv[4]; - // flags - argv[4] = ULONG2NUM(cast->flags); + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("RegularExpressionNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { - yp_required_destructured_parameter_node_t *cast = (yp_required_destructured_parameter_node_t *) node; - VALUE argv[4]; - - // parameters - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->parameters.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->parameters.nodes[index], source, encoding, constants)); - } + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPInstanceVariableOperatorOrWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: { + yp_instance_variable_operator_write_node_t *cast = (yp_instance_variable_operator_write_node_t *) node; + VALUE argv[5]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); + + // operator + argv[3] = rb_id2sym(constants[cast->operator - 1]); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPInstanceVariableOperatorWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_READ_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPInstanceVariableReadNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INSTANCE_VARIABLE_WRITE_NODE: { + yp_instance_variable_write_node_t *cast = (yp_instance_variable_write_node_t *) node; + VALUE argv[4]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // value + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPInstanceVariableWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INTEGER_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPIntegerNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INTERPOLATED_REGULAR_EXPRESSION_NODE: { + yp_interpolated_regular_expression_node_t *cast = (yp_interpolated_regular_expression_node_t *) node; + VALUE argv[5]; + + // opening_loc + argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // parts + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->parts.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // flags + argv[3] = ULONG2NUM(node->flags >> 1); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPInterpolatedRegularExpressionNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INTERPOLATED_STRING_NODE: { + yp_interpolated_string_node_t *cast = (yp_interpolated_string_node_t *) node; + VALUE argv[4]; + + // opening_loc + argv[0] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // parts + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->parts.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // closing_loc + argv[2] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPInterpolatedStringNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INTERPOLATED_SYMBOL_NODE: { + yp_interpolated_symbol_node_t *cast = (yp_interpolated_symbol_node_t *) node; + VALUE argv[4]; + + // opening_loc + argv[0] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // parts + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->parts.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // closing_loc + argv[2] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPInterpolatedSymbolNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_INTERPOLATED_X_STRING_NODE: { + yp_interpolated_x_string_node_t *cast = (yp_interpolated_x_string_node_t *) node; + VALUE argv[4]; + + // opening_loc + argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // parts + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->parts.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPInterpolatedXStringNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_KEYWORD_HASH_NODE: { + yp_keyword_hash_node_t *cast = (yp_keyword_hash_node_t *) node; + VALUE argv[2]; + + // elements + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->elements.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } + + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPKeywordHashNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_KEYWORD_PARAMETER_NODE: { + yp_keyword_parameter_node_t *cast = (yp_keyword_parameter_node_t *) node; + VALUE argv[3]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // value + argv[1] = rb_ary_pop(value_stack); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPKeywordParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_KEYWORD_REST_PARAMETER_NODE: { + yp_keyword_rest_parameter_node_t *cast = (yp_keyword_rest_parameter_node_t *) node; + VALUE argv[3]; + + // operator_loc + argv[0] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // name_loc + argv[1] = cast->name_loc.start == NULL ? Qnil : yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPKeywordRestParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_LAMBDA_NODE: { + yp_lambda_node_t *cast = (yp_lambda_node_t *) node; + VALUE argv[5]; + + // locals + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); + } + + // opening_loc + argv[1] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // parameters + argv[2] = rb_ary_pop(value_stack); + + // statements + argv[3] = rb_ary_pop(value_stack); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPLambdaNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE: { + yp_local_variable_operator_and_write_node_t *cast = (yp_local_variable_operator_and_write_node_t *) node; + VALUE argv[5]; + + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); - // opening_loc - argv[1] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + // constant_id + argv[3] = rb_id2sym(constants[cast->constant_id - 1]); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPLocalVariableOperatorAndWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE: { + yp_local_variable_operator_or_write_node_t *cast = (yp_local_variable_operator_or_write_node_t *) node; + VALUE argv[5]; - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("RequiredDestructuredParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_REQUIRED_PARAMETER_NODE: { - yp_required_parameter_node_t *cast = (yp_required_parameter_node_t *) node; - VALUE argv[2]; + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // constant_id - argv[0] = rb_id2sym(constants[cast->constant_id - 1]); + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("RequiredParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_RESCUE_MODIFIER_NODE: { - yp_rescue_modifier_node_t *cast = (yp_rescue_modifier_node_t *) node; - VALUE argv[4]; + // constant_id + argv[3] = rb_id2sym(constants[cast->constant_id - 1]); - // expression - argv[0] = yp_node_new(parser, (yp_node_t *) cast->expression, source, encoding, constants); + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // keyword_loc - argv[1] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPLocalVariableOperatorOrWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { + yp_local_variable_operator_write_node_t *cast = (yp_local_variable_operator_write_node_t *) node; + VALUE argv[6]; - // rescue_expression - argv[2] = yp_node_new(parser, (yp_node_t *) cast->rescue_expression, source, encoding, constants); + // name_loc + argv[0] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("RescueModifierNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_RESCUE_NODE: { - yp_rescue_node_t *cast = (yp_rescue_node_t *) node; - VALUE argv[7]; - - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // exceptions - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->exceptions.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->exceptions.nodes[index], source, encoding, constants)); - } + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // operator_loc - argv[2] = cast->operator_loc.start == NULL ? Qnil : location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // value + argv[2] = rb_ary_pop(value_stack); - // exception - argv[3] = cast->exception == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->exception, source, encoding, constants); + // constant_id + argv[3] = rb_id2sym(constants[cast->constant_id - 1]); - // statements - argv[4] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // operator_id + argv[4] = rb_id2sym(constants[cast->operator_id - 1]); - // consequent - argv[5] = cast->consequent == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->consequent, source, encoding, constants); + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPLocalVariableOperatorWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_READ_NODE: { + yp_local_variable_read_node_t *cast = (yp_local_variable_read_node_t *) node; + VALUE argv[3]; - // location - argv[6] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(7, argv, rb_const_get_at(rb_cYARP, rb_intern("RescueNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_REST_PARAMETER_NODE: { - yp_rest_parameter_node_t *cast = (yp_rest_parameter_node_t *) node; - VALUE argv[3]; + // constant_id + argv[0] = rb_id2sym(constants[cast->constant_id - 1]); - // operator_loc - argv[0] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // depth + argv[1] = ULONG2NUM(cast->depth); - // name_loc - argv[1] = cast->name_loc.start == NULL ? Qnil : location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("RestParameterNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_RETRY_NODE: { - VALUE argv[1]; + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPLocalVariableReadNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_LOCAL_VARIABLE_WRITE_NODE: { + yp_local_variable_write_node_t *cast = (yp_local_variable_write_node_t *) node; + VALUE argv[6]; - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("RetryNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_RETURN_NODE: { - yp_return_node_t *cast = (yp_return_node_t *) node; - VALUE argv[3]; + // constant_id + argv[0] = rb_id2sym(constants[cast->constant_id - 1]); - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + // depth + argv[1] = ULONG2NUM(cast->depth); - // arguments - argv[1] = cast->arguments == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->arguments, source, encoding, constants); + // value + argv[2] = rb_ary_pop(value_stack); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("ReturnNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SELF_NODE: { - VALUE argv[1]; + // name_loc + argv[3] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("SelfNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SINGLETON_CLASS_NODE: { - yp_singleton_class_node_t *cast = (yp_singleton_class_node_t *) node; - VALUE argv[7]; - - // locals - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->locals.size; index++) { - rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); - } + // operator_loc + argv[4] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // class_keyword_loc - argv[1] = location_new(parser, cast->class_keyword_loc.start, cast->class_keyword_loc.end, source); + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); - // operator_loc - argv[2] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPLocalVariableWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_MATCH_PREDICATE_NODE: { + yp_match_predicate_node_t *cast = (yp_match_predicate_node_t *) node; + VALUE argv[4]; - // expression - argv[3] = yp_node_new(parser, (yp_node_t *) cast->expression, source, encoding, constants); + // value + argv[0] = rb_ary_pop(value_stack); - // statements - argv[4] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // pattern + argv[1] = rb_ary_pop(value_stack); - // end_keyword_loc - argv[5] = location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // location - argv[6] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(7, argv, rb_const_get_at(rb_cYARP, rb_intern("SingletonClassNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SOURCE_ENCODING_NODE: { - VALUE argv[1]; + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("SourceEncodingNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SOURCE_FILE_NODE: { - yp_source_file_node_t *cast = (yp_source_file_node_t *) node; - VALUE argv[2]; + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPMatchPredicateNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_MATCH_REQUIRED_NODE: { + yp_match_required_node_t *cast = (yp_match_required_node_t *) node; + VALUE argv[4]; - // filepath - argv[0] = yp_string_new(&cast->filepath, encoding); + // value + argv[0] = rb_ary_pop(value_stack); + + // pattern + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("SourceFileNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SOURCE_LINE_NODE: { - VALUE argv[1]; + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPMatchRequiredNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_MISSING_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPMissingNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_MODULE_NODE: { + yp_module_node_t *cast = (yp_module_node_t *) node; + VALUE argv[6]; + + // locals + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); + } + + // module_keyword_loc + argv[1] = yp_location_new(parser, cast->module_keyword_loc.start, cast->module_keyword_loc.end, source); + + // constant_path + argv[2] = rb_ary_pop(value_stack); + + // statements + argv[3] = rb_ary_pop(value_stack); + + // end_keyword_loc + argv[4] = yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPModuleNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_MULTI_WRITE_NODE: { + yp_multi_write_node_t *cast = (yp_multi_write_node_t *) node; + VALUE argv[6]; + + // targets + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->targets.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } + + // operator_loc + argv[1] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[2] = rb_ary_pop(value_stack); + + // lparen_loc + argv[3] = cast->lparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); + + // rparen_loc + argv[4] = cast->rparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); + + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPMultiWriteNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_NEXT_NODE: { + yp_next_node_t *cast = (yp_next_node_t *) node; + VALUE argv[3]; + + // arguments + argv[0] = rb_ary_pop(value_stack); + + // keyword_loc + argv[1] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPNextNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_NIL_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPNilNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_NO_KEYWORDS_PARAMETER_NODE: { + yp_no_keywords_parameter_node_t *cast = (yp_no_keywords_parameter_node_t *) node; + VALUE argv[3]; + + // operator_loc + argv[0] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // keyword_loc + argv[1] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPNoKeywordsParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_NUMBERED_REFERENCE_READ_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPNumberedReferenceReadNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_OPTIONAL_PARAMETER_NODE: { + yp_optional_parameter_node_t *cast = (yp_optional_parameter_node_t *) node; + VALUE argv[5]; + + // constant_id + argv[0] = rb_id2sym(constants[cast->constant_id - 1]); + + // name_loc + argv[1] = yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // value + argv[3] = rb_ary_pop(value_stack); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPOptionalParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_OR_NODE: { + yp_or_node_t *cast = (yp_or_node_t *) node; + VALUE argv[4]; + + // left + argv[0] = rb_ary_pop(value_stack); + + // right + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPOrNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_PARAMETERS_NODE: { + yp_parameters_node_t *cast = (yp_parameters_node_t *) node; + VALUE argv[8]; + + // requireds + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->requireds.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } + + // optionals + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->optionals.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // posts + argv[2] = rb_ary_new(); + for (size_t index = 0; index < cast->posts.size; index++) { + rb_ary_push(argv[2], rb_ary_pop(value_stack)); + } + + // rest + argv[3] = rb_ary_pop(value_stack); + + // keywords + argv[4] = rb_ary_new(); + for (size_t index = 0; index < cast->keywords.size; index++) { + rb_ary_push(argv[4], rb_ary_pop(value_stack)); + } + + // keyword_rest + argv[5] = rb_ary_pop(value_stack); + + // block + argv[6] = rb_ary_pop(value_stack); + + // location + argv[7] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(8, argv, rb_cYARPParametersNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_PARENTHESES_NODE: { + yp_parentheses_node_t *cast = (yp_parentheses_node_t *) node; + VALUE argv[4]; + + // statements + argv[0] = rb_ary_pop(value_stack); + + // opening_loc + argv[1] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPParenthesesNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_PINNED_EXPRESSION_NODE: { + yp_pinned_expression_node_t *cast = (yp_pinned_expression_node_t *) node; + VALUE argv[5]; + + // expression + argv[0] = rb_ary_pop(value_stack); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // lparen_loc + argv[2] = yp_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); + + // rparen_loc + argv[3] = yp_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPPinnedExpressionNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_PINNED_VARIABLE_NODE: { + yp_pinned_variable_node_t *cast = (yp_pinned_variable_node_t *) node; + VALUE argv[3]; + + // variable + argv[0] = rb_ary_pop(value_stack); + + // operator_loc + argv[1] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPPinnedVariableNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_POST_EXECUTION_NODE: { + yp_post_execution_node_t *cast = (yp_post_execution_node_t *) node; + VALUE argv[5]; + + // statements + argv[0] = rb_ary_pop(value_stack); + + // keyword_loc + argv[1] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // opening_loc + argv[2] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // closing_loc + argv[3] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPPostExecutionNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_PRE_EXECUTION_NODE: { + yp_pre_execution_node_t *cast = (yp_pre_execution_node_t *) node; + VALUE argv[5]; - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("SourceLineNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SPLAT_NODE: { - yp_splat_node_t *cast = (yp_splat_node_t *) node; - VALUE argv[3]; + // statements + argv[0] = rb_ary_pop(value_stack); - // operator_loc - argv[0] = location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + // keyword_loc + argv[1] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // expression - argv[1] = cast->expression == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->expression, source, encoding, constants); + // opening_loc + argv[2] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("SplatNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_STATEMENTS_NODE: { - yp_statements_node_t *cast = (yp_statements_node_t *) node; - VALUE argv[2]; - - // body - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->body.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->body.nodes[index], source, encoding, constants)); - } + // closing_loc + argv[3] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[1] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(2, argv, rb_const_get_at(rb_cYARP, rb_intern("StatementsNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_STRING_CONCAT_NODE: { - yp_string_concat_node_t *cast = (yp_string_concat_node_t *) node; - VALUE argv[3]; + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPPreExecutionNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_PROGRAM_NODE: { + yp_program_node_t *cast = (yp_program_node_t *) node; + VALUE argv[3]; + + // locals + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); + } + + // statements + argv[1] = rb_ary_pop(value_stack); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPProgramNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_RANGE_NODE: { + yp_range_node_t *cast = (yp_range_node_t *) node; + VALUE argv[5]; + + // left + argv[0] = rb_ary_pop(value_stack); + + // right + argv[1] = rb_ary_pop(value_stack); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // flags + argv[3] = ULONG2NUM(node->flags >> 1); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPRangeNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_RATIONAL_NODE: { + VALUE argv[2]; + + // numeric + argv[0] = rb_ary_pop(value_stack); + + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPRationalNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_REDO_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPRedoNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_REGULAR_EXPRESSION_NODE: { + yp_regular_expression_node_t *cast = (yp_regular_expression_node_t *) node; + VALUE argv[6]; + + // opening_loc + argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // content_loc + argv[1] = yp_location_new(parser, cast->content_loc.start, cast->content_loc.end, source); + + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // unescaped + argv[3] = yp_string_new(&cast->unescaped, encoding); + + // flags + argv[4] = ULONG2NUM(node->flags >> 1); + + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPRegularExpressionNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { + yp_required_destructured_parameter_node_t *cast = (yp_required_destructured_parameter_node_t *) node; + VALUE argv[4]; + + // parameters + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->parameters.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } + + // opening_loc + argv[1] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPRequiredDestructuredParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_REQUIRED_PARAMETER_NODE: { + yp_required_parameter_node_t *cast = (yp_required_parameter_node_t *) node; + VALUE argv[2]; + + // constant_id + argv[0] = rb_id2sym(constants[cast->constant_id - 1]); + + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPRequiredParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_RESCUE_MODIFIER_NODE: { + yp_rescue_modifier_node_t *cast = (yp_rescue_modifier_node_t *) node; + VALUE argv[4]; + + // expression + argv[0] = rb_ary_pop(value_stack); + + // keyword_loc + argv[1] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // rescue_expression + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPRescueModifierNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_RESCUE_NODE: { + yp_rescue_node_t *cast = (yp_rescue_node_t *) node; + VALUE argv[7]; + + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // exceptions + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->exceptions.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // operator_loc + argv[2] = cast->operator_loc.start == NULL ? Qnil : yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // reference + argv[3] = rb_ary_pop(value_stack); + + // statements + argv[4] = rb_ary_pop(value_stack); + + // consequent + argv[5] = rb_ary_pop(value_stack); + + // location + argv[6] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(7, argv, rb_cYARPRescueNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_REST_PARAMETER_NODE: { + yp_rest_parameter_node_t *cast = (yp_rest_parameter_node_t *) node; + VALUE argv[3]; + + // operator_loc + argv[0] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // name_loc + argv[1] = cast->name_loc.start == NULL ? Qnil : yp_location_new(parser, cast->name_loc.start, cast->name_loc.end, source); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPRestParameterNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_RETRY_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPRetryNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_RETURN_NODE: { + yp_return_node_t *cast = (yp_return_node_t *) node; + VALUE argv[3]; + + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // arguments + argv[1] = rb_ary_pop(value_stack); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPReturnNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SELF_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPSelfNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SINGLETON_CLASS_NODE: { + yp_singleton_class_node_t *cast = (yp_singleton_class_node_t *) node; + VALUE argv[7]; + + // locals + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->locals.size; index++) { + rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); + } + + // class_keyword_loc + argv[1] = yp_location_new(parser, cast->class_keyword_loc.start, cast->class_keyword_loc.end, source); + + // operator_loc + argv[2] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // expression + argv[3] = rb_ary_pop(value_stack); + + // statements + argv[4] = rb_ary_pop(value_stack); + + // end_keyword_loc + argv[5] = yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + + // location + argv[6] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(7, argv, rb_cYARPSingletonClassNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SOURCE_ENCODING_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPSourceEncodingNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SOURCE_FILE_NODE: { + yp_source_file_node_t *cast = (yp_source_file_node_t *) node; + VALUE argv[2]; + + // filepath + argv[0] = yp_string_new(&cast->filepath, encoding); + + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPSourceFileNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SOURCE_LINE_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPSourceLineNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SPLAT_NODE: { + yp_splat_node_t *cast = (yp_splat_node_t *) node; + VALUE argv[3]; + + // operator_loc + argv[0] = yp_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source); + + // expression + argv[1] = rb_ary_pop(value_stack); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPSplatNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_STATEMENTS_NODE: { + yp_statements_node_t *cast = (yp_statements_node_t *) node; + VALUE argv[2]; + + // body + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->body.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } + + // location + argv[1] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(2, argv, rb_cYARPStatementsNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_STRING_CONCAT_NODE: { + VALUE argv[3]; + + // left + argv[0] = rb_ary_pop(value_stack); + + // right + argv[1] = rb_ary_pop(value_stack); + + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPStringConcatNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_STRING_NODE: { + yp_string_node_t *cast = (yp_string_node_t *) node; + VALUE argv[5]; + + // opening_loc + argv[0] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // content_loc + argv[1] = yp_location_new(parser, cast->content_loc.start, cast->content_loc.end, source); + + // closing_loc + argv[2] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // unescaped + argv[3] = yp_string_new(&cast->unescaped, encoding); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPStringNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SUPER_NODE: { + yp_super_node_t *cast = (yp_super_node_t *) node; + VALUE argv[6]; + + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // lparen_loc + argv[1] = cast->lparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); + + // arguments + argv[2] = rb_ary_pop(value_stack); + + // rparen_loc + argv[3] = cast->rparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); + + // block + argv[4] = rb_ary_pop(value_stack); + + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPSuperNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_SYMBOL_NODE: { + yp_symbol_node_t *cast = (yp_symbol_node_t *) node; + VALUE argv[5]; + + // opening_loc + argv[0] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + + // value_loc + argv[1] = yp_location_new(parser, cast->value_loc.start, cast->value_loc.end, source); + + // closing_loc + argv[2] = cast->closing_loc.start == NULL ? Qnil : yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + + // unescaped + argv[3] = yp_string_new(&cast->unescaped, encoding); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPSymbolNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_TRUE_NODE: { + VALUE argv[1]; + + // location + argv[0] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(1, argv, rb_cYARPTrueNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_UNDEF_NODE: { + yp_undef_node_t *cast = (yp_undef_node_t *) node; + VALUE argv[3]; - // left - argv[0] = yp_node_new(parser, (yp_node_t *) cast->left, source, encoding, constants); + // names + argv[0] = rb_ary_new(); + for (size_t index = 0; index < cast->names.size; index++) { + rb_ary_push(argv[0], rb_ary_pop(value_stack)); + } - // right - argv[1] = yp_node_new(parser, (yp_node_t *) cast->right, source, encoding, constants); + // keyword_loc + argv[1] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("StringConcatNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_STRING_NODE: { - yp_string_node_t *cast = (yp_string_node_t *) node; - VALUE argv[5]; + // location + argv[2] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cYARPUndefNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_UNLESS_NODE: { + yp_unless_node_t *cast = (yp_unless_node_t *) node; + VALUE argv[6]; - // opening_loc - argv[0] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // content_loc - argv[1] = location_new(parser, cast->content_loc.start, cast->content_loc.end, source); + // predicate + argv[1] = rb_ary_pop(value_stack); - // closing_loc - argv[2] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // statements + argv[2] = rb_ary_pop(value_stack); - // unescaped - argv[3] = yp_string_new(&cast->unescaped, encoding); + // consequent + argv[3] = rb_ary_pop(value_stack); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("StringNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SUPER_NODE: { - yp_super_node_t *cast = (yp_super_node_t *) node; - VALUE argv[6]; + // end_keyword_loc + argv[4] = cast->end_keyword_loc.start == NULL ? Qnil : yp_location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + + // location + argv[5] = yp_location_new(parser, node->location.start, node->location.end, source); - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cYARPUnlessNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_UNTIL_NODE: { + yp_until_node_t *cast = (yp_until_node_t *) node; + VALUE argv[5]; - // lparen_loc - argv[1] = cast->lparen_loc.start == NULL ? Qnil : location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // arguments - argv[2] = cast->arguments == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->arguments, source, encoding, constants); + // predicate + argv[1] = rb_ary_pop(value_stack); - // rparen_loc - argv[3] = cast->rparen_loc.start == NULL ? Qnil : location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); + // statements + argv[2] = rb_ary_pop(value_stack); - // block - argv[4] = cast->block == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->block, source, encoding, constants); + // flags + argv[3] = ULONG2NUM(node->flags >> 1); + + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPUntilNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_WHEN_NODE: { + yp_when_node_t *cast = (yp_when_node_t *) node; + VALUE argv[4]; - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("SuperNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_SYMBOL_NODE: { - yp_symbol_node_t *cast = (yp_symbol_node_t *) node; - VALUE argv[5]; + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // opening_loc - argv[0] = cast->opening_loc.start == NULL ? Qnil : location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); + // conditions + argv[1] = rb_ary_new(); + for (size_t index = 0; index < cast->conditions.size; index++) { + rb_ary_push(argv[1], rb_ary_pop(value_stack)); + } + + // statements + argv[2] = rb_ary_pop(value_stack); + + // location + argv[3] = yp_location_new(parser, node->location.start, node->location.end, source); + + rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cYARPWhenNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_WHILE_NODE: { + yp_while_node_t *cast = (yp_while_node_t *) node; + VALUE argv[5]; - // value_loc - argv[1] = location_new(parser, cast->value_loc.start, cast->value_loc.end, source); + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + + // predicate + argv[1] = rb_ary_pop(value_stack); - // closing_loc - argv[2] = cast->closing_loc.start == NULL ? Qnil : location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); + // statements + argv[2] = rb_ary_pop(value_stack); - // unescaped - argv[3] = yp_string_new(&cast->unescaped, encoding); + // flags + argv[3] = ULONG2NUM(node->flags >> 1); - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("SymbolNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_TRUE_NODE: { - VALUE argv[1]; + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[0] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(1, argv, rb_const_get_at(rb_cYARP, rb_intern("TrueNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_UNDEF_NODE: { - yp_undef_node_t *cast = (yp_undef_node_t *) node; - VALUE argv[3]; - - // names - argv[0] = rb_ary_new(); - for (size_t index = 0; index < cast->names.size; index++) { - rb_ary_push(argv[0], yp_node_new(parser, cast->names.nodes[index], source, encoding, constants)); - } + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPWhileNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_X_STRING_NODE: { + yp_x_string_node_t *cast = (yp_x_string_node_t *) node; + VALUE argv[5]; - // keyword_loc - argv[1] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + // opening_loc + argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - // location - argv[2] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(3, argv, rb_const_get_at(rb_cYARP, rb_intern("UndefNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_UNLESS_NODE: { - yp_unless_node_t *cast = (yp_unless_node_t *) node; - VALUE argv[6]; + // content_loc + argv[1] = yp_location_new(parser, cast->content_loc.start, cast->content_loc.end, source); - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + // closing_loc + argv[2] = yp_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - // predicate - argv[1] = yp_node_new(parser, (yp_node_t *) cast->predicate, source, encoding, constants); + // unescaped + argv[3] = yp_string_new(&cast->unescaped, encoding); - // statements - argv[2] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // consequent - argv[3] = cast->consequent == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->consequent, source, encoding, constants); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPXStringNode)); + break; + } +#line 137 "api_node.c.erb" + case YP_NODE_YIELD_NODE: { + yp_yield_node_t *cast = (yp_yield_node_t *) node; + VALUE argv[5]; - // end_keyword_loc - argv[4] = cast->end_keyword_loc.start == NULL ? Qnil : location_new(parser, cast->end_keyword_loc.start, cast->end_keyword_loc.end, source); + // keyword_loc + argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - // location - argv[5] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(6, argv, rb_const_get_at(rb_cYARP, rb_intern("UnlessNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_UNTIL_NODE: { - yp_until_node_t *cast = (yp_until_node_t *) node; - VALUE argv[4]; + // lparen_loc + argv[1] = cast->lparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); + // arguments + argv[2] = rb_ary_pop(value_stack); - // predicate - argv[1] = yp_node_new(parser, (yp_node_t *) cast->predicate, source, encoding, constants); + // rparen_loc + argv[3] = cast->rparen_loc.start == NULL ? Qnil : yp_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); - // statements - argv[2] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); + // location + argv[4] = yp_location_new(parser, node->location.start, node->location.end, source); - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("UntilNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_WHEN_NODE: { - yp_when_node_t *cast = (yp_when_node_t *) node; - VALUE argv[4]; - - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // conditions - argv[1] = rb_ary_new(); - for (size_t index = 0; index < cast->conditions.size; index++) { - rb_ary_push(argv[1], yp_node_new(parser, cast->conditions.nodes[index], source, encoding, constants)); + rb_ary_push(value_stack, rb_class_new_instance(5, argv, rb_cYARPYieldNode)); + break; + } + default: + rb_raise(rb_eRuntimeError, "unknown node type: %d", YP_NODE_TYPE(node)); } - - // statements - argv[2] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("WhenNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_WHILE_NODE: { - yp_while_node_t *cast = (yp_while_node_t *) node; - VALUE argv[4]; - - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // predicate - argv[1] = yp_node_new(parser, (yp_node_t *) cast->predicate, source, encoding, constants); - - // statements - argv[2] = cast->statements == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->statements, source, encoding, constants); - - // location - argv[3] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(4, argv, rb_const_get_at(rb_cYARP, rb_intern("WhileNode"))); } -#line 25 "api_node.c.erb" - case YP_NODE_X_STRING_NODE: { - yp_x_string_node_t *cast = (yp_x_string_node_t *) node; - VALUE argv[5]; - - // opening_loc - argv[0] = location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); - - // content_loc - argv[1] = location_new(parser, cast->content_loc.start, cast->content_loc.end, source); - - // closing_loc - argv[2] = location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source); - - // unescaped - argv[3] = yp_string_new(&cast->unescaped, encoding); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("XStringNode"))); - } -#line 25 "api_node.c.erb" - case YP_NODE_YIELD_NODE: { - yp_yield_node_t *cast = (yp_yield_node_t *) node; - VALUE argv[5]; - - // keyword_loc - argv[0] = location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); - - // lparen_loc - argv[1] = cast->lparen_loc.start == NULL ? Qnil : location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source); - - // arguments - argv[2] = cast->arguments == NULL ? Qnil : yp_node_new(parser, (yp_node_t *) cast->arguments, source, encoding, constants); - - // rparen_loc - argv[3] = cast->rparen_loc.start == NULL ? Qnil : location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source); - - // location - argv[4] = location_new(parser, node->location.start, node->location.end, source); - return rb_class_new_instance(5, argv, rb_const_get_at(rb_cYARP, rb_intern("YieldNode"))); - } - default: - rb_raise(rb_eRuntimeError, "unknown node type: %d", node->type); } -} - -#line 80 "api_node.c.erb" -VALUE -yp_token_new(yp_parser_t *parser, yp_token_t *token, rb_encoding *encoding, VALUE source) { - ID type = rb_intern(yp_token_type_to_str(token->type)); - VALUE location = location_new(parser, token->start, token->end, source); - - VALUE argv[] = { - ID2SYM(type), - rb_enc_str_new(token->start, token->end - token->start, encoding), - location - }; - - return rb_class_new_instance(3, argv, rb_cYARPToken); -} -// Create a YARP::Source object from the given parser. -VALUE -yp_source_new(yp_parser_t *parser) { - VALUE source = rb_str_new(parser->start, parser->end - parser->start); - 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, INT2FIX(parser->newline_list.offsets[index])); - } - - VALUE source_argv[] = { source, offsets }; - return rb_class_new_instance(2, source_argv, rb_cYARPSource); + VALUE result = rb_ary_pop(value_stack); + free(constants); + return result; } -VALUE yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { - VALUE source = yp_source_new(parser); - ID *constants = calloc(parser->constant_pool.size, sizeof(ID)); - - for (size_t index = 0; index < parser->constant_pool.capacity; index++) { - yp_constant_t constant = parser->constant_pool.constants[index]; - - if (constant.id != 0) { - constants[constant.id - 1] = rb_intern3(constant.start, constant.length, encoding); - } - } - - VALUE res_node = yp_node_new(parser, node, source, encoding, constants); - free(constants); - return res_node; +void +Init_yarp_api_node(void) { + rb_cYARPAliasNode = rb_define_class_under(rb_cYARP, "AliasNode", rb_cYARPNode); + rb_cYARPAlternationPatternNode = rb_define_class_under(rb_cYARP, "AlternationPatternNode", rb_cYARPNode); + rb_cYARPAndNode = rb_define_class_under(rb_cYARP, "AndNode", rb_cYARPNode); + rb_cYARPArgumentsNode = rb_define_class_under(rb_cYARP, "ArgumentsNode", rb_cYARPNode); + rb_cYARPArrayNode = rb_define_class_under(rb_cYARP, "ArrayNode", rb_cYARPNode); + rb_cYARPArrayPatternNode = rb_define_class_under(rb_cYARP, "ArrayPatternNode", rb_cYARPNode); + rb_cYARPAssocNode = rb_define_class_under(rb_cYARP, "AssocNode", rb_cYARPNode); + rb_cYARPAssocSplatNode = rb_define_class_under(rb_cYARP, "AssocSplatNode", rb_cYARPNode); + rb_cYARPBackReferenceReadNode = rb_define_class_under(rb_cYARP, "BackReferenceReadNode", rb_cYARPNode); + rb_cYARPBeginNode = rb_define_class_under(rb_cYARP, "BeginNode", rb_cYARPNode); + rb_cYARPBlockArgumentNode = rb_define_class_under(rb_cYARP, "BlockArgumentNode", rb_cYARPNode); + rb_cYARPBlockNode = rb_define_class_under(rb_cYARP, "BlockNode", rb_cYARPNode); + rb_cYARPBlockParameterNode = rb_define_class_under(rb_cYARP, "BlockParameterNode", rb_cYARPNode); + rb_cYARPBlockParametersNode = rb_define_class_under(rb_cYARP, "BlockParametersNode", rb_cYARPNode); + rb_cYARPBreakNode = rb_define_class_under(rb_cYARP, "BreakNode", rb_cYARPNode); + rb_cYARPCallNode = rb_define_class_under(rb_cYARP, "CallNode", rb_cYARPNode); + rb_cYARPCallOperatorAndWriteNode = rb_define_class_under(rb_cYARP, "CallOperatorAndWriteNode", rb_cYARPNode); + rb_cYARPCallOperatorOrWriteNode = rb_define_class_under(rb_cYARP, "CallOperatorOrWriteNode", rb_cYARPNode); + rb_cYARPCallOperatorWriteNode = rb_define_class_under(rb_cYARP, "CallOperatorWriteNode", rb_cYARPNode); + rb_cYARPCapturePatternNode = rb_define_class_under(rb_cYARP, "CapturePatternNode", rb_cYARPNode); + rb_cYARPCaseNode = rb_define_class_under(rb_cYARP, "CaseNode", rb_cYARPNode); + rb_cYARPClassNode = rb_define_class_under(rb_cYARP, "ClassNode", rb_cYARPNode); + rb_cYARPClassVariableOperatorAndWriteNode = rb_define_class_under(rb_cYARP, "ClassVariableOperatorAndWriteNode", rb_cYARPNode); + rb_cYARPClassVariableOperatorOrWriteNode = rb_define_class_under(rb_cYARP, "ClassVariableOperatorOrWriteNode", rb_cYARPNode); + rb_cYARPClassVariableOperatorWriteNode = rb_define_class_under(rb_cYARP, "ClassVariableOperatorWriteNode", rb_cYARPNode); + rb_cYARPClassVariableReadNode = rb_define_class_under(rb_cYARP, "ClassVariableReadNode", rb_cYARPNode); + rb_cYARPClassVariableWriteNode = rb_define_class_under(rb_cYARP, "ClassVariableWriteNode", rb_cYARPNode); + rb_cYARPConstantOperatorAndWriteNode = rb_define_class_under(rb_cYARP, "ConstantOperatorAndWriteNode", rb_cYARPNode); + rb_cYARPConstantOperatorOrWriteNode = rb_define_class_under(rb_cYARP, "ConstantOperatorOrWriteNode", rb_cYARPNode); + rb_cYARPConstantOperatorWriteNode = rb_define_class_under(rb_cYARP, "ConstantOperatorWriteNode", rb_cYARPNode); + rb_cYARPConstantPathNode = rb_define_class_under(rb_cYARP, "ConstantPathNode", rb_cYARPNode); + rb_cYARPConstantPathOperatorAndWriteNode = rb_define_class_under(rb_cYARP, "ConstantPathOperatorAndWriteNode", rb_cYARPNode); + rb_cYARPConstantPathOperatorOrWriteNode = rb_define_class_under(rb_cYARP, "ConstantPathOperatorOrWriteNode", rb_cYARPNode); + rb_cYARPConstantPathOperatorWriteNode = rb_define_class_under(rb_cYARP, "ConstantPathOperatorWriteNode", rb_cYARPNode); + rb_cYARPConstantPathWriteNode = rb_define_class_under(rb_cYARP, "ConstantPathWriteNode", rb_cYARPNode); + rb_cYARPConstantReadNode = rb_define_class_under(rb_cYARP, "ConstantReadNode", rb_cYARPNode); + rb_cYARPConstantWriteNode = rb_define_class_under(rb_cYARP, "ConstantWriteNode", rb_cYARPNode); + rb_cYARPDefNode = rb_define_class_under(rb_cYARP, "DefNode", rb_cYARPNode); + rb_cYARPDefinedNode = rb_define_class_under(rb_cYARP, "DefinedNode", rb_cYARPNode); + rb_cYARPElseNode = rb_define_class_under(rb_cYARP, "ElseNode", rb_cYARPNode); + rb_cYARPEmbeddedStatementsNode = rb_define_class_under(rb_cYARP, "EmbeddedStatementsNode", rb_cYARPNode); + rb_cYARPEmbeddedVariableNode = rb_define_class_under(rb_cYARP, "EmbeddedVariableNode", rb_cYARPNode); + rb_cYARPEnsureNode = rb_define_class_under(rb_cYARP, "EnsureNode", rb_cYARPNode); + rb_cYARPFalseNode = rb_define_class_under(rb_cYARP, "FalseNode", rb_cYARPNode); + rb_cYARPFindPatternNode = rb_define_class_under(rb_cYARP, "FindPatternNode", rb_cYARPNode); + rb_cYARPFlipFlopNode = rb_define_class_under(rb_cYARP, "FlipFlopNode", rb_cYARPNode); + rb_cYARPFloatNode = rb_define_class_under(rb_cYARP, "FloatNode", rb_cYARPNode); + rb_cYARPForNode = rb_define_class_under(rb_cYARP, "ForNode", rb_cYARPNode); + rb_cYARPForwardingArgumentsNode = rb_define_class_under(rb_cYARP, "ForwardingArgumentsNode", rb_cYARPNode); + rb_cYARPForwardingParameterNode = rb_define_class_under(rb_cYARP, "ForwardingParameterNode", rb_cYARPNode); + rb_cYARPForwardingSuperNode = rb_define_class_under(rb_cYARP, "ForwardingSuperNode", rb_cYARPNode); + rb_cYARPGlobalVariableOperatorAndWriteNode = rb_define_class_under(rb_cYARP, "GlobalVariableOperatorAndWriteNode", rb_cYARPNode); + rb_cYARPGlobalVariableOperatorOrWriteNode = rb_define_class_under(rb_cYARP, "GlobalVariableOperatorOrWriteNode", rb_cYARPNode); + rb_cYARPGlobalVariableOperatorWriteNode = rb_define_class_under(rb_cYARP, "GlobalVariableOperatorWriteNode", rb_cYARPNode); + rb_cYARPGlobalVariableReadNode = rb_define_class_under(rb_cYARP, "GlobalVariableReadNode", rb_cYARPNode); + rb_cYARPGlobalVariableWriteNode = rb_define_class_under(rb_cYARP, "GlobalVariableWriteNode", rb_cYARPNode); + rb_cYARPHashNode = rb_define_class_under(rb_cYARP, "HashNode", rb_cYARPNode); + rb_cYARPHashPatternNode = rb_define_class_under(rb_cYARP, "HashPatternNode", rb_cYARPNode); + rb_cYARPIfNode = rb_define_class_under(rb_cYARP, "IfNode", rb_cYARPNode); + rb_cYARPImaginaryNode = rb_define_class_under(rb_cYARP, "ImaginaryNode", rb_cYARPNode); + rb_cYARPInNode = rb_define_class_under(rb_cYARP, "InNode", rb_cYARPNode); + rb_cYARPInstanceVariableOperatorAndWriteNode = rb_define_class_under(rb_cYARP, "InstanceVariableOperatorAndWriteNode", rb_cYARPNode); + rb_cYARPInstanceVariableOperatorOrWriteNode = rb_define_class_under(rb_cYARP, "InstanceVariableOperatorOrWriteNode", rb_cYARPNode); + rb_cYARPInstanceVariableOperatorWriteNode = rb_define_class_under(rb_cYARP, "InstanceVariableOperatorWriteNode", rb_cYARPNode); + rb_cYARPInstanceVariableReadNode = rb_define_class_under(rb_cYARP, "InstanceVariableReadNode", rb_cYARPNode); + rb_cYARPInstanceVariableWriteNode = rb_define_class_under(rb_cYARP, "InstanceVariableWriteNode", rb_cYARPNode); + rb_cYARPIntegerNode = rb_define_class_under(rb_cYARP, "IntegerNode", rb_cYARPNode); + rb_cYARPInterpolatedRegularExpressionNode = rb_define_class_under(rb_cYARP, "InterpolatedRegularExpressionNode", rb_cYARPNode); + rb_cYARPInterpolatedStringNode = rb_define_class_under(rb_cYARP, "InterpolatedStringNode", rb_cYARPNode); + rb_cYARPInterpolatedSymbolNode = rb_define_class_under(rb_cYARP, "InterpolatedSymbolNode", rb_cYARPNode); + rb_cYARPInterpolatedXStringNode = rb_define_class_under(rb_cYARP, "InterpolatedXStringNode", rb_cYARPNode); + rb_cYARPKeywordHashNode = rb_define_class_under(rb_cYARP, "KeywordHashNode", rb_cYARPNode); + rb_cYARPKeywordParameterNode = rb_define_class_under(rb_cYARP, "KeywordParameterNode", rb_cYARPNode); + rb_cYARPKeywordRestParameterNode = rb_define_class_under(rb_cYARP, "KeywordRestParameterNode", rb_cYARPNode); + rb_cYARPLambdaNode = rb_define_class_under(rb_cYARP, "LambdaNode", rb_cYARPNode); + rb_cYARPLocalVariableOperatorAndWriteNode = rb_define_class_under(rb_cYARP, "LocalVariableOperatorAndWriteNode", rb_cYARPNode); + rb_cYARPLocalVariableOperatorOrWriteNode = rb_define_class_under(rb_cYARP, "LocalVariableOperatorOrWriteNode", rb_cYARPNode); + rb_cYARPLocalVariableOperatorWriteNode = rb_define_class_under(rb_cYARP, "LocalVariableOperatorWriteNode", rb_cYARPNode); + rb_cYARPLocalVariableReadNode = rb_define_class_under(rb_cYARP, "LocalVariableReadNode", rb_cYARPNode); + rb_cYARPLocalVariableWriteNode = rb_define_class_under(rb_cYARP, "LocalVariableWriteNode", rb_cYARPNode); + rb_cYARPMatchPredicateNode = rb_define_class_under(rb_cYARP, "MatchPredicateNode", rb_cYARPNode); + rb_cYARPMatchRequiredNode = rb_define_class_under(rb_cYARP, "MatchRequiredNode", rb_cYARPNode); + rb_cYARPMissingNode = rb_define_class_under(rb_cYARP, "MissingNode", rb_cYARPNode); + rb_cYARPModuleNode = rb_define_class_under(rb_cYARP, "ModuleNode", rb_cYARPNode); + rb_cYARPMultiWriteNode = rb_define_class_under(rb_cYARP, "MultiWriteNode", rb_cYARPNode); + rb_cYARPNextNode = rb_define_class_under(rb_cYARP, "NextNode", rb_cYARPNode); + rb_cYARPNilNode = rb_define_class_under(rb_cYARP, "NilNode", rb_cYARPNode); + rb_cYARPNoKeywordsParameterNode = rb_define_class_under(rb_cYARP, "NoKeywordsParameterNode", rb_cYARPNode); + rb_cYARPNumberedReferenceReadNode = rb_define_class_under(rb_cYARP, "NumberedReferenceReadNode", rb_cYARPNode); + rb_cYARPOptionalParameterNode = rb_define_class_under(rb_cYARP, "OptionalParameterNode", rb_cYARPNode); + rb_cYARPOrNode = rb_define_class_under(rb_cYARP, "OrNode", rb_cYARPNode); + rb_cYARPParametersNode = rb_define_class_under(rb_cYARP, "ParametersNode", rb_cYARPNode); + rb_cYARPParenthesesNode = rb_define_class_under(rb_cYARP, "ParenthesesNode", rb_cYARPNode); + rb_cYARPPinnedExpressionNode = rb_define_class_under(rb_cYARP, "PinnedExpressionNode", rb_cYARPNode); + rb_cYARPPinnedVariableNode = rb_define_class_under(rb_cYARP, "PinnedVariableNode", rb_cYARPNode); + rb_cYARPPostExecutionNode = rb_define_class_under(rb_cYARP, "PostExecutionNode", rb_cYARPNode); + rb_cYARPPreExecutionNode = rb_define_class_under(rb_cYARP, "PreExecutionNode", rb_cYARPNode); + rb_cYARPProgramNode = rb_define_class_under(rb_cYARP, "ProgramNode", rb_cYARPNode); + rb_cYARPRangeNode = rb_define_class_under(rb_cYARP, "RangeNode", rb_cYARPNode); + rb_cYARPRationalNode = rb_define_class_under(rb_cYARP, "RationalNode", rb_cYARPNode); + rb_cYARPRedoNode = rb_define_class_under(rb_cYARP, "RedoNode", rb_cYARPNode); + rb_cYARPRegularExpressionNode = rb_define_class_under(rb_cYARP, "RegularExpressionNode", rb_cYARPNode); + rb_cYARPRequiredDestructuredParameterNode = rb_define_class_under(rb_cYARP, "RequiredDestructuredParameterNode", rb_cYARPNode); + rb_cYARPRequiredParameterNode = rb_define_class_under(rb_cYARP, "RequiredParameterNode", rb_cYARPNode); + rb_cYARPRescueModifierNode = rb_define_class_under(rb_cYARP, "RescueModifierNode", rb_cYARPNode); + rb_cYARPRescueNode = rb_define_class_under(rb_cYARP, "RescueNode", rb_cYARPNode); + rb_cYARPRestParameterNode = rb_define_class_under(rb_cYARP, "RestParameterNode", rb_cYARPNode); + rb_cYARPRetryNode = rb_define_class_under(rb_cYARP, "RetryNode", rb_cYARPNode); + rb_cYARPReturnNode = rb_define_class_under(rb_cYARP, "ReturnNode", rb_cYARPNode); + rb_cYARPSelfNode = rb_define_class_under(rb_cYARP, "SelfNode", rb_cYARPNode); + rb_cYARPSingletonClassNode = rb_define_class_under(rb_cYARP, "SingletonClassNode", rb_cYARPNode); + rb_cYARPSourceEncodingNode = rb_define_class_under(rb_cYARP, "SourceEncodingNode", rb_cYARPNode); + rb_cYARPSourceFileNode = rb_define_class_under(rb_cYARP, "SourceFileNode", rb_cYARPNode); + rb_cYARPSourceLineNode = rb_define_class_under(rb_cYARP, "SourceLineNode", rb_cYARPNode); + rb_cYARPSplatNode = rb_define_class_under(rb_cYARP, "SplatNode", rb_cYARPNode); + rb_cYARPStatementsNode = rb_define_class_under(rb_cYARP, "StatementsNode", rb_cYARPNode); + rb_cYARPStringConcatNode = rb_define_class_under(rb_cYARP, "StringConcatNode", rb_cYARPNode); + rb_cYARPStringNode = rb_define_class_under(rb_cYARP, "StringNode", rb_cYARPNode); + rb_cYARPSuperNode = rb_define_class_under(rb_cYARP, "SuperNode", rb_cYARPNode); + rb_cYARPSymbolNode = rb_define_class_under(rb_cYARP, "SymbolNode", rb_cYARPNode); + rb_cYARPTrueNode = rb_define_class_under(rb_cYARP, "TrueNode", rb_cYARPNode); + rb_cYARPUndefNode = rb_define_class_under(rb_cYARP, "UndefNode", rb_cYARPNode); + rb_cYARPUnlessNode = rb_define_class_under(rb_cYARP, "UnlessNode", rb_cYARPNode); + rb_cYARPUntilNode = rb_define_class_under(rb_cYARP, "UntilNode", rb_cYARPNode); + rb_cYARPWhenNode = rb_define_class_under(rb_cYARP, "WhenNode", rb_cYARPNode); + rb_cYARPWhileNode = rb_define_class_under(rb_cYARP, "WhileNode", rb_cYARPNode); + rb_cYARPXStringNode = rb_define_class_under(rb_cYARP, "XStringNode", rb_cYARPNode); + rb_cYARPYieldNode = rb_define_class_under(rb_cYARP, "YieldNode", rb_cYARPNode); } diff --git a/yarp/ast.h b/yarp/ast.h index 15c8b2855f4dea..0e0d320f4dd29a 100644 --- a/yarp/ast.h +++ b/yarp/ast.h @@ -62,6 +62,9 @@ typedef enum yp_token_type { YP_TOKEN_EQUAL_GREATER, // => YP_TOKEN_EQUAL_TILDE, // =~ YP_TOKEN_FLOAT, // a floating point number + YP_TOKEN_FLOAT_IMAGINARY, // a floating pointer number with an imaginary suffix + YP_TOKEN_FLOAT_RATIONAL, // a floating pointer number with a rational suffix + YP_TOKEN_FLOAT_RATIONAL_IMAGINARY, // a floating pointer number with a rational and imaginary suffix YP_TOKEN_GLOBAL_VARIABLE, // a global variable YP_TOKEN_GREATER, // > YP_TOKEN_GREATER_EQUAL, // >= @@ -71,9 +74,11 @@ typedef enum yp_token_type { YP_TOKEN_HEREDOC_START, // the start of a heredoc YP_TOKEN_IDENTIFIER, // an identifier YP_TOKEN_IGNORED_NEWLINE, // an ignored newline - YP_TOKEN_IMAGINARY_NUMBER, // an imaginary number literal YP_TOKEN_INSTANCE_VARIABLE, // an instance variable YP_TOKEN_INTEGER, // an integer (any base) + YP_TOKEN_INTEGER_IMAGINARY, // an integer with an imaginary suffix + YP_TOKEN_INTEGER_RATIONAL, // an integer with a rational suffix + YP_TOKEN_INTEGER_RATIONAL_IMAGINARY, // an integer with a rational and imaginary suffix YP_TOKEN_KEYWORD_ALIAS, // alias YP_TOKEN_KEYWORD_AND, // and YP_TOKEN_KEYWORD_BEGIN, // begin @@ -151,7 +156,6 @@ typedef enum yp_token_type { YP_TOKEN_PLUS, // + YP_TOKEN_PLUS_EQUAL, // += YP_TOKEN_QUESTION_MARK, // ? - YP_TOKEN_RATIONAL_NUMBER, // a rational number literal YP_TOKEN_REGEXP_BEGIN, // the beginning of a regular expression YP_TOKEN_REGEXP_END, // the end of a regular expression YP_TOKEN_SEMICOLON, // ; @@ -166,6 +170,7 @@ typedef enum yp_token_type { YP_TOKEN_STRING_END, // the end of a string YP_TOKEN_SYMBOL_BEGIN, // the beginning of a symbol YP_TOKEN_TILDE, // ~ or ~@ + YP_TOKEN_UAMPERSAND, // unary & YP_TOKEN_UCOLON_COLON, // unary :: YP_TOKEN_UDOT_DOT, // unary .. YP_TOKEN_UDOT_DOT_DOT, // unary ... @@ -208,7 +213,7 @@ typedef struct yp_node_list { size_t capacity; } yp_node_list_t; -typedef enum { +enum yp_node_type { YP_NODE_ALIAS_NODE = 1, YP_NODE_ALTERNATION_PATTERN_NODE = 2, YP_NODE_AND_NODE = 3, @@ -245,97 +250,110 @@ typedef enum { YP_NODE_CONSTANT_PATH_OPERATOR_WRITE_NODE = 34, YP_NODE_CONSTANT_PATH_WRITE_NODE = 35, YP_NODE_CONSTANT_READ_NODE = 36, - YP_NODE_DEF_NODE = 37, - YP_NODE_DEFINED_NODE = 38, - YP_NODE_ELSE_NODE = 39, - YP_NODE_EMBEDDED_STATEMENTS_NODE = 40, - YP_NODE_EMBEDDED_VARIABLE_NODE = 41, - YP_NODE_ENSURE_NODE = 42, - YP_NODE_FALSE_NODE = 43, - YP_NODE_FIND_PATTERN_NODE = 44, - YP_NODE_FLOAT_NODE = 45, - YP_NODE_FOR_NODE = 46, - YP_NODE_FORWARDING_ARGUMENTS_NODE = 47, - YP_NODE_FORWARDING_PARAMETER_NODE = 48, - YP_NODE_FORWARDING_SUPER_NODE = 49, - YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE = 50, - YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE = 51, - YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE = 52, - YP_NODE_GLOBAL_VARIABLE_READ_NODE = 53, - YP_NODE_GLOBAL_VARIABLE_WRITE_NODE = 54, - YP_NODE_HASH_NODE = 55, - YP_NODE_HASH_PATTERN_NODE = 56, - YP_NODE_IF_NODE = 57, - YP_NODE_IMAGINARY_NODE = 58, - YP_NODE_IN_NODE = 59, - YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE = 60, - YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE = 61, - YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE = 62, - YP_NODE_INSTANCE_VARIABLE_READ_NODE = 63, - YP_NODE_INSTANCE_VARIABLE_WRITE_NODE = 64, - YP_NODE_INTEGER_NODE = 65, - YP_NODE_INTERPOLATED_REGULAR_EXPRESSION_NODE = 66, - YP_NODE_INTERPOLATED_STRING_NODE = 67, - YP_NODE_INTERPOLATED_SYMBOL_NODE = 68, - YP_NODE_INTERPOLATED_X_STRING_NODE = 69, - YP_NODE_KEYWORD_HASH_NODE = 70, - YP_NODE_KEYWORD_PARAMETER_NODE = 71, - YP_NODE_KEYWORD_REST_PARAMETER_NODE = 72, - YP_NODE_LAMBDA_NODE = 73, - YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE = 74, - YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE = 75, - YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE = 76, - YP_NODE_LOCAL_VARIABLE_READ_NODE = 77, - YP_NODE_LOCAL_VARIABLE_WRITE_NODE = 78, - YP_NODE_MATCH_PREDICATE_NODE = 79, - YP_NODE_MATCH_REQUIRED_NODE = 80, - YP_NODE_MISSING_NODE = 81, - YP_NODE_MODULE_NODE = 82, - YP_NODE_MULTI_WRITE_NODE = 83, - YP_NODE_NEXT_NODE = 84, - YP_NODE_NIL_NODE = 85, - YP_NODE_NO_KEYWORDS_PARAMETER_NODE = 86, - YP_NODE_NUMBERED_REFERENCE_READ_NODE = 87, - YP_NODE_OPTIONAL_PARAMETER_NODE = 88, - YP_NODE_OR_NODE = 89, - YP_NODE_PARAMETERS_NODE = 90, - YP_NODE_PARENTHESES_NODE = 91, - YP_NODE_PINNED_EXPRESSION_NODE = 92, - YP_NODE_PINNED_VARIABLE_NODE = 93, - YP_NODE_POST_EXECUTION_NODE = 94, - YP_NODE_PRE_EXECUTION_NODE = 95, - YP_NODE_PROGRAM_NODE = 96, - YP_NODE_RANGE_NODE = 97, - YP_NODE_RATIONAL_NODE = 98, - YP_NODE_REDO_NODE = 99, - YP_NODE_REGULAR_EXPRESSION_NODE = 100, - YP_NODE_REQUIRED_DESTRUCTURED_PARAMETER_NODE = 101, - YP_NODE_REQUIRED_PARAMETER_NODE = 102, - YP_NODE_RESCUE_MODIFIER_NODE = 103, - YP_NODE_RESCUE_NODE = 104, - YP_NODE_REST_PARAMETER_NODE = 105, - YP_NODE_RETRY_NODE = 106, - YP_NODE_RETURN_NODE = 107, - YP_NODE_SELF_NODE = 108, - YP_NODE_SINGLETON_CLASS_NODE = 109, - YP_NODE_SOURCE_ENCODING_NODE = 110, - YP_NODE_SOURCE_FILE_NODE = 111, - YP_NODE_SOURCE_LINE_NODE = 112, - YP_NODE_SPLAT_NODE = 113, - YP_NODE_STATEMENTS_NODE = 114, - YP_NODE_STRING_CONCAT_NODE = 115, - YP_NODE_STRING_NODE = 116, - YP_NODE_SUPER_NODE = 117, - YP_NODE_SYMBOL_NODE = 118, - YP_NODE_TRUE_NODE = 119, - YP_NODE_UNDEF_NODE = 120, - YP_NODE_UNLESS_NODE = 121, - YP_NODE_UNTIL_NODE = 122, - YP_NODE_WHEN_NODE = 123, - YP_NODE_WHILE_NODE = 124, - YP_NODE_X_STRING_NODE = 125, - YP_NODE_YIELD_NODE = 126, -} yp_node_type_t; + YP_NODE_CONSTANT_WRITE_NODE = 37, + YP_NODE_DEF_NODE = 38, + YP_NODE_DEFINED_NODE = 39, + YP_NODE_ELSE_NODE = 40, + YP_NODE_EMBEDDED_STATEMENTS_NODE = 41, + YP_NODE_EMBEDDED_VARIABLE_NODE = 42, + YP_NODE_ENSURE_NODE = 43, + YP_NODE_FALSE_NODE = 44, + YP_NODE_FIND_PATTERN_NODE = 45, + YP_NODE_FLIP_FLOP_NODE = 46, + YP_NODE_FLOAT_NODE = 47, + YP_NODE_FOR_NODE = 48, + YP_NODE_FORWARDING_ARGUMENTS_NODE = 49, + YP_NODE_FORWARDING_PARAMETER_NODE = 50, + YP_NODE_FORWARDING_SUPER_NODE = 51, + YP_NODE_GLOBAL_VARIABLE_OPERATOR_AND_WRITE_NODE = 52, + YP_NODE_GLOBAL_VARIABLE_OPERATOR_OR_WRITE_NODE = 53, + YP_NODE_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE = 54, + YP_NODE_GLOBAL_VARIABLE_READ_NODE = 55, + YP_NODE_GLOBAL_VARIABLE_WRITE_NODE = 56, + YP_NODE_HASH_NODE = 57, + YP_NODE_HASH_PATTERN_NODE = 58, + YP_NODE_IF_NODE = 59, + YP_NODE_IMAGINARY_NODE = 60, + YP_NODE_IN_NODE = 61, + YP_NODE_INSTANCE_VARIABLE_OPERATOR_AND_WRITE_NODE = 62, + YP_NODE_INSTANCE_VARIABLE_OPERATOR_OR_WRITE_NODE = 63, + YP_NODE_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE = 64, + YP_NODE_INSTANCE_VARIABLE_READ_NODE = 65, + YP_NODE_INSTANCE_VARIABLE_WRITE_NODE = 66, + YP_NODE_INTEGER_NODE = 67, + YP_NODE_INTERPOLATED_REGULAR_EXPRESSION_NODE = 68, + YP_NODE_INTERPOLATED_STRING_NODE = 69, + YP_NODE_INTERPOLATED_SYMBOL_NODE = 70, + YP_NODE_INTERPOLATED_X_STRING_NODE = 71, + YP_NODE_KEYWORD_HASH_NODE = 72, + YP_NODE_KEYWORD_PARAMETER_NODE = 73, + YP_NODE_KEYWORD_REST_PARAMETER_NODE = 74, + YP_NODE_LAMBDA_NODE = 75, + YP_NODE_LOCAL_VARIABLE_OPERATOR_AND_WRITE_NODE = 76, + YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE = 77, + YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE = 78, + YP_NODE_LOCAL_VARIABLE_READ_NODE = 79, + YP_NODE_LOCAL_VARIABLE_WRITE_NODE = 80, + YP_NODE_MATCH_PREDICATE_NODE = 81, + YP_NODE_MATCH_REQUIRED_NODE = 82, + YP_NODE_MISSING_NODE = 83, + YP_NODE_MODULE_NODE = 84, + YP_NODE_MULTI_WRITE_NODE = 85, + YP_NODE_NEXT_NODE = 86, + YP_NODE_NIL_NODE = 87, + YP_NODE_NO_KEYWORDS_PARAMETER_NODE = 88, + YP_NODE_NUMBERED_REFERENCE_READ_NODE = 89, + YP_NODE_OPTIONAL_PARAMETER_NODE = 90, + YP_NODE_OR_NODE = 91, + YP_NODE_PARAMETERS_NODE = 92, + YP_NODE_PARENTHESES_NODE = 93, + YP_NODE_PINNED_EXPRESSION_NODE = 94, + YP_NODE_PINNED_VARIABLE_NODE = 95, + YP_NODE_POST_EXECUTION_NODE = 96, + YP_NODE_PRE_EXECUTION_NODE = 97, + YP_NODE_PROGRAM_NODE = 98, + YP_NODE_RANGE_NODE = 99, + YP_NODE_RATIONAL_NODE = 100, + YP_NODE_REDO_NODE = 101, + YP_NODE_REGULAR_EXPRESSION_NODE = 102, + YP_NODE_REQUIRED_DESTRUCTURED_PARAMETER_NODE = 103, + YP_NODE_REQUIRED_PARAMETER_NODE = 104, + YP_NODE_RESCUE_MODIFIER_NODE = 105, + YP_NODE_RESCUE_NODE = 106, + YP_NODE_REST_PARAMETER_NODE = 107, + YP_NODE_RETRY_NODE = 108, + YP_NODE_RETURN_NODE = 109, + YP_NODE_SELF_NODE = 110, + YP_NODE_SINGLETON_CLASS_NODE = 111, + YP_NODE_SOURCE_ENCODING_NODE = 112, + YP_NODE_SOURCE_FILE_NODE = 113, + YP_NODE_SOURCE_LINE_NODE = 114, + YP_NODE_SPLAT_NODE = 115, + YP_NODE_STATEMENTS_NODE = 116, + YP_NODE_STRING_CONCAT_NODE = 117, + YP_NODE_STRING_NODE = 118, + YP_NODE_SUPER_NODE = 119, + YP_NODE_SYMBOL_NODE = 120, + YP_NODE_TRUE_NODE = 121, + YP_NODE_UNDEF_NODE = 122, + YP_NODE_UNLESS_NODE = 123, + YP_NODE_UNTIL_NODE = 124, + YP_NODE_WHEN_NODE = 125, + YP_NODE_WHILE_NODE = 126, + YP_NODE_X_STRING_NODE = 127, + YP_NODE_YIELD_NODE = 128, +}; + +typedef uint16_t yp_node_type_t; +typedef uint16_t yp_node_flags_t; + +// We store the flags enum in every node in the tree. Some flags are common to +// all nodes (the ones listed below). Others are specific to certain node types. +static const yp_node_flags_t YP_NODE_FLAG_NEWLINE = 0x1; + +// For easy access, we define some macros to check node type +#define YP_NODE_TYPE(node) ((enum yp_node_type)node->type) +#define YP_NODE_TYPE_P(node, type) (YP_NODE_TYPE(node) == (type)) // This is the overall tagged union representing a node in the syntax tree. typedef struct yp_node { @@ -343,6 +361,10 @@ typedef struct yp_node { // existed in the original grammar and ripper, but it's not a 1:1 mapping. yp_node_type_t type; + // This represents any flags on the node. Currently, this is only a newline + // flag + yp_node_flags_t flags; + // This is the location of the node in the source. It's a range of bytes // containing a start and an end. yp_location_t location; @@ -478,7 +500,6 @@ typedef struct yp_call_node { struct yp_arguments_node *arguments; yp_location_t closing_loc; struct yp_block_node *block; - uint32_t flags; yp_string_t name; } yp_call_node_t; @@ -636,7 +657,7 @@ typedef struct yp_constant_path_operator_write_node { // ConstantPathWriteNode typedef struct yp_constant_path_write_node { yp_node_t base; - struct yp_node *target; + struct yp_constant_path_node *target; yp_location_t operator_loc; struct yp_node *value; } yp_constant_path_write_node_t; @@ -646,6 +667,14 @@ typedef struct yp_constant_read_node { yp_node_t base; } yp_constant_read_node_t; +// ConstantWriteNode +typedef struct yp_constant_write_node { + yp_node_t base; + yp_location_t name_loc; + struct yp_node *value; + yp_location_t operator_loc; +} yp_constant_write_node_t; + // DefNode typedef struct yp_def_node { yp_node_t base; @@ -718,6 +747,14 @@ typedef struct yp_find_pattern_node { yp_location_t closing_loc; } yp_find_pattern_node_t; +// FlipFlopNode +typedef struct yp_flip_flop_node { + yp_node_t base; + struct yp_node *left; + struct yp_node *right; + yp_location_t operator_loc; +} yp_flip_flop_node_t; + // FloatNode typedef struct yp_float_node { yp_node_t base; @@ -881,7 +918,6 @@ typedef struct yp_interpolated_regular_expression_node { yp_location_t opening_loc; struct yp_node_list parts; yp_location_t closing_loc; - uint32_t flags; } yp_interpolated_regular_expression_node_t; // InterpolatedStringNode @@ -1131,7 +1167,6 @@ typedef struct yp_range_node { struct yp_node *left; struct yp_node *right; yp_location_t operator_loc; - uint32_t flags; } yp_range_node_t; // RationalNode @@ -1152,7 +1187,6 @@ typedef struct yp_regular_expression_node { yp_location_t content_loc; yp_location_t closing_loc; yp_string_t unescaped; - uint32_t flags; } yp_regular_expression_node_t; // RequiredDestructuredParameterNode @@ -1183,7 +1217,7 @@ typedef struct yp_rescue_node { yp_location_t keyword_loc; struct yp_node_list exceptions; yp_location_t operator_loc; - struct yp_node *exception; + struct yp_node *reference; struct yp_statements_node *statements; struct yp_rescue_node *consequent; } yp_rescue_node_t; @@ -1353,24 +1387,30 @@ typedef struct yp_yield_node { // CallNodeFlags typedef enum { - YP_CALL_NODE_FLAGS_SAFE_NAVIGATION = 1 << 0, + YP_CALL_NODE_FLAGS_SAFE_NAVIGATION = 1 << 1, + YP_CALL_NODE_FLAGS_VARIABLE_CALL = 1 << 2, } yp_call_node_flags_t; -// RangeNodeFlags +// LoopFlags +typedef enum { + YP_LOOP_FLAGS_BEGIN_MODIFIER = 1 << 1, +} yp_loop_flags_t; + +// RangeFlags typedef enum { - YP_RANGE_NODE_FLAGS_EXCLUDE_END = 1 << 0, -} yp_range_node_flags_t; + YP_RANGE_FLAGS_EXCLUDE_END = 1 << 1, +} yp_range_flags_t; // RegularExpressionFlags typedef enum { - YP_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE = 1 << 0, - YP_REGULAR_EXPRESSION_FLAGS_MULTI_LINE = 1 << 1, - YP_REGULAR_EXPRESSION_FLAGS_EXTENDED = 1 << 2, - YP_REGULAR_EXPRESSION_FLAGS_EUC_JP = 1 << 3, - YP_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT = 1 << 4, - YP_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J = 1 << 5, - YP_REGULAR_EXPRESSION_FLAGS_UTF_8 = 1 << 6, - YP_REGULAR_EXPRESSION_FLAGS_ONCE = 1 << 7, + YP_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE = 1 << 1, + YP_REGULAR_EXPRESSION_FLAGS_MULTI_LINE = 1 << 2, + YP_REGULAR_EXPRESSION_FLAGS_EXTENDED = 1 << 3, + YP_REGULAR_EXPRESSION_FLAGS_EUC_JP = 1 << 4, + YP_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT = 1 << 5, + YP_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J = 1 << 6, + YP_REGULAR_EXPRESSION_FLAGS_UTF_8 = 1 << 7, + YP_REGULAR_EXPRESSION_FLAGS_ONCE = 1 << 8, } yp_regular_expression_flags_t; #endif // YARP_AST_H diff --git a/yarp/defines.h b/yarp/defines.h index 5c7e02e932afa4..32ed3a557a9f94 100644 --- a/yarp/defines.h +++ b/yarp/defines.h @@ -3,8 +3,6 @@ // This file should be included first by any *.h or *.c in YARP -#include "yarp/config.h" - #include #include #include @@ -38,17 +36,4 @@ int yp_strncasecmp(const char *string1, const char *string2, size_t length); -int yp_snprintf(char *dest, YP_ATTRIBUTE_UNUSED size_t size, const char *format, ...); - -#if defined(HAVE_SNPRINTF) - // We use snprintf if it's available -# define yp_snprintf snprintf - -#else - // In case snprintf isn't present on the system, we provide our own that simply - // forwards to the less-safe sprintf. -# define yp_snprintf(dest, size, ...) sprintf((dest), __VA_ARGS__) - -#endif - #endif diff --git a/yarp/enc/yp_ascii.c b/yarp/enc/yp_ascii.c deleted file mode 100644 index 655dd49fa65d1d..00000000000000 --- a/yarp/enc/yp_ascii.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ASCII character. -static unsigned char yp_encoding_ascii_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Cx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Dx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ex - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Fx -}; - -static size_t -yp_encoding_ascii_char_width(const char *c) { - const unsigned char v = (const unsigned char) *c; - return v < 0x80 ? 1 : 0; -} - -size_t -yp_encoding_ascii_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_ascii_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -size_t -yp_encoding_ascii_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_ascii_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -bool -yp_encoding_ascii_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_ascii_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_ascii = { - .name = "ascii", - .char_width = yp_encoding_ascii_char_width, - .alnum_char = yp_encoding_ascii_alnum_char, - .alpha_char = yp_encoding_ascii_alpha_char, - .isupper_char = yp_encoding_ascii_isupper_char, - .multibyte = false -}; - -yp_encoding_t yp_encoding_ascii_8bit = { - .name = "ascii-8bit", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_ascii_alnum_char, - .alpha_char = yp_encoding_ascii_alpha_char, - .isupper_char = yp_encoding_ascii_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_big5.c b/yarp/enc/yp_big5.c index 23f90c0297f1ba..a33f5ce50493ac 100644 --- a/yarp/enc/yp_big5.c +++ b/yarp/enc/yp_big5.c @@ -1,9 +1,9 @@ #include "yarp/enc/yp_encoding.h" -typedef uint16_t big5_codepoint_t; +typedef uint16_t yp_big5_codepoint_t; -static big5_codepoint_t -big5_codepoint(const char *c, size_t *width) { +static yp_big5_codepoint_t +yp_big5_codepoint(const char *c, ptrdiff_t n, size_t *width) { const unsigned char *uc = (const unsigned char *) c; // These are the single byte characters. @@ -13,9 +13,9 @@ big5_codepoint(const char *c, size_t *width) { } // These are the double byte characters. - if ((uc[0] >= 0xA1 && uc[0] <= 0xFE) && (uc[1] >= 0x40 && uc[1] <= 0xFE)) { + if ((n > 1) && (uc[0] >= 0xA1 && uc[0] <= 0xFE) && (uc[1] >= 0x40 && uc[1] <= 0xFE)) { *width = 2; - return (big5_codepoint_t) (uc[0] << 8 | uc[1]); + return (yp_big5_codepoint_t) (uc[0] << 8 | uc[1]); } *width = 0; @@ -23,47 +23,47 @@ big5_codepoint(const char *c, size_t *width) { } static size_t -yp_encoding_big5_char_width(const char *c) { +yp_encoding_big5_char_width(const char *c, ptrdiff_t n) { size_t width; - big5_codepoint(c, &width); + yp_big5_codepoint(c, n, &width); return width; } static size_t -yp_encoding_big5_alpha_char(const char *c) { +yp_encoding_big5_alpha_char(const char *c, ptrdiff_t n) { size_t width; - big5_codepoint_t codepoint = big5_codepoint(c, &width); + yp_big5_codepoint_t codepoint = yp_big5_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alpha_char(&value); + return yp_encoding_ascii_alpha_char(&value, n); } else { return 0; } } static size_t -yp_encoding_big5_alnum_char(const char *c) { +yp_encoding_big5_alnum_char(const char *c, ptrdiff_t n) { size_t width; - big5_codepoint_t codepoint = big5_codepoint(c, &width); + yp_big5_codepoint_t codepoint = yp_big5_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alnum_char(&value); + return yp_encoding_ascii_alnum_char(&value, n); } else { return 0; } } static bool -yp_encoding_big5_isupper_char(const char *c) { +yp_encoding_big5_isupper_char(const char *c, ptrdiff_t n) { size_t width; - big5_codepoint_t codepoint = big5_codepoint(c, &width); + yp_big5_codepoint_t codepoint = yp_big5_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_isupper_char(&value); + return yp_encoding_ascii_isupper_char(&value, n); } else { return false; } diff --git a/yarp/enc/yp_encoding.h b/yarp/enc/yp_encoding.h index 24714bd41f85aa..7c4ce28c9428b7 100644 --- a/yarp/enc/yp_encoding.h +++ b/yarp/enc/yp_encoding.h @@ -3,6 +3,7 @@ #include "yarp/defines.h" +#include #include #include #include @@ -13,20 +14,24 @@ // 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. - size_t (*char_width)(const char *c); + // in the encoding. Does not read more than n bytes. It is assumed that n is + // at least 1. + size_t (*char_width)(const char *c, ptrdiff_t n); // Return the number of bytes that the next character takes if it is valid - // in the encoding and is alphabetical. - size_t (*alpha_char)(const char *c); + // 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 char *c, ptrdiff_t n); // Return the number of bytes that the next character takes if it is valid - // in the encoding and is alphanumeric. - size_t (*alnum_char)(const char *c); + // 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 char *c, ptrdiff_t n); // Return true if the next character is valid in the encoding and is an - // uppercase character. - bool (*isupper_char)(const char *c); + // uppercase character. Does not read more than n bytes. It is assumed that + // n is at least 1. + bool (*isupper_char)(const char *c, ptrdiff_t n); // The name of the encoding. This should correspond to a value that can be // passed to Encoding.find in Ruby. @@ -42,21 +47,16 @@ typedef struct { #define YP_ENCODING_ALPHANUMERIC_BIT 1 << 1 #define YP_ENCODING_UPPERCASE_BIT 1 << 2 -// The function is shared between all of the encodings that use single bytes to -// represent characters. They don't have need of a dynamic function to determine -// their width. -size_t yp_encoding_single_char_width(YP_ATTRIBUTE_UNUSED const char *c); - // These functions are reused by some other encodings, so they are defined here // so they can be shared. -size_t yp_encoding_ascii_alpha_char(const char *c); -size_t yp_encoding_ascii_alnum_char(const char *c); -bool yp_encoding_ascii_isupper_char(const char *c); +size_t yp_encoding_ascii_alpha_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n); +size_t yp_encoding_ascii_alnum_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n); +bool yp_encoding_ascii_isupper_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n); // These functions are shared between the actual encoding and the fast path in // the parser so they need to be internally visible. -size_t yp_encoding_utf_8_alpha_char(const char *c); -size_t yp_encoding_utf_8_alnum_char(const char *c); +size_t yp_encoding_utf_8_alpha_char(const char *c, ptrdiff_t n); +size_t yp_encoding_utf_8_alnum_char(const char *c, 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. @@ -87,6 +87,7 @@ extern yp_encoding_t yp_encoding_iso_8859_16; extern yp_encoding_t yp_encoding_koi8_r; extern yp_encoding_t yp_encoding_shift_jis; extern yp_encoding_t yp_encoding_utf_8; +extern yp_encoding_t yp_encoding_utf8_mac; extern yp_encoding_t yp_encoding_windows_31j; extern yp_encoding_t yp_encoding_windows_1251; extern yp_encoding_t yp_encoding_windows_1252; diff --git a/yarp/enc/yp_euc_jp.c b/yarp/enc/yp_euc_jp.c index 3a616e230a9adb..ebcd6a784992df 100644 --- a/yarp/enc/yp_euc_jp.c +++ b/yarp/enc/yp_euc_jp.c @@ -1,9 +1,9 @@ #include "yarp/enc/yp_encoding.h" -typedef uint16_t euc_jp_codepoint_t; +typedef uint16_t yp_euc_jp_codepoint_t; -static euc_jp_codepoint_t -euc_jp_codepoint(const char *c, size_t *width) { +static yp_euc_jp_codepoint_t +yp_euc_jp_codepoint(const char *c, ptrdiff_t n, size_t *width) { const unsigned char *uc = (const unsigned char *) c; // These are the single byte characters. @@ -14,11 +14,14 @@ euc_jp_codepoint(const char *c, size_t *width) { // These are the double byte characters. if ( - ((uc[0] == 0x8E) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) || - ((uc[0] >= 0xA1 && uc[0] <= 0xFE) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) + (n > 1) && + ( + ((uc[0] == 0x8E) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) || + ((uc[0] >= 0xA1 && uc[0] <= 0xFE) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) + ) ) { *width = 2; - return (euc_jp_codepoint_t) (uc[0] << 8 | uc[1]); + return (yp_euc_jp_codepoint_t) (uc[0] << 8 | uc[1]); } *width = 0; @@ -26,47 +29,47 @@ euc_jp_codepoint(const char *c, size_t *width) { } static size_t -yp_encoding_euc_jp_char_width(const char *c) { +yp_encoding_euc_jp_char_width(const char *c, ptrdiff_t n) { size_t width; - euc_jp_codepoint(c, &width); + yp_euc_jp_codepoint(c, n, &width); return width; } static size_t -yp_encoding_euc_jp_alpha_char(const char *c) { +yp_encoding_euc_jp_alpha_char(const char *c, ptrdiff_t n) { size_t width; - euc_jp_codepoint_t codepoint = euc_jp_codepoint(c, &width); + yp_euc_jp_codepoint_t codepoint = yp_euc_jp_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alpha_char(&value); + return yp_encoding_ascii_alpha_char(&value, n); } else { return 0; } } static size_t -yp_encoding_euc_jp_alnum_char(const char *c) { +yp_encoding_euc_jp_alnum_char(const char *c, ptrdiff_t n) { size_t width; - euc_jp_codepoint_t codepoint = euc_jp_codepoint(c, &width); + yp_euc_jp_codepoint_t codepoint = yp_euc_jp_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alnum_char(&value); + return yp_encoding_ascii_alnum_char(&value, n); } else { return 0; } } static bool -yp_encoding_euc_jp_isupper_char(const char *c) { +yp_encoding_euc_jp_isupper_char(const char *c, ptrdiff_t n) { size_t width; - euc_jp_codepoint_t codepoint = euc_jp_codepoint(c, &width); + yp_euc_jp_codepoint_t codepoint = yp_euc_jp_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_isupper_char(&value); + return yp_encoding_ascii_isupper_char(&value, n); } else { return 0; } diff --git a/yarp/enc/yp_gbk.c b/yarp/enc/yp_gbk.c index 3daa1ee3f39d0e..31e88756db5865 100644 --- a/yarp/enc/yp_gbk.c +++ b/yarp/enc/yp_gbk.c @@ -1,9 +1,9 @@ #include "yarp/enc/yp_encoding.h" -typedef uint16_t gbk_codepoint_t; +typedef uint16_t yp_gbk_codepoint_t; -static gbk_codepoint_t -gbk_codepoint(const char *c, size_t *width) { +static yp_gbk_codepoint_t +yp_gbk_codepoint(const char *c, ptrdiff_t n, size_t *width) { const unsigned char *uc = (const unsigned char *) c; // These are the single byte characters. @@ -14,14 +14,17 @@ gbk_codepoint(const char *c, size_t *width) { // These are the double byte characters. if ( - ((uc[0] >= 0xA1 && uc[0] <= 0xA9) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) || // GBK/1 - ((uc[0] >= 0xB0 && uc[0] <= 0xF7) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) || // GBK/2 - ((uc[0] >= 0x81 && uc[0] <= 0xA0) && (uc[1] >= 0x40 && uc[1] <= 0xFE) && (uc[1] != 0x7F)) || // GBK/3 - ((uc[0] >= 0xAA && uc[0] <= 0xFE) && (uc[1] >= 0x40 && uc[1] <= 0xA0) && (uc[1] != 0x7F)) || // GBK/4 - ((uc[0] >= 0xA8 && uc[0] <= 0xA9) && (uc[1] >= 0x40 && uc[1] <= 0xA0) && (uc[1] != 0x7F)) // GBK/5 + (n > 1) && + ( + ((uc[0] >= 0xA1 && uc[0] <= 0xA9) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) || // GBK/1 + ((uc[0] >= 0xB0 && uc[0] <= 0xF7) && (uc[1] >= 0xA1 && uc[1] <= 0xFE)) || // GBK/2 + ((uc[0] >= 0x81 && uc[0] <= 0xA0) && (uc[1] >= 0x40 && uc[1] <= 0xFE) && (uc[1] != 0x7F)) || // GBK/3 + ((uc[0] >= 0xAA && uc[0] <= 0xFE) && (uc[1] >= 0x40 && uc[1] <= 0xA0) && (uc[1] != 0x7F)) || // GBK/4 + ((uc[0] >= 0xA8 && uc[0] <= 0xA9) && (uc[1] >= 0x40 && uc[1] <= 0xA0) && (uc[1] != 0x7F)) // GBK/5 + ) ) { *width = 2; - return (gbk_codepoint_t) (uc[0] << 8 | uc[1]); + return (yp_gbk_codepoint_t) (uc[0] << 8 | uc[1]); } *width = 0; @@ -29,47 +32,47 @@ gbk_codepoint(const char *c, size_t *width) { } static size_t -yp_encoding_gbk_char_width(const char *c) { +yp_encoding_gbk_char_width(const char *c, ptrdiff_t n) { size_t width; - gbk_codepoint(c, &width); + yp_gbk_codepoint(c, n, &width); return width; } static size_t -yp_encoding_gbk_alpha_char(const char *c) { +yp_encoding_gbk_alpha_char(const char *c, ptrdiff_t n) { size_t width; - gbk_codepoint_t codepoint = gbk_codepoint(c, &width); + yp_gbk_codepoint_t codepoint = yp_gbk_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alpha_char(&value); + return yp_encoding_ascii_alpha_char(&value, n); } else { return 0; } } static size_t -yp_encoding_gbk_alnum_char(const char *c) { +yp_encoding_gbk_alnum_char(const char *c, ptrdiff_t n) { size_t width; - gbk_codepoint_t codepoint = gbk_codepoint(c, &width); + yp_gbk_codepoint_t codepoint = yp_gbk_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alnum_char(&value); + return yp_encoding_ascii_alnum_char(&value, n); } else { return 0; } } static bool -yp_encoding_gbk_isupper_char(const char *c) { +yp_encoding_gbk_isupper_char(const char *c, ptrdiff_t n) { size_t width; - gbk_codepoint_t codepoint = gbk_codepoint(c, &width); + yp_gbk_codepoint_t codepoint = yp_gbk_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_isupper_char(&value); + return yp_encoding_ascii_isupper_char(&value, n); } else { return false; } diff --git a/yarp/enc/yp_iso_8859_1.c b/yarp/enc/yp_iso_8859_1.c deleted file mode 100644 index e56a47d223da7d..00000000000000 --- a/yarp/enc/yp_iso_8859_1.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-1 character. -static unsigned char yp_encoding_iso_8859_1_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_iso_8859_1_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_1_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_1_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_1_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_1_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_1_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_1 = { - .name = "iso-8859-1", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_1_alnum_char, - .alpha_char = yp_encoding_iso_8859_1_alpha_char, - .isupper_char = yp_encoding_iso_8859_1_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_10.c b/yarp/enc/yp_iso_8859_10.c deleted file mode 100644 index d3abf7d09f698c..00000000000000 --- a/yarp/enc/yp_iso_8859_10.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-10 character. -static unsigned char yp_encoding_iso_8859_10_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, // Ax - 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_iso_8859_10_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_10_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_10_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_10_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_10_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_10_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_10 = { - .name = "iso-8859-10", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_10_alnum_char, - .alpha_char = yp_encoding_iso_8859_10_alpha_char, - .isupper_char = yp_encoding_iso_8859_10_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_11.c b/yarp/enc/yp_iso_8859_11.c deleted file mode 100644 index 45b55fb1efa8bd..00000000000000 --- a/yarp/enc/yp_iso_8859_11.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-11 character. -static unsigned char yp_encoding_iso_8859_11_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ax - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Bx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Cx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_11_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_11_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_11_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_11_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_11_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_11_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_11 = { - .name = "iso-8859-11", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_11_alnum_char, - .alpha_char = yp_encoding_iso_8859_11_alpha_char, - .isupper_char = yp_encoding_iso_8859_11_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_13.c b/yarp/enc/yp_iso_8859_13.c deleted file mode 100644 index 4504779f3661d5..00000000000000 --- a/yarp/enc/yp_iso_8859_13.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-13 character. -static unsigned char yp_encoding_iso_8859_13_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 7, // Ax - 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 0, 0, 0, 3, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_13_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_13_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_13_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_13_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_13_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_13_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_13 = { - .name = "iso-8859-13", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_13_alnum_char, - .alpha_char = yp_encoding_iso_8859_13_alpha_char, - .isupper_char = yp_encoding_iso_8859_13_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_14.c b/yarp/enc/yp_iso_8859_14.c deleted file mode 100644 index 7c25610bd0880c..00000000000000 --- a/yarp/enc/yp_iso_8859_14.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-14 character. -static unsigned char yp_encoding_iso_8859_14_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 7, 3, 0, 7, 3, 7, 0, 7, 0, 7, 3, 7, 0, 0, 7, // Ax - 7, 3, 7, 3, 7, 3, 0, 7, 3, 3, 3, 7, 3, 7, 3, 3, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_iso_8859_14_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_14_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_14_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_14_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_14_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_14_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_14 = { - .name = "iso-8859-14", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_14_alnum_char, - .alpha_char = yp_encoding_iso_8859_14_alpha_char, - .isupper_char = yp_encoding_iso_8859_14_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_15.c b/yarp/enc/yp_iso_8859_15.c deleted file mode 100644 index e41cc6fbb05336..00000000000000 --- a/yarp/enc/yp_iso_8859_15.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-15 character. -static unsigned char yp_encoding_iso_8859_15_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 7, 0, 3, 0, 3, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 7, 3, 0, 0, 3, 0, 3, 0, 7, 3, 7, 0, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_iso_8859_15_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_15_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_15_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_15_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_15_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_15_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_15 = { - .name = "iso-8859-15", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_15_alnum_char, - .alpha_char = yp_encoding_iso_8859_15_alpha_char, - .isupper_char = yp_encoding_iso_8859_15_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_16.c b/yarp/enc/yp_iso_8859_16.c deleted file mode 100644 index f30067f82a9b80..00000000000000 --- a/yarp/enc/yp_iso_8859_16.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-16 character. -static unsigned char yp_encoding_iso_8859_16_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 7, 3, 7, 0, 0, 7, 0, 3, 0, 7, 0, 7, 0, 3, 7, // Ax - 0, 0, 7, 3, 7, 0, 0, 0, 3, 3, 3, 0, 7, 3, 7, 3, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_iso_8859_16_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_16_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_16_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_16_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_16_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_16_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_16 = { - .name = "iso-8859-16", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_16_alnum_char, - .alpha_char = yp_encoding_iso_8859_16_alpha_char, - .isupper_char = yp_encoding_iso_8859_16_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_2.c b/yarp/enc/yp_iso_8859_2.c deleted file mode 100644 index af9536276154b3..00000000000000 --- a/yarp/enc/yp_iso_8859_2.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-2 character. -static unsigned char yp_encoding_iso_8859_2_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 7, 0, 7, 0, 7, 7, 0, 0, 7, 7, 7, 7, 0, 7, 7, // Ax - 0, 3, 0, 3, 0, 3, 3, 0, 0, 3, 3, 3, 3, 0, 3, 3, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_2_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_2_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_2_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_2_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_2_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_2_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_2 = { - .name = "iso-8859-2", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_2_alnum_char, - .alpha_char = yp_encoding_iso_8859_2_alpha_char, - .isupper_char = yp_encoding_iso_8859_2_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_3.c b/yarp/enc/yp_iso_8859_3.c deleted file mode 100644 index 382a9f239a7ccc..00000000000000 --- a/yarp/enc/yp_iso_8859_3.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-3 character. -static unsigned char yp_encoding_iso_8859_3_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 7, 0, 0, 0, 0, 7, 0, 0, 7, 7, 7, 7, 0, 0, 7, // Ax - 0, 3, 0, 0, 0, 3, 3, 0, 0, 3, 3, 3, 3, 0, 0, 3, // Bx - 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 0, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_3_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_3_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_3_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_3_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_3_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_3_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_3 = { - .name = "iso-8859-3", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_3_alnum_char, - .alpha_char = yp_encoding_iso_8859_3_alpha_char, - .isupper_char = yp_encoding_iso_8859_3_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_4.c b/yarp/enc/yp_iso_8859_4.c deleted file mode 100644 index 5f7d87ecca08c1..00000000000000 --- a/yarp/enc/yp_iso_8859_4.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-4 character. -static unsigned char yp_encoding_iso_8859_4_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 7, 3, 7, 0, 7, 7, 0, 0, 7, 7, 7, 7, 0, 7, 0, // Ax - 0, 3, 0, 3, 0, 3, 3, 0, 0, 3, 3, 3, 3, 7, 3, 3, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_4_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_4_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_4_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_4_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_4_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_4_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_4 = { - .name = "iso-8859-4", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_4_alnum_char, - .alpha_char = yp_encoding_iso_8859_4_alpha_char, - .isupper_char = yp_encoding_iso_8859_4_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_5.c b/yarp/enc/yp_iso_8859_5.c deleted file mode 100644 index ff6d4105d1fce1..00000000000000 --- a/yarp/enc/yp_iso_8859_5.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-5 character. -static unsigned char yp_encoding_iso_8859_5_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, // Ax - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, // Fx -}; - -static size_t -yp_encoding_iso_8859_5_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_5_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_5_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_5_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_5_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_5_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_5 = { - .name = "iso-8859-5", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_5_alnum_char, - .alpha_char = yp_encoding_iso_8859_5_alpha_char, - .isupper_char = yp_encoding_iso_8859_5_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_6.c b/yarp/enc/yp_iso_8859_6.c deleted file mode 100644 index b32d3081cdf857..00000000000000 --- a/yarp/enc/yp_iso_8859_6.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-6 character. -static unsigned char yp_encoding_iso_8859_6_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Cx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_6_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_6_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_6_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_6_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_6_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_6_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_6 = { - .name = "iso-8859-6", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_6_alnum_char, - .alpha_char = yp_encoding_iso_8859_6_alpha_char, - .isupper_char = yp_encoding_iso_8859_6_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_7.c b/yarp/enc/yp_iso_8859_7.c deleted file mode 100644 index 0ccea26f508cc4..00000000000000 --- a/yarp/enc/yp_iso_8859_7.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-7 character. -static unsigned char yp_encoding_iso_8859_7_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 0, 0, 7, 0, 7, 7, 7, 0, 7, 0, 7, 7, // Bx - 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_7_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_7_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_7_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_7_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_7_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_7_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_7 = { - .name = "iso-8859-7", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_7_alnum_char, - .alpha_char = yp_encoding_iso_8859_7_alpha_char, - .isupper_char = yp_encoding_iso_8859_7_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_8.c b/yarp/enc/yp_iso_8859_8.c deleted file mode 100644 index 718ba8f5b4edc8..00000000000000 --- a/yarp/enc/yp_iso_8859_8.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-8 character. -static unsigned char yp_encoding_iso_8859_8_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Cx - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // Fx -}; - -static size_t -yp_encoding_iso_8859_8_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_8_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_8_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_8_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_8_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_8_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_8 = { - .name = "iso-8859-8", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_8_alnum_char, - .alpha_char = yp_encoding_iso_8859_8_alpha_char, - .isupper_char = yp_encoding_iso_8859_8_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_iso_8859_9.c b/yarp/enc/yp_iso_8859_9.c deleted file mode 100644 index 3dab740382d6f8..00000000000000 --- a/yarp/enc/yp_iso_8859_9.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding ISO-8859-9 character. -static unsigned char yp_encoding_iso_8859_9_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_iso_8859_9_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_9_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_iso_8859_9_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_9_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_iso_8859_9_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_iso_8859_9_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_iso_8859_9 = { - .name = "iso-8859-9", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_iso_8859_9_alnum_char, - .alpha_char = yp_encoding_iso_8859_9_alpha_char, - .isupper_char = yp_encoding_iso_8859_9_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_koi8_r.c b/yarp/enc/yp_koi8_r.c deleted file mode 100644 index cc778896102903..00000000000000 --- a/yarp/enc/yp_koi8_r.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding windows-1251 character. -static unsigned char yp_encoding_koi8_r_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x - 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Cx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Dx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Ex - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Fx -}; - -static size_t -yp_encoding_koi8_r_char_width(const char *c) { - const unsigned char v = (const unsigned char) *c; - return ((v >= 0x20 && v <= 0x7E) || (v >= 0x80)) ? 1 : 0; -} - -static size_t -yp_encoding_koi8_r_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_koi8_r_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_koi8_r_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_koi8_r_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_koi8_r_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_koi8_r_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_koi8_r = { - .name = "koi8-r", - .char_width = yp_encoding_koi8_r_char_width, - .alnum_char = yp_encoding_koi8_r_alnum_char, - .alpha_char = yp_encoding_koi8_r_alpha_char, - .isupper_char = yp_encoding_koi8_r_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_shared.c b/yarp/enc/yp_shared.c deleted file mode 100644 index 035ab8cc44564b..00000000000000 --- a/yarp/enc/yp_shared.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// The function is shared between all of the encodings that use single bytes to -// represent characters. They don't have need of a dynamic function to determine -// their width. -size_t -yp_encoding_single_char_width(YP_ATTRIBUTE_UNUSED const char *c) { - return 1; -} diff --git a/yarp/enc/yp_shift_jis.c b/yarp/enc/yp_shift_jis.c index 6977d3ce98df33..1f361b9e705cd2 100644 --- a/yarp/enc/yp_shift_jis.c +++ b/yarp/enc/yp_shift_jis.c @@ -1,9 +1,9 @@ #include "yarp/enc/yp_encoding.h" -typedef uint16_t shift_jis_codepoint_t; +typedef uint16_t yp_shift_jis_codepoint_t; -static shift_jis_codepoint_t -shift_jis_codepoint(const char *c, size_t *width) { +static yp_shift_jis_codepoint_t +yp_shift_jis_codepoint(const char *c, ptrdiff_t n, size_t *width) { const unsigned char *uc = (const unsigned char *) c; // These are the single byte characters. @@ -14,11 +14,12 @@ shift_jis_codepoint(const char *c, size_t *width) { // These are the double byte characters. if ( + (n > 1) && ((uc[0] >= 0x81 && uc[0] <= 0x9F) || (uc[0] >= 0xE0 && uc[0] <= 0xFC)) && (uc[1] >= 0x40 && uc[1] <= 0xFC) ) { *width = 2; - return (shift_jis_codepoint_t) (uc[0] << 8 | uc[1]); + return (yp_shift_jis_codepoint_t) (uc[0] << 8 | uc[1]); } *width = 0; @@ -26,47 +27,47 @@ shift_jis_codepoint(const char *c, size_t *width) { } static size_t -yp_encoding_shift_jis_char_width(const char *c) { +yp_encoding_shift_jis_char_width(const char *c, ptrdiff_t n) { size_t width; - shift_jis_codepoint(c, &width); + yp_shift_jis_codepoint(c, n, &width); return width; } static size_t -yp_encoding_shift_jis_alpha_char(const char *c) { +yp_encoding_shift_jis_alpha_char(const char *c, ptrdiff_t n) { size_t width; - shift_jis_codepoint_t codepoint = shift_jis_codepoint(c, &width); + yp_shift_jis_codepoint_t codepoint = yp_shift_jis_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alpha_char(&value); + return yp_encoding_ascii_alpha_char(&value, n); } else { return 0; } } static size_t -yp_encoding_shift_jis_alnum_char(const char *c) { +yp_encoding_shift_jis_alnum_char(const char *c, ptrdiff_t n) { size_t width; - shift_jis_codepoint_t codepoint = shift_jis_codepoint(c, &width); + yp_shift_jis_codepoint_t codepoint = yp_shift_jis_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alnum_char(&value); + return yp_encoding_ascii_alnum_char(&value, n); } else { return 0; } } static bool -yp_encoding_shift_jis_isupper_char(const char *c) { +yp_encoding_shift_jis_isupper_char(const char *c, ptrdiff_t n) { size_t width; - shift_jis_codepoint_t codepoint = shift_jis_codepoint(c, &width); + yp_shift_jis_codepoint_t codepoint = yp_shift_jis_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_isupper_char(&value); + return yp_encoding_ascii_isupper_char(&value, n); } else { return 0; } diff --git a/yarp/enc/yp_tables.c b/yarp/enc/yp_tables.c new file mode 100644 index 00000000000000..057f2b3f818259 --- /dev/null +++ b/yarp/enc/yp_tables.c @@ -0,0 +1,509 @@ +#include "yarp/enc/yp_encoding.h" + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ASCII character. +static unsigned char yp_encoding_ascii_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-1 character. +static unsigned char yp_encoding_iso_8859_1_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-2 character. +static unsigned char yp_encoding_iso_8859_2_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 7, 0, 7, 0, 7, 7, 0, 0, 7, 7, 7, 7, 0, 7, 7, // Ax + 0, 3, 0, 3, 0, 3, 3, 0, 0, 3, 3, 3, 3, 0, 3, 3, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-3 character. +static unsigned char yp_encoding_iso_8859_3_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 7, 0, 0, 0, 0, 7, 0, 0, 7, 7, 7, 7, 0, 0, 7, // Ax + 0, 3, 0, 0, 0, 3, 3, 0, 0, 3, 3, 3, 3, 0, 0, 3, // Bx + 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 0, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-4 character. +static unsigned char yp_encoding_iso_8859_4_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 7, 3, 7, 0, 7, 7, 0, 0, 7, 7, 7, 7, 0, 7, 0, // Ax + 0, 3, 0, 3, 0, 3, 3, 0, 0, 3, 3, 3, 3, 7, 3, 3, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-5 character. +static unsigned char yp_encoding_iso_8859_5_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, // Ax + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-6 character. +static unsigned char yp_encoding_iso_8859_6_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Cx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-7 character. +static unsigned char yp_encoding_iso_8859_7_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 0, 0, 7, 0, 7, 7, 7, 0, 7, 0, 7, 7, // Bx + 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-8 character. +static unsigned char yp_encoding_iso_8859_8_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-9 character. +static unsigned char yp_encoding_iso_8859_9_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-10 character. +static unsigned char yp_encoding_iso_8859_10_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, // Ax + 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-11 character. +static unsigned char yp_encoding_iso_8859_11_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ax + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Bx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Cx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-13 character. +static unsigned char yp_encoding_iso_8859_13_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 7, // Ax + 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 0, 0, 0, 3, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-14 character. +static unsigned char yp_encoding_iso_8859_14_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 7, 3, 0, 7, 3, 7, 0, 7, 0, 7, 3, 7, 0, 0, 7, // Ax + 7, 3, 7, 3, 7, 3, 0, 7, 3, 3, 3, 7, 3, 7, 3, 3, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-15 character. +static unsigned char yp_encoding_iso_8859_15_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 7, 0, 3, 0, 3, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 7, 3, 0, 0, 3, 0, 3, 0, 7, 3, 7, 0, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding ISO-8859-16 character. +static unsigned char yp_encoding_iso_8859_16_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 7, 3, 7, 0, 0, 7, 0, 3, 0, 7, 0, 7, 0, 3, 7, // Ax + 0, 0, 7, 3, 7, 0, 0, 0, 3, 3, 3, 0, 7, 3, 7, 3, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding KOI8-R character. +static unsigned char yp_encoding_koi8_r_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Bx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Cx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Dx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Ex + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding windows-1251 character. +static unsigned char yp_encoding_windows_1251_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 7, 7, 0, 3, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7, 7, 7, // 8x + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 3, 3, 3, // 9x + 0, 7, 3, 7, 0, 7, 0, 0, 7, 0, 7, 0, 0, 0, 0, 7, // Ax + 0, 0, 7, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 7, 3, 3, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +// Each element of the following table contains a bitfield that indicates a +// piece of information about the corresponding windows-1252 character. +static unsigned char yp_encoding_windows_1252_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, 0, 0, 0, 0, 0, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x + 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 7, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 7, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Ax + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Bx + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx + 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex + 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx +}; + +static size_t +yp_encoding_ascii_char_width(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { + const unsigned char v = (const unsigned char) *c; + return v < 0x80 ? 1 : 0; +} + +size_t +yp_encoding_ascii_alpha_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { + return (yp_encoding_ascii_table[(const unsigned char) *c] & YP_ENCODING_ALPHABETIC_BIT); +} + +size_t +yp_encoding_ascii_alnum_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { + return (yp_encoding_ascii_table[(const unsigned char) *c] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; +} + +bool +yp_encoding_ascii_isupper_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { + return (yp_encoding_ascii_table[(const unsigned char) *c] & YP_ENCODING_UPPERCASE_BIT); +} + +static size_t +yp_encoding_koi8_r_char_width(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { + const unsigned char v = (const unsigned char) *c; + return ((v >= 0x20 && v <= 0x7E) || (v >= 0x80)) ? 1 : 0; +} + +static size_t +yp_encoding_single_char_width(YP_ATTRIBUTE_UNUSED const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { + return 1; +} + +yp_encoding_t yp_encoding_ascii = { + .name = "ascii", + .char_width = yp_encoding_ascii_char_width, + .alnum_char = yp_encoding_ascii_alnum_char, + .alpha_char = yp_encoding_ascii_alpha_char, + .isupper_char = yp_encoding_ascii_isupper_char, + .multibyte = false +}; + +yp_encoding_t yp_encoding_ascii_8bit = { + .name = "ascii-8bit", + .char_width = yp_encoding_single_char_width, + .alnum_char = yp_encoding_ascii_alnum_char, + .alpha_char = yp_encoding_ascii_alpha_char, + .isupper_char = yp_encoding_ascii_isupper_char, + .multibyte = false +}; + +#define YP_ENCODING_TABLE(s, i, w) \ + static size_t yp_encoding_ ##i ## _alpha_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { \ + return (yp_encoding_ ##i ## _table[(const unsigned char) *c] & YP_ENCODING_ALPHABETIC_BIT); \ + } \ + static size_t yp_encoding_ ##i ## _alnum_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { \ + return (yp_encoding_ ##i ## _table[(const unsigned char) *c] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; \ + } \ + static bool yp_encoding_ ##i ## _isupper_char(const char *c, YP_ATTRIBUTE_UNUSED ptrdiff_t n) { \ + return (yp_encoding_ ##i ## _table[(const unsigned char) *c] & YP_ENCODING_UPPERCASE_BIT); \ + } \ + yp_encoding_t yp_encoding_ ##i = { \ + .name = s, \ + .char_width = w, \ + .alnum_char = yp_encoding_ ##i ## _alnum_char, \ + .alpha_char = yp_encoding_ ##i ## _alpha_char, \ + .isupper_char = yp_encoding_ ##i ## _isupper_char, \ + .multibyte = false, \ + }; + +YP_ENCODING_TABLE("iso-8859-1", iso_8859_1, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-2", iso_8859_2, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-3", iso_8859_3, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-4", iso_8859_4, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-5", iso_8859_5, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-6", iso_8859_6, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-7", iso_8859_7, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-8", iso_8859_8, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-9", iso_8859_9, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-10", iso_8859_10, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-11", iso_8859_11, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-13", iso_8859_13, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-14", iso_8859_14, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-15", iso_8859_15, yp_encoding_single_char_width) +YP_ENCODING_TABLE("iso-8859-16", iso_8859_16, yp_encoding_single_char_width) +YP_ENCODING_TABLE("koi8-r", koi8_r, yp_encoding_koi8_r_char_width) +YP_ENCODING_TABLE("windows-1251", windows_1251, yp_encoding_single_char_width) +YP_ENCODING_TABLE("windows-1252", windows_1252, yp_encoding_single_char_width) + +#undef YP_ENCODING_TABLE diff --git a/yarp/enc/yp_unicode.c b/yarp/enc/yp_unicode.c index 63cbf418ddee56..fc2f0336fb7bf3 100644 --- a/yarp/enc/yp_unicode.c +++ b/yarp/enc/yp_unicode.c @@ -3,7 +3,7 @@ #include "yarp/enc/yp_encoding.h" -typedef uint32_t unicode_codepoint_t; +typedef uint32_t yp_unicode_codepoint_t; // Each element of the following table contains a bitfield that indicates a // piece of information about the corresponding unicode codepoint. Note that @@ -31,7 +31,7 @@ unsigned char yp_encoding_unicode_table[256] = { }; #define UNICODE_ALPHA_CODEPOINTS_LENGTH 1450 -static unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEPOINTS_LENGTH] = { +static yp_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEPOINTS_LENGTH] = { 0x100, 0x2C1, 0x2C6, 0x2D1, 0x2E0, 0x2E4, @@ -760,7 +760,7 @@ static unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEPOINTS_LEN }; #define UNICODE_ALNUM_CODEPOINTS_LENGTH 1528 -static unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEPOINTS_LENGTH] = { +static yp_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEPOINTS_LENGTH] = { 0x100, 0x2C1, 0x2C6, 0x2D1, 0x2E0, 0x2E4, @@ -1528,7 +1528,7 @@ static unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEPOINTS_LEN }; #define UNICODE_ISUPPER_CODEPOINTS_LENGTH 1296 -static unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_CODEPOINTS_LENGTH] = { +static yp_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_CODEPOINTS_LENGTH] = { 0x100, 0x100, 0x102, 0x102, 0x104, 0x104, @@ -2180,7 +2180,7 @@ static unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_CODEPOINTS }; static bool -unicode_codepoint_match(unicode_codepoint_t codepoint, unicode_codepoint_t *codepoints, size_t size) { +yp_unicode_codepoint_match(yp_unicode_codepoint_t codepoint, yp_unicode_codepoint_t *codepoints, size_t size) { size_t start = 0; size_t end = size; @@ -2202,7 +2202,7 @@ unicode_codepoint_match(unicode_codepoint_t codepoint, unicode_codepoint_t *code return false; } -static const uint8_t utf_8_dfa[] = { +static const uint8_t yp_utf_8_dfa[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f @@ -2219,23 +2219,26 @@ static const uint8_t utf_8_dfa[] = { 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 }; -static unicode_codepoint_t -utf_8_codepoint(const unsigned char *c, size_t *width) { +static yp_unicode_codepoint_t +yp_utf_8_codepoint(const unsigned char *c, ptrdiff_t n, size_t *width) { + assert(n >= 1); + size_t maximum = (size_t) n; + uint32_t codepoint; uint32_t state = 0; - for (size_t index = 0; index < 4; index++) { + for (size_t index = 0; index < 4 && index < maximum; index++) { uint32_t byte = c[index]; - uint32_t type = utf_8_dfa[byte]; + uint32_t type = yp_utf_8_dfa[byte]; codepoint = (state != 0) ? (byte & 0x3fu) | (codepoint << 6) : (0xffu >> type) & (byte); - state = utf_8_dfa[256 + (state * 16) + type]; + state = yp_utf_8_dfa[256 + (state * 16) + type]; if (!state) { *width = index + 1; - return (unicode_codepoint_t) codepoint; + return (yp_unicode_codepoint_t) codepoint; } } @@ -2244,62 +2247,62 @@ utf_8_codepoint(const unsigned char *c, size_t *width) { } static size_t -yp_encoding_utf_8_char_width(const char *c) { +yp_encoding_utf_8_char_width(const char *c, ptrdiff_t n) { size_t width; const unsigned char *v = (const unsigned char *) c; - utf_8_codepoint(v, &width); + yp_utf_8_codepoint(v, n, &width); return width; } size_t -yp_encoding_utf_8_alpha_char(const char *c) { +yp_encoding_utf_8_alpha_char(const char *c, ptrdiff_t n) { const unsigned char *v = (const unsigned char *) c; if (*v < 0x80) { return (yp_encoding_unicode_table[*v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; } size_t width; - unicode_codepoint_t codepoint = utf_8_codepoint(v, &width); + yp_unicode_codepoint_t codepoint = yp_utf_8_codepoint(v, n, &width); if (codepoint <= 0xFF) { return (yp_encoding_unicode_table[(unsigned char) codepoint] & YP_ENCODING_ALPHABETIC_BIT) ? width : 0; } else { - return unicode_codepoint_match(codepoint, unicode_alpha_codepoints, UNICODE_ALPHA_CODEPOINTS_LENGTH) ? width : 0; + return yp_unicode_codepoint_match(codepoint, unicode_alpha_codepoints, UNICODE_ALPHA_CODEPOINTS_LENGTH) ? width : 0; } } size_t -yp_encoding_utf_8_alnum_char(const char *c) { +yp_encoding_utf_8_alnum_char(const char *c, ptrdiff_t n) { const unsigned char *v = (const unsigned char *) c; if (*v < 0x80) { return (yp_encoding_unicode_table[*v] & (YP_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0; } size_t width; - unicode_codepoint_t codepoint = utf_8_codepoint(v, &width); + yp_unicode_codepoint_t codepoint = yp_utf_8_codepoint(v, n, &width); if (codepoint <= 0xFF) { return (yp_encoding_unicode_table[(unsigned char) codepoint] & (YP_ENCODING_ALPHANUMERIC_BIT)) ? width : 0; } else { - return unicode_codepoint_match(codepoint, unicode_alnum_codepoints, UNICODE_ALNUM_CODEPOINTS_LENGTH) ? width : 0; + return yp_unicode_codepoint_match(codepoint, unicode_alnum_codepoints, UNICODE_ALNUM_CODEPOINTS_LENGTH) ? width : 0; } } static bool -yp_encoding_utf_8_isupper_char(const char *c) { +yp_encoding_utf_8_isupper_char(const char *c, ptrdiff_t n) { const unsigned char *v = (const unsigned char *) c; if (*v < 0x80) { return (yp_encoding_unicode_table[*v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; } size_t width; - unicode_codepoint_t codepoint = utf_8_codepoint(v, &width); + yp_unicode_codepoint_t codepoint = yp_utf_8_codepoint(v, n, &width); if (codepoint <= 0xFF) { return (yp_encoding_unicode_table[(unsigned char) codepoint] & YP_ENCODING_UPPERCASE_BIT) ? true : false; } else { - return unicode_codepoint_match(codepoint, unicode_isupper_codepoints, UNICODE_ISUPPER_CODEPOINTS_LENGTH) ? true : false; + return yp_unicode_codepoint_match(codepoint, unicode_isupper_codepoints, UNICODE_ISUPPER_CODEPOINTS_LENGTH) ? true : false; } } @@ -2315,3 +2318,12 @@ yp_encoding_t yp_encoding_utf_8 = { .isupper_char = yp_encoding_utf_8_isupper_char, .multibyte = true }; + +yp_encoding_t yp_encoding_utf8_mac = { + .name = "utf8-mac", + .char_width = yp_encoding_utf_8_char_width, + .alnum_char = yp_encoding_utf_8_alnum_char, + .alpha_char = yp_encoding_utf_8_alpha_char, + .isupper_char = yp_encoding_utf_8_isupper_char, + .multibyte = true +}; diff --git a/yarp/enc/yp_windows_1251.c b/yarp/enc/yp_windows_1251.c deleted file mode 100644 index 37344e1ebf5bb9..00000000000000 --- a/yarp/enc/yp_windows_1251.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding windows-1251 character. -static unsigned char yp_encoding_windows_1251_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 7, 7, 0, 3, 0, 0, 0, 0, 0, 0, 7, 0, 7, 7, 7, 7, // 8x - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 3, 3, 3, // 9x - 0, 7, 3, 7, 0, 7, 0, 0, 7, 0, 7, 0, 0, 0, 0, 7, // Ax - 0, 0, 7, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 7, 3, 3, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_windows_1251_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_windows_1251_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_windows_1251_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_windows_1251_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_windows_1251_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_windows_1251_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_windows_1251 = { - .name = "windows-1251", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_windows_1251_alnum_char, - .alpha_char = yp_encoding_windows_1251_alpha_char, - .isupper_char = yp_encoding_windows_1251_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_windows_1252.c b/yarp/enc/yp_windows_1252.c deleted file mode 100644 index a62d4f4a210281..00000000000000 --- a/yarp/enc/yp_windows_1252.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "yarp/enc/yp_encoding.h" - -// Each element of the following table contains a bitfield that indicates a -// piece of information about the corresponding windows-1252 character. -static unsigned char yp_encoding_windows_1252_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, 0, 0, 0, 0, 0, 0, 0, // 0x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, // 3x - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 4x - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, // 5x - 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 6x - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, // 7x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 7, 0, // 8x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 7, // 9x - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Ax - 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, // Bx - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // Cx - 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 3, // Dx - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // Ex - 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx -}; - -static size_t -yp_encoding_windows_1252_alpha_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_windows_1252_table[v] & YP_ENCODING_ALPHABETIC_BIT) ? 1 : 0; -} - -static size_t -yp_encoding_windows_1252_alnum_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_windows_1252_table[v] & YP_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; -} - -static bool -yp_encoding_windows_1252_isupper_char(const char *c) { - const unsigned char v = (const unsigned char) *c; - return (yp_encoding_windows_1252_table[v] & YP_ENCODING_UPPERCASE_BIT) ? true : false; -} - -yp_encoding_t yp_encoding_windows_1252 = { - .name = "windows-1252", - .char_width = yp_encoding_single_char_width, - .alnum_char = yp_encoding_windows_1252_alnum_char, - .alpha_char = yp_encoding_windows_1252_alpha_char, - .isupper_char = yp_encoding_windows_1252_isupper_char, - .multibyte = false -}; diff --git a/yarp/enc/yp_windows_31j.c b/yarp/enc/yp_windows_31j.c index 9aa62c9b101a9f..7062d7c39c3a90 100644 --- a/yarp/enc/yp_windows_31j.c +++ b/yarp/enc/yp_windows_31j.c @@ -1,9 +1,9 @@ #include "yarp/enc/yp_encoding.h" -typedef uint16_t windows_31j_codepoint_t; +typedef uint16_t yp_windows_31j_codepoint_t; -static windows_31j_codepoint_t -windows_31j_codepoint(const char *c, size_t *width) { +static yp_windows_31j_codepoint_t +yp_windows_31j_codepoint(const char *c, ptrdiff_t n, size_t *width) { const unsigned char *uc = (const unsigned char *) c; // These are the single byte characters. @@ -14,11 +14,12 @@ windows_31j_codepoint(const char *c, size_t *width) { // These are the double byte characters. if ( + (n > 1) && ((uc[0] >= 0x81 && uc[0] <= 0x9F) || (uc[0] >= 0xE0 && uc[0] <= 0xFC)) && (uc[1] >= 0x40 && uc[1] <= 0xFC) ) { *width = 2; - return (windows_31j_codepoint_t) (uc[0] << 8 | uc[1]); + return (yp_windows_31j_codepoint_t) (uc[0] << 8 | uc[1]); } *width = 0; @@ -26,47 +27,47 @@ windows_31j_codepoint(const char *c, size_t *width) { } static size_t -yp_encoding_windows_31j_char_width(const char *c) { +yp_encoding_windows_31j_char_width(const char *c, ptrdiff_t n) { size_t width; - windows_31j_codepoint(c, &width); + yp_windows_31j_codepoint(c, n, &width); return width; } static size_t -yp_encoding_windows_31j_alpha_char(const char *c) { +yp_encoding_windows_31j_alpha_char(const char *c, ptrdiff_t n) { size_t width; - windows_31j_codepoint_t codepoint = windows_31j_codepoint(c, &width); + yp_windows_31j_codepoint_t codepoint = yp_windows_31j_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alpha_char(&value); + return yp_encoding_ascii_alpha_char(&value, n); } else { return 0; } } static size_t -yp_encoding_windows_31j_alnum_char(const char *c) { +yp_encoding_windows_31j_alnum_char(const char *c, ptrdiff_t n) { size_t width; - windows_31j_codepoint_t codepoint = windows_31j_codepoint(c, &width); + yp_windows_31j_codepoint_t codepoint = yp_windows_31j_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_alnum_char(&value); + return yp_encoding_ascii_alnum_char(&value, n); } else { return 0; } } static bool -yp_encoding_windows_31j_isupper_char(const char *c) { +yp_encoding_windows_31j_isupper_char(const char *c, ptrdiff_t n) { size_t width; - windows_31j_codepoint_t codepoint = windows_31j_codepoint(c, &width); + yp_windows_31j_codepoint_t codepoint = yp_windows_31j_codepoint(c, n, &width); if (width == 1) { const char value = (const char) codepoint; - return yp_encoding_ascii_isupper_char(&value); + return yp_encoding_ascii_isupper_char(&value, n); } else { return false; } diff --git a/yarp/extension.c b/yarp/extension.c index 2aa4dca3960777..119c28004e30a7 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -18,23 +18,23 @@ VALUE rb_cYARPParseResult; /* IO of Ruby code */ /******************************************************************************/ -// Check if the given filepath is a string. If it's nil, then return NULL. If -// it's not a string, then raise a type error. Otherwise return the filepath as -// a C string. +// Check if the given VALUE is a string. If it's nil, then return NULL. If it's +// not a string, then raise a type error. Otherwise return the VALUE as a C +// string. static const char * -check_filepath(VALUE filepath) { - // If the filepath is nil, then we don't need to do anything. - if (NIL_P(filepath)) { +check_string(VALUE value) { + // If the value is nil, then we don't need to do anything. + if (NIL_P(value)) { return NULL; } - // Check if the filepath is a string. If it's not, then raise a type error. - if (!RB_TYPE_P(filepath, T_STRING)) { - rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(filepath)); + // Check if the value is a string. If it's not, then raise a type error. + if (!RB_TYPE_P(value, T_STRING)) { + rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(value)); } - // Otherwise, return the filepath as a C string. - return StringValueCStr(filepath); + // Otherwise, return the value as a C string. + return RSTRING_PTR(value); } // Load the contents and size of the given string into the given yp_string_t. @@ -83,7 +83,7 @@ dump(int argc, VALUE *argv, VALUE self) { yp_string_t input; input_load_string(&input, string); - return dump_input(&input, check_filepath(filepath)); + return dump_input(&input, check_string(filepath)); } // Dump the AST corresponding to the given file to a string. @@ -91,7 +91,7 @@ static VALUE dump_file(VALUE self, VALUE filepath) { yp_string_t input; - const char *checked = check_filepath(filepath); + const char *checked = check_string(filepath); if (!yp_string_mapped_init(&input, checked)) return Qnil; VALUE value = dump_input(&input, checked); @@ -281,7 +281,7 @@ lex(int argc, VALUE *argv, VALUE self) { yp_string_t input; input_load_string(&input, string); - return lex_input(&input, check_filepath(filepath)); + return lex_input(&input, check_string(filepath)); } // Return an array of tokens corresponding to the given file. @@ -289,7 +289,7 @@ static VALUE lex_file(VALUE self, VALUE filepath) { yp_string_t input; - const char *checked = check_filepath(filepath); + const char *checked = check_string(filepath); if (!yp_string_mapped_init(&input, checked)) return Qnil; VALUE value = lex_input(&input, checked); @@ -345,7 +345,7 @@ parse(int argc, VALUE *argv, VALUE self) { yp_string_constant_init(&input, dup, length); #endif - VALUE value = parse_input(&input, check_filepath(filepath)); + VALUE value = parse_input(&input, check_string(filepath)); #ifdef YARP_DEBUG_MODE_BUILD free(dup); @@ -359,7 +359,7 @@ static VALUE parse_file(VALUE self, VALUE filepath) { yp_string_t input; - const char *checked = check_filepath(filepath); + const char *checked = check_string(filepath); if (!yp_string_mapped_init(&input, checked)) return Qnil; VALUE value = parse_input(&input, checked); @@ -458,7 +458,7 @@ static VALUE profile_file(VALUE self, VALUE filepath) { yp_string_t input; - const char *checked = check_filepath(filepath); + const char *checked = check_string(filepath); if (!yp_string_mapped_init(&input, checked)) return Qnil; yp_parser_t parser; @@ -471,6 +471,24 @@ profile_file(VALUE self, VALUE filepath) { return Qnil; } +// Parse the file and serialize the result. This is mostly used to test this +// path since it is used by client libraries. +static VALUE +parse_serialize_file_metadata(VALUE self, VALUE filepath, VALUE metadata) { + yp_string_t input; + yp_buffer_t buffer; + yp_buffer_init(&buffer); + + const char *checked = check_string(filepath); + if (!yp_string_mapped_init(&input, checked)) return Qnil; + + yp_parse_serialize(yp_string_source(&input), yp_string_length(&input), &buffer, check_string(metadata)); + VALUE result = rb_str_new(buffer.value, buffer.length); + + yp_buffer_free(&buffer); + return result; +} + /******************************************************************************/ /* Initialization of the extension */ /******************************************************************************/ @@ -504,6 +522,8 @@ Init_yarp(void) { // in yarp.h. rb_define_const(rb_cYARP, "VERSION", rb_str_new2(EXPECTED_YARP_VERSION)); + rb_define_const(rb_cYARP, "BACKEND", ID2SYM(rb_intern("CExtension"))); + // First, the functions that have to do with lexing and parsing. rb_define_singleton_method(rb_cYARP, "dump", dump, -1); rb_define_singleton_method(rb_cYARP, "dump_file", dump_file, 1); @@ -521,6 +541,7 @@ Init_yarp(void) { rb_define_singleton_method(rb_cYARPDebug, "unescape_all", unescape_all, 1); rb_define_singleton_method(rb_cYARPDebug, "memsize", memsize, 1); rb_define_singleton_method(rb_cYARPDebug, "profile_file", profile_file, 1); + rb_define_singleton_method(rb_cYARPDebug, "parse_serialize_file_metadata", parse_serialize_file_metadata, 2); // Next, initialize the other APIs. Init_yarp_api_node(); diff --git a/yarp/extension.h b/yarp/extension.h index c8f950c2d2f6cc..12381317dcdeaf 100644 --- a/yarp/extension.h +++ b/yarp/extension.h @@ -5,7 +5,7 @@ #include #include "yarp.h" -#define EXPECTED_YARP_VERSION "0.4.0" +#define EXPECTED_YARP_VERSION "0.7.0" VALUE yp_source_new(yp_parser_t *parser); VALUE yp_token_new(yp_parser_t *parser, yp_token_t *token, rb_encoding *encoding, VALUE source); diff --git a/yarp/node.c b/yarp/node.c index f02cac3f3cb92f..46e24d1ee7ffa8 100644 --- a/yarp/node.c +++ b/yarp/node.c @@ -82,7 +82,7 @@ yp_node_list_free(yp_parser_t *parser, yp_node_list_t *list) { // of pre-allocating larger memory pools. YP_EXPORTED_FUNCTION void yp_node_destroy(yp_parser_t *parser, yp_node_t *node) { - switch (node->type) { + switch (YP_NODE_TYPE(node)) { #line 81 "node.c.erb" case YP_NODE_ALIAS_NODE: yp_node_destroy(parser, (yp_node_t *)((yp_alias_node_t *)node)->new_name); @@ -299,6 +299,12 @@ yp_node_destroy(yp_parser_t *parser, yp_node_t *node) { #line 81 "node.c.erb" case YP_NODE_CONSTANT_READ_NODE: break; +#line 81 "node.c.erb" + case YP_NODE_CONSTANT_WRITE_NODE: + if (((yp_constant_write_node_t *)node)->value != NULL) { + yp_node_destroy(parser, (yp_node_t *)((yp_constant_write_node_t *)node)->value); + } + break; #line 81 "node.c.erb" case YP_NODE_DEF_NODE: if (((yp_def_node_t *)node)->receiver != NULL) { @@ -350,6 +356,15 @@ yp_node_destroy(yp_parser_t *parser, yp_node_t *node) { yp_node_list_free(parser, &((yp_find_pattern_node_t *)node)->requireds); yp_node_destroy(parser, (yp_node_t *)((yp_find_pattern_node_t *)node)->right); break; +#line 81 "node.c.erb" + case YP_NODE_FLIP_FLOP_NODE: + if (((yp_flip_flop_node_t *)node)->left != NULL) { + yp_node_destroy(parser, (yp_node_t *)((yp_flip_flop_node_t *)node)->left); + } + if (((yp_flip_flop_node_t *)node)->right != NULL) { + yp_node_destroy(parser, (yp_node_t *)((yp_flip_flop_node_t *)node)->right); + } + break; #line 81 "node.c.erb" case YP_NODE_FLOAT_NODE: break; @@ -647,8 +662,8 @@ yp_node_destroy(yp_parser_t *parser, yp_node_t *node) { #line 81 "node.c.erb" case YP_NODE_RESCUE_NODE: yp_node_list_free(parser, &((yp_rescue_node_t *)node)->exceptions); - if (((yp_rescue_node_t *)node)->exception != NULL) { - yp_node_destroy(parser, (yp_node_t *)((yp_rescue_node_t *)node)->exception); + if (((yp_rescue_node_t *)node)->reference != NULL) { + yp_node_destroy(parser, (yp_node_t *)((yp_rescue_node_t *)node)->reference); } if (((yp_rescue_node_t *)node)->statements != NULL) { yp_node_destroy(parser, (yp_node_t *)((yp_rescue_node_t *)node)->statements); @@ -782,7 +797,7 @@ static void yp_node_memsize_node(yp_node_t *node, yp_memsize_t *memsize) { memsize->node_count++; - switch (node->type) { + switch (YP_NODE_TYPE(node)) { #line 120 "node.c.erb" case YP_NODE_ALIAS_NODE: { memsize->memsize += sizeof(yp_alias_node_t); @@ -1071,6 +1086,14 @@ yp_node_memsize_node(yp_node_t *node, yp_memsize_t *memsize) { memsize->memsize += sizeof(yp_constant_read_node_t); break; } +#line 120 "node.c.erb" + case YP_NODE_CONSTANT_WRITE_NODE: { + memsize->memsize += sizeof(yp_constant_write_node_t); + if (((yp_constant_write_node_t *)node)->value != NULL) { + yp_node_memsize_node((yp_node_t *)((yp_constant_write_node_t *)node)->value, memsize); + } + break; + } #line 120 "node.c.erb" case YP_NODE_DEF_NODE: { memsize->memsize += sizeof(yp_def_node_t); @@ -1138,6 +1161,17 @@ yp_node_memsize_node(yp_node_t *node, yp_memsize_t *memsize) { yp_node_memsize_node((yp_node_t *)((yp_find_pattern_node_t *)node)->right, memsize); break; } +#line 120 "node.c.erb" + case YP_NODE_FLIP_FLOP_NODE: { + memsize->memsize += sizeof(yp_flip_flop_node_t); + if (((yp_flip_flop_node_t *)node)->left != NULL) { + yp_node_memsize_node((yp_node_t *)((yp_flip_flop_node_t *)node)->left, memsize); + } + if (((yp_flip_flop_node_t *)node)->right != NULL) { + yp_node_memsize_node((yp_node_t *)((yp_flip_flop_node_t *)node)->right, memsize); + } + break; + } #line 120 "node.c.erb" case YP_NODE_FLOAT_NODE: { memsize->memsize += sizeof(yp_float_node_t); @@ -1554,8 +1588,8 @@ yp_node_memsize_node(yp_node_t *node, yp_memsize_t *memsize) { case YP_NODE_RESCUE_NODE: { memsize->memsize += sizeof(yp_rescue_node_t); yp_node_list_memsize(&((yp_rescue_node_t *)node)->exceptions, memsize); - if (((yp_rescue_node_t *)node)->exception != NULL) { - yp_node_memsize_node((yp_node_t *)((yp_rescue_node_t *)node)->exception, memsize); + if (((yp_rescue_node_t *)node)->reference != NULL) { + yp_node_memsize_node((yp_node_t *)((yp_rescue_node_t *)node)->reference, memsize); } if (((yp_rescue_node_t *)node)->statements != NULL) { yp_node_memsize_node((yp_node_t *)((yp_rescue_node_t *)node)->statements, memsize); @@ -1810,6 +1844,8 @@ yp_node_type_to_str(yp_node_type_t node_type) return "YP_NODE_CONSTANT_PATH_WRITE_NODE"; case YP_NODE_CONSTANT_READ_NODE: return "YP_NODE_CONSTANT_READ_NODE"; + case YP_NODE_CONSTANT_WRITE_NODE: + return "YP_NODE_CONSTANT_WRITE_NODE"; case YP_NODE_DEF_NODE: return "YP_NODE_DEF_NODE"; case YP_NODE_DEFINED_NODE: @@ -1826,6 +1862,8 @@ yp_node_type_to_str(yp_node_type_t node_type) return "YP_NODE_FALSE_NODE"; case YP_NODE_FIND_PATTERN_NODE: return "YP_NODE_FIND_PATTERN_NODE"; + case YP_NODE_FLIP_FLOP_NODE: + return "YP_NODE_FLIP_FLOP_NODE"; case YP_NODE_FLOAT_NODE: return "YP_NODE_FLOAT_NODE"; case YP_NODE_FOR_NODE: diff --git a/yarp/prettyprint.c b/yarp/prettyprint.c index 727ac6c4305059..04a666dc8f72e9 100644 --- a/yarp/prettyprint.c +++ b/yarp/prettyprint.c @@ -16,13 +16,13 @@ static void prettyprint_location(yp_buffer_t *buffer, yp_parser_t *parser, yp_location_t *location) { char printed[] = "[0000-0000]"; - yp_snprintf(printed, sizeof(printed), "[%04ld-%04ld]", (long int)(location->start - parser->start), (long int)(location->end - parser->start)); + snprintf(printed, sizeof(printed), "[%04ld-%04ld]", (long int)(location->start - parser->start), (long int)(location->end - parser->start)); yp_buffer_append_str(buffer, printed, strlen(printed)); } static void prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { - switch (node->type) { + switch (YP_NODE_TYPE(node)) { case YP_NODE_ALIAS_NODE: { yp_buffer_append_str(buffer, "AliasNode(", 10); prettyprint_node(buffer, parser, (yp_node_t *)((yp_alias_node_t *)node)->new_name); @@ -49,19 +49,23 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_ARGUMENTS_NODE: { yp_buffer_append_str(buffer, "ArgumentsNode(", 14); - for (uint32_t index = 0; index < ((yp_arguments_node_t *)node)->arguments.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_arguments_node_t *)node)->arguments.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_arguments_node_t *) node)->arguments.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ")", 1); break; } case YP_NODE_ARRAY_NODE: { yp_buffer_append_str(buffer, "ArrayNode(", 10); - for (uint32_t index = 0; index < ((yp_array_node_t *)node)->elements.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_array_node_t *)node)->elements.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_array_node_t *) node)->elements.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_array_node_t *)node)->opening_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -82,19 +86,23 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_array_pattern_node_t *)node)->constant); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_array_pattern_node_t *)node)->requireds.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_array_pattern_node_t *)node)->requireds.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_array_pattern_node_t *) node)->requireds.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_array_pattern_node_t *)node)->rest == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_array_pattern_node_t *)node)->rest); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_array_pattern_node_t *)node)->posts.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_array_pattern_node_t *)node)->posts.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_array_pattern_node_t *) node)->posts.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_array_pattern_node_t *)node)->opening_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -188,12 +196,14 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_BLOCK_NODE: { yp_buffer_append_str(buffer, "BlockNode(", 10); - for (uint32_t index = 0; index < ((yp_block_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_block_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); char locals_buffer[12]; - yp_snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_block_node_t *)node)->locals.ids[index]); + snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_block_node_t *)node)->locals.ids[index]); yp_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_block_node_t *)node)->parameters == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -227,10 +237,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_block_parameters_node_t *)node)->parameters); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_block_parameters_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_block_parameters_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_block_parameters_node_t *)node)->locals.locations[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_block_parameters_node_t *)node)->opening_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -293,7 +305,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { prettyprint_node(buffer, parser, (yp_node_t *)((yp_call_node_t *)node)->block); } yp_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - yp_snprintf(flags_buffer, sizeof(flags_buffer), "+%d", ((yp_call_node_t *)node)->flags); + snprintf(flags_buffer, sizeof(flags_buffer), "+%d", node->flags >> 1); yp_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "\"", 1); yp_buffer_append_str(buffer, yp_string_source(&((yp_call_node_t *)node)->name), yp_string_length(&((yp_call_node_t *)node)->name)); @@ -323,7 +335,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_call_operator_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_call_operator_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char operator_id_buffer[12]; - yp_snprintf(operator_id_buffer, sizeof(operator_id_buffer), "%u", ((yp_call_operator_write_node_t *)node)->operator_id); + snprintf(operator_id_buffer, sizeof(operator_id_buffer), "%u", ((yp_call_operator_write_node_t *)node)->operator_id); yp_buffer_append_str(buffer, operator_id_buffer, strlen(operator_id_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -343,10 +355,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_case_node_t *)node)->predicate); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_case_node_t *)node)->conditions.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_case_node_t *)node)->conditions.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_case_node_t *) node)->conditions.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_case_node_t *)node)->consequent == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -359,12 +373,14 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_CLASS_NODE: { yp_buffer_append_str(buffer, "ClassNode(", 10); - for (uint32_t index = 0; index < ((yp_class_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_class_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); char locals_buffer[12]; - yp_snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_class_node_t *)node)->locals.ids[index]); + snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_class_node_t *)node)->locals.ids[index]); yp_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_class_node_t *)node)->class_keyword_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_class_node_t *)node)->constant_path); yp_buffer_append_str(buffer, ", ", 2); if (((yp_class_node_t *)node)->inheritance_operator_loc.start == NULL) { @@ -408,7 +424,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_class_variable_operator_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_class_variable_operator_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - yp_snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_class_variable_operator_write_node_t *)node)->operator); + snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_class_variable_operator_write_node_t *)node)->operator); yp_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -456,7 +472,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_constant_operator_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_constant_operator_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - yp_snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_constant_operator_write_node_t *)node)->operator); + snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_constant_operator_write_node_t *)node)->operator); yp_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -495,7 +511,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_constant_path_operator_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_constant_path_operator_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - yp_snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_constant_path_operator_write_node_t *)node)->operator); + snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_constant_path_operator_write_node_t *)node)->operator); yp_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -521,6 +537,22 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ")", 1); break; } + case YP_NODE_CONSTANT_WRITE_NODE: { + yp_buffer_append_str(buffer, "ConstantWriteNode(", 18); + prettyprint_location(buffer, parser, &((yp_constant_write_node_t *)node)->name_loc); + yp_buffer_append_str(buffer, ", ", 2); if (((yp_constant_write_node_t *)node)->value == NULL) { + yp_buffer_append_str(buffer, "nil", 3); + } else { + prettyprint_node(buffer, parser, (yp_node_t *)((yp_constant_write_node_t *)node)->value); + } + yp_buffer_append_str(buffer, ", ", 2); if (((yp_constant_write_node_t *)node)->operator_loc.start == NULL) { + yp_buffer_append_str(buffer, "nil", 3); + } else { + prettyprint_location(buffer, parser, &((yp_constant_write_node_t *)node)->operator_loc); + } + yp_buffer_append_str(buffer, ")", 1); + break; + } case YP_NODE_DEF_NODE: { yp_buffer_append_str(buffer, "DefNode(", 8); prettyprint_location(buffer, parser, &((yp_def_node_t *)node)->name_loc); @@ -539,12 +571,14 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_def_node_t *)node)->statements); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_def_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_def_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); char locals_buffer[12]; - yp_snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_def_node_t *)node)->locals.ids[index]); + snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_def_node_t *)node)->locals.ids[index]); yp_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_def_node_t *)node)->def_keyword_loc); yp_buffer_append_str(buffer, ", ", 2); if (((yp_def_node_t *)node)->operator_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); @@ -651,10 +685,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { prettyprint_node(buffer, parser, (yp_node_t *)((yp_find_pattern_node_t *)node)->constant); } yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_find_pattern_node_t *)node)->left); - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_find_pattern_node_t *)node)->requireds.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_find_pattern_node_t *)node)->requireds.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_find_pattern_node_t *) node)->requireds.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_find_pattern_node_t *)node)->right); yp_buffer_append_str(buffer, ", ", 2); if (((yp_find_pattern_node_t *)node)->opening_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); @@ -669,6 +705,25 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ")", 1); break; } + case YP_NODE_FLIP_FLOP_NODE: { + yp_buffer_append_str(buffer, "FlipFlopNode(", 13); + if (((yp_flip_flop_node_t *)node)->left == NULL) { + yp_buffer_append_str(buffer, "nil", 3); + } else { + prettyprint_node(buffer, parser, (yp_node_t *)((yp_flip_flop_node_t *)node)->left); + } + yp_buffer_append_str(buffer, ", ", 2); if (((yp_flip_flop_node_t *)node)->right == NULL) { + yp_buffer_append_str(buffer, "nil", 3); + } else { + prettyprint_node(buffer, parser, (yp_node_t *)((yp_flip_flop_node_t *)node)->right); + } + yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_flip_flop_node_t *)node)->operator_loc); + yp_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; + snprintf(flags_buffer, sizeof(flags_buffer), "+%d", node->flags >> 1); + yp_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); + yp_buffer_append_str(buffer, ")", 1); + break; + } case YP_NODE_FLOAT_NODE: { yp_buffer_append_str(buffer, "FloatNode(", 10); yp_buffer_append_str(buffer, ")", 1); @@ -736,7 +791,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_global_variable_operator_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_global_variable_operator_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - yp_snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_global_variable_operator_write_node_t *)node)->operator); + snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_global_variable_operator_write_node_t *)node)->operator); yp_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -765,10 +820,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_HASH_NODE: { yp_buffer_append_str(buffer, "HashNode(", 9); prettyprint_location(buffer, parser, &((yp_hash_node_t *)node)->opening_loc); - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_hash_node_t *)node)->elements.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_hash_node_t *)node)->elements.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_hash_node_t *) node)->elements.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_hash_node_t *)node)->closing_loc); yp_buffer_append_str(buffer, ")", 1); break; @@ -780,10 +837,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_hash_pattern_node_t *)node)->constant); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_hash_pattern_node_t *)node)->assocs.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_hash_pattern_node_t *)node)->assocs.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_hash_pattern_node_t *) node)->assocs.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_hash_pattern_node_t *)node)->kwrest == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -873,7 +932,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_instance_variable_operator_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_instance_variable_operator_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char operator_buffer[12]; - yp_snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_instance_variable_operator_write_node_t *)node)->operator); + snprintf(operator_buffer, sizeof(operator_buffer), "%u", ((yp_instance_variable_operator_write_node_t *)node)->operator); yp_buffer_append_str(buffer, operator_buffer, strlen(operator_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -907,13 +966,15 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_INTERPOLATED_REGULAR_EXPRESSION_NODE: { yp_buffer_append_str(buffer, "InterpolatedRegularExpressionNode(", 34); prettyprint_location(buffer, parser, &((yp_interpolated_regular_expression_node_t *)node)->opening_loc); - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_interpolated_regular_expression_node_t *)node)->parts.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_interpolated_regular_expression_node_t *)node)->parts.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_interpolated_regular_expression_node_t *) node)->parts.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_interpolated_regular_expression_node_t *)node)->closing_loc); yp_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - yp_snprintf(flags_buffer, sizeof(flags_buffer), "+%d", ((yp_interpolated_regular_expression_node_t *)node)->flags); + snprintf(flags_buffer, sizeof(flags_buffer), "+%d", node->flags >> 1); yp_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -925,10 +986,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_location(buffer, parser, &((yp_interpolated_string_node_t *)node)->opening_loc); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_interpolated_string_node_t *)node)->parts.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_interpolated_string_node_t *)node)->parts.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_interpolated_string_node_t *) node)->parts.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_interpolated_string_node_t *)node)->closing_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -944,10 +1007,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_location(buffer, parser, &((yp_interpolated_symbol_node_t *)node)->opening_loc); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_interpolated_symbol_node_t *)node)->parts.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_interpolated_symbol_node_t *)node)->parts.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_interpolated_symbol_node_t *) node)->parts.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_interpolated_symbol_node_t *)node)->closing_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -959,20 +1024,24 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_INTERPOLATED_X_STRING_NODE: { yp_buffer_append_str(buffer, "InterpolatedXStringNode(", 24); prettyprint_location(buffer, parser, &((yp_interpolated_x_string_node_t *)node)->opening_loc); - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_interpolated_x_string_node_t *)node)->parts.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_interpolated_x_string_node_t *)node)->parts.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_interpolated_x_string_node_t *) node)->parts.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_interpolated_x_string_node_t *)node)->closing_loc); yp_buffer_append_str(buffer, ")", 1); break; } case YP_NODE_KEYWORD_HASH_NODE: { yp_buffer_append_str(buffer, "KeywordHashNode(", 16); - for (uint32_t index = 0; index < ((yp_keyword_hash_node_t *)node)->elements.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_keyword_hash_node_t *)node)->elements.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_keyword_hash_node_t *) node)->elements.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ")", 1); break; } @@ -1000,12 +1069,14 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_LAMBDA_NODE: { yp_buffer_append_str(buffer, "LambdaNode(", 11); - for (uint32_t index = 0; index < ((yp_lambda_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_lambda_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); char locals_buffer[12]; - yp_snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_lambda_node_t *)node)->locals.ids[index]); + snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_lambda_node_t *)node)->locals.ids[index]); yp_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_lambda_node_t *)node)->opening_loc); yp_buffer_append_str(buffer, ", ", 2); if (((yp_lambda_node_t *)node)->parameters == NULL) { yp_buffer_append_str(buffer, "nil", 3); @@ -1026,7 +1097,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_local_variable_operator_and_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_local_variable_operator_and_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char constant_id_buffer[12]; - yp_snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_operator_and_write_node_t *)node)->constant_id); + snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_operator_and_write_node_t *)node)->constant_id); yp_buffer_append_str(buffer, constant_id_buffer, strlen(constant_id_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -1037,7 +1108,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_local_variable_operator_or_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_local_variable_operator_or_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char constant_id_buffer[12]; - yp_snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_operator_or_write_node_t *)node)->constant_id); + snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_operator_or_write_node_t *)node)->constant_id); yp_buffer_append_str(buffer, constant_id_buffer, strlen(constant_id_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -1048,10 +1119,10 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_local_variable_operator_write_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_local_variable_operator_write_node_t *)node)->value); yp_buffer_append_str(buffer, ", ", 2); char constant_id_buffer[12]; - yp_snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_operator_write_node_t *)node)->constant_id); + snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_operator_write_node_t *)node)->constant_id); yp_buffer_append_str(buffer, constant_id_buffer, strlen(constant_id_buffer)); yp_buffer_append_str(buffer, ", ", 2); char operator_id_buffer[12]; - yp_snprintf(operator_id_buffer, sizeof(operator_id_buffer), "%u", ((yp_local_variable_operator_write_node_t *)node)->operator_id); + snprintf(operator_id_buffer, sizeof(operator_id_buffer), "%u", ((yp_local_variable_operator_write_node_t *)node)->operator_id); yp_buffer_append_str(buffer, operator_id_buffer, strlen(operator_id_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -1059,10 +1130,10 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_LOCAL_VARIABLE_READ_NODE: { yp_buffer_append_str(buffer, "LocalVariableReadNode(", 22); char constant_id_buffer[12]; - yp_snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_read_node_t *)node)->constant_id); + snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_read_node_t *)node)->constant_id); yp_buffer_append_str(buffer, constant_id_buffer, strlen(constant_id_buffer)); yp_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - yp_snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((yp_local_variable_read_node_t *)node)->depth); + snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((yp_local_variable_read_node_t *)node)->depth); yp_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -1070,10 +1141,10 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_LOCAL_VARIABLE_WRITE_NODE: { yp_buffer_append_str(buffer, "LocalVariableWriteNode(", 23); char constant_id_buffer[12]; - yp_snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_write_node_t *)node)->constant_id); + snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_local_variable_write_node_t *)node)->constant_id); yp_buffer_append_str(buffer, constant_id_buffer, strlen(constant_id_buffer)); yp_buffer_append_str(buffer, ", ", 2); char depth_buffer[12]; - yp_snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((yp_local_variable_write_node_t *)node)->depth); + snprintf(depth_buffer, sizeof(depth_buffer), "+%d", ((yp_local_variable_write_node_t *)node)->depth); yp_buffer_append_str(buffer, depth_buffer, strlen(depth_buffer)); yp_buffer_append_str(buffer, ", ", 2); if (((yp_local_variable_write_node_t *)node)->value == NULL) { yp_buffer_append_str(buffer, "nil", 3); @@ -1112,12 +1183,14 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_MODULE_NODE: { yp_buffer_append_str(buffer, "ModuleNode(", 11); - for (uint32_t index = 0; index < ((yp_module_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_module_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); char locals_buffer[12]; - yp_snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_module_node_t *)node)->locals.ids[index]); + snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_module_node_t *)node)->locals.ids[index]); yp_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_module_node_t *)node)->module_keyword_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_module_node_t *)node)->constant_path); yp_buffer_append_str(buffer, ", ", 2); if (((yp_module_node_t *)node)->statements == NULL) { @@ -1131,10 +1204,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_MULTI_WRITE_NODE: { yp_buffer_append_str(buffer, "MultiWriteNode(", 15); - for (uint32_t index = 0; index < ((yp_multi_write_node_t *)node)->targets.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_multi_write_node_t *)node)->targets.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_multi_write_node_t *) node)->targets.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_multi_write_node_t *)node)->operator_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -1189,7 +1264,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_OPTIONAL_PARAMETER_NODE: { yp_buffer_append_str(buffer, "OptionalParameterNode(", 22); char constant_id_buffer[12]; - yp_snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_optional_parameter_node_t *)node)->constant_id); + snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_optional_parameter_node_t *)node)->constant_id); yp_buffer_append_str(buffer, constant_id_buffer, strlen(constant_id_buffer)); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_optional_parameter_node_t *)node)->name_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_optional_parameter_node_t *)node)->operator_loc); @@ -1207,27 +1282,35 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_PARAMETERS_NODE: { yp_buffer_append_str(buffer, "ParametersNode(", 15); - for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->requireds.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->requireds.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_parameters_node_t *) node)->requireds.nodes[index]); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->optionals.size; index++) { + yp_buffer_append_str(buffer, "]", 1); + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->optionals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_parameters_node_t *) node)->optionals.nodes[index]); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->posts.size; index++) { + yp_buffer_append_str(buffer, "]", 1); + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->posts.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_parameters_node_t *) node)->posts.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_parameters_node_t *)node)->rest == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_parameters_node_t *)node)->rest); } - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->keywords.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_parameters_node_t *)node)->keywords.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_parameters_node_t *) node)->keywords.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_parameters_node_t *)node)->keyword_rest == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -1297,12 +1380,14 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_PROGRAM_NODE: { yp_buffer_append_str(buffer, "ProgramNode(", 12); - for (uint32_t index = 0; index < ((yp_program_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_program_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); char locals_buffer[12]; - yp_snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_program_node_t *)node)->locals.ids[index]); + snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_program_node_t *)node)->locals.ids[index]); yp_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_program_node_t *)node)->statements); yp_buffer_append_str(buffer, ")", 1); break; @@ -1321,7 +1406,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_range_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - yp_snprintf(flags_buffer, sizeof(flags_buffer), "+%d", ((yp_range_node_t *)node)->flags); + snprintf(flags_buffer, sizeof(flags_buffer), "+%d", node->flags >> 1); yp_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -1346,17 +1431,19 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { yp_buffer_append_str(buffer, yp_string_source(&((yp_regular_expression_node_t *)node)->unescaped), yp_string_length(&((yp_regular_expression_node_t *)node)->unescaped)); yp_buffer_append_str(buffer, "\"", 1); yp_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; - yp_snprintf(flags_buffer, sizeof(flags_buffer), "+%d", ((yp_regular_expression_node_t *)node)->flags); + snprintf(flags_buffer, sizeof(flags_buffer), "+%d", node->flags >> 1); yp_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); yp_buffer_append_str(buffer, ")", 1); break; } case YP_NODE_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { yp_buffer_append_str(buffer, "RequiredDestructuredParameterNode(", 34); - for (uint32_t index = 0; index < ((yp_required_destructured_parameter_node_t *)node)->parameters.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_required_destructured_parameter_node_t *)node)->parameters.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_required_destructured_parameter_node_t *) node)->parameters.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_required_destructured_parameter_node_t *)node)->opening_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_required_destructured_parameter_node_t *)node)->closing_loc); yp_buffer_append_str(buffer, ")", 1); @@ -1365,7 +1452,7 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_REQUIRED_PARAMETER_NODE: { yp_buffer_append_str(buffer, "RequiredParameterNode(", 22); char constant_id_buffer[12]; - yp_snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_required_parameter_node_t *)node)->constant_id); + snprintf(constant_id_buffer, sizeof(constant_id_buffer), "%u", ((yp_required_parameter_node_t *)node)->constant_id); yp_buffer_append_str(buffer, constant_id_buffer, strlen(constant_id_buffer)); yp_buffer_append_str(buffer, ")", 1); break; @@ -1381,19 +1468,21 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { case YP_NODE_RESCUE_NODE: { yp_buffer_append_str(buffer, "RescueNode(", 11); prettyprint_location(buffer, parser, &((yp_rescue_node_t *)node)->keyword_loc); - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_rescue_node_t *)node)->exceptions.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_rescue_node_t *)node)->exceptions.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_rescue_node_t *) node)->exceptions.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_rescue_node_t *)node)->operator_loc.start == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { prettyprint_location(buffer, parser, &((yp_rescue_node_t *)node)->operator_loc); } - yp_buffer_append_str(buffer, ", ", 2); if (((yp_rescue_node_t *)node)->exception == NULL) { + yp_buffer_append_str(buffer, ", ", 2); if (((yp_rescue_node_t *)node)->reference == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { - prettyprint_node(buffer, parser, (yp_node_t *)((yp_rescue_node_t *)node)->exception); + prettyprint_node(buffer, parser, (yp_node_t *)((yp_rescue_node_t *)node)->reference); } yp_buffer_append_str(buffer, ", ", 2); if (((yp_rescue_node_t *)node)->statements == NULL) { yp_buffer_append_str(buffer, "nil", 3); @@ -1442,12 +1531,14 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_SINGLETON_CLASS_NODE: { yp_buffer_append_str(buffer, "SingletonClassNode(", 19); - for (uint32_t index = 0; index < ((yp_singleton_class_node_t *)node)->locals.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_singleton_class_node_t *)node)->locals.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); char locals_buffer[12]; - yp_snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_singleton_class_node_t *)node)->locals.ids[index]); + snprintf(locals_buffer, sizeof(locals_buffer), "%u", ((yp_singleton_class_node_t *)node)->locals.ids[index]); yp_buffer_append_str(buffer, locals_buffer, strlen(locals_buffer)); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_singleton_class_node_t *)node)->class_keyword_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_singleton_class_node_t *)node)->operator_loc); yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *)((yp_singleton_class_node_t *)node)->expression); @@ -1491,10 +1582,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_STATEMENTS_NODE: { yp_buffer_append_str(buffer, "StatementsNode(", 15); - for (uint32_t index = 0; index < ((yp_statements_node_t *)node)->body.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_statements_node_t *)node)->body.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_statements_node_t *) node)->body.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ")", 1); break; } @@ -1576,10 +1669,12 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } case YP_NODE_UNDEF_NODE: { yp_buffer_append_str(buffer, "UndefNode(", 10); - for (uint32_t index = 0; index < ((yp_undef_node_t *)node)->names.size; index++) { + yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_undef_node_t *)node)->names.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_undef_node_t *) node)->names.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); prettyprint_location(buffer, parser, &((yp_undef_node_t *)node)->keyword_loc); yp_buffer_append_str(buffer, ")", 1); break; @@ -1615,16 +1710,21 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_until_node_t *)node)->statements); } + yp_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; + snprintf(flags_buffer, sizeof(flags_buffer), "+%d", node->flags >> 1); + yp_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); yp_buffer_append_str(buffer, ")", 1); break; } case YP_NODE_WHEN_NODE: { yp_buffer_append_str(buffer, "WhenNode(", 9); prettyprint_location(buffer, parser, &((yp_when_node_t *)node)->keyword_loc); - yp_buffer_append_str(buffer, ", ", 2); for (uint32_t index = 0; index < ((yp_when_node_t *)node)->conditions.size; index++) { + yp_buffer_append_str(buffer, ", ", 2); yp_buffer_append_str(buffer, "[", 1); + for (uint32_t index = 0; index < ((yp_when_node_t *)node)->conditions.size; index++) { if (index != 0) yp_buffer_append_str(buffer, ", ", 2); prettyprint_node(buffer, parser, (yp_node_t *) ((yp_when_node_t *) node)->conditions.nodes[index]); } + yp_buffer_append_str(buffer, "]", 1); yp_buffer_append_str(buffer, ", ", 2); if (((yp_when_node_t *)node)->statements == NULL) { yp_buffer_append_str(buffer, "nil", 3); } else { @@ -1642,6 +1742,9 @@ prettyprint_node(yp_buffer_t *buffer, yp_parser_t *parser, yp_node_t *node) { } else { prettyprint_node(buffer, parser, (yp_node_t *)((yp_while_node_t *)node)->statements); } + yp_buffer_append_str(buffer, ", ", 2); char flags_buffer[12]; + snprintf(flags_buffer, sizeof(flags_buffer), "+%d", node->flags >> 1); + yp_buffer_append_str(buffer, flags_buffer, strlen(flags_buffer)); yp_buffer_append_str(buffer, ")", 1); break; } diff --git a/yarp/serialize.c b/yarp/serialize.c index 512dedef65e287..fbdf337f8dab1f 100644 --- a/yarp/serialize.c +++ b/yarp/serialize.c @@ -5,20 +5,18 @@ /* if you are looking to modify the */ /* template */ /******************************************************************************/ -#include "yarp/ast.h" -#include "yarp/parser.h" -#include "yarp/util/yp_buffer.h" +#include "yarp.h" #include static inline uint32_t -yp_long_to_u32(long value) { - assert(value >= 0 && (unsigned long)value < UINT32_MAX); +yp_ptrdifft_to_u32(ptrdiff_t value) { + assert(value >= 0 && ((unsigned long) value) < UINT32_MAX); return (uint32_t) value; } static inline uint32_t -yp_ulong_to_u32(unsigned long value) { +yp_sizet_to_u32(size_t value) { assert(value < UINT32_MAX); return (uint32_t) value; } @@ -29,19 +27,19 @@ serialize_location(yp_parser_t *parser, yp_location_t *location, yp_buffer_t *bu assert(location->end); assert(location->start <= location->end); - yp_buffer_append_u32(buffer, yp_long_to_u32(location->start - parser->start)); - yp_buffer_append_u32(buffer, yp_long_to_u32(location->end - location->start)); + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(location->start - parser->start)); + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(location->end - location->start)); } void yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { - yp_buffer_append_u8(buffer, node->type); + yp_buffer_append_u8(buffer, (uint8_t) YP_NODE_TYPE(node)); size_t offset = buffer->length; serialize_location(parser, &node->location, buffer); - switch (node->type) { + switch (YP_NODE_TYPE(node)) { case YP_NODE_ALIAS_NODE: { yp_serialize_node(parser, (yp_node_t *)((yp_alias_node_t *)node)->new_name, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_alias_node_t *)node)->old_name, buffer); @@ -61,7 +59,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_ARGUMENTS_NODE: { - uint32_t arguments_size = yp_ulong_to_u32(((yp_arguments_node_t *)node)->arguments.size); + uint32_t arguments_size = yp_sizet_to_u32(((yp_arguments_node_t *)node)->arguments.size); yp_buffer_append_u32(buffer, arguments_size); for (uint32_t index = 0; index < arguments_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_arguments_node_t *)node)->arguments.nodes[index], buffer); @@ -69,7 +67,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_ARRAY_NODE: { - uint32_t elements_size = yp_ulong_to_u32(((yp_array_node_t *)node)->elements.size); + uint32_t elements_size = yp_sizet_to_u32(((yp_array_node_t *)node)->elements.size); yp_buffer_append_u32(buffer, elements_size); for (uint32_t index = 0; index < elements_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_array_node_t *)node)->elements.nodes[index], buffer); @@ -94,7 +92,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_array_pattern_node_t *)node)->constant, buffer); } - uint32_t requireds_size = yp_ulong_to_u32(((yp_array_pattern_node_t *)node)->requireds.size); + uint32_t requireds_size = yp_sizet_to_u32(((yp_array_pattern_node_t *)node)->requireds.size); yp_buffer_append_u32(buffer, requireds_size); for (uint32_t index = 0; index < requireds_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_array_pattern_node_t *)node)->requireds.nodes[index], buffer); @@ -104,7 +102,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_array_pattern_node_t *)node)->rest, buffer); } - uint32_t posts_size = yp_ulong_to_u32(((yp_array_pattern_node_t *)node)->posts.size); + uint32_t posts_size = yp_sizet_to_u32(((yp_array_pattern_node_t *)node)->posts.size); yp_buffer_append_u32(buffer, posts_size); for (uint32_t index = 0; index < posts_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_array_pattern_node_t *)node)->posts.nodes[index], buffer); @@ -195,10 +193,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_BLOCK_NODE: { - uint32_t locals_size = yp_ulong_to_u32(((yp_block_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_block_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_block_node_t *)node)->locals.ids[index])); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_block_node_t *)node)->locals.ids[index])); } if (((yp_block_node_t *)node)->parameters == NULL) { yp_buffer_append_u8(buffer, 0); @@ -230,7 +228,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_block_parameters_node_t *)node)->parameters, buffer); } - uint32_t locals_size = yp_ulong_to_u32(((yp_block_parameters_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_block_parameters_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { serialize_location(parser, &((yp_block_parameters_node_t *)node)->locals.locations[index], buffer); @@ -298,8 +296,8 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_call_node_t *)node)->block, buffer); } - yp_buffer_append_u32(buffer, ((yp_call_node_t *)node)->flags); - uint32_t name_length = yp_ulong_to_u32(yp_string_length(&((yp_call_node_t *)node)->name)); + yp_buffer_append_u32(buffer, node->flags >> 1); + uint32_t name_length = yp_sizet_to_u32(yp_string_length(&((yp_call_node_t *)node)->name)); yp_buffer_append_u32(buffer, name_length); yp_buffer_append_str(buffer, yp_string_source(&((yp_call_node_t *)node)->name), name_length); break; @@ -320,7 +318,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_serialize_node(parser, (yp_node_t *)((yp_call_operator_write_node_t *)node)->target, buffer); serialize_location(parser, &((yp_call_operator_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_call_operator_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_call_operator_write_node_t *)node)->operator_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_call_operator_write_node_t *)node)->operator_id)); break; } case YP_NODE_CAPTURE_PATTERN_NODE: { @@ -335,7 +333,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_case_node_t *)node)->predicate, buffer); } - uint32_t conditions_size = yp_ulong_to_u32(((yp_case_node_t *)node)->conditions.size); + uint32_t conditions_size = yp_sizet_to_u32(((yp_case_node_t *)node)->conditions.size); yp_buffer_append_u32(buffer, conditions_size); for (uint32_t index = 0; index < conditions_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_case_node_t *)node)->conditions.nodes[index], buffer); @@ -350,10 +348,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_CLASS_NODE: { - uint32_t locals_size = yp_ulong_to_u32(((yp_class_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_class_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_class_node_t *)node)->locals.ids[index])); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_class_node_t *)node)->locals.ids[index])); } serialize_location(parser, &((yp_class_node_t *)node)->class_keyword_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_class_node_t *)node)->constant_path, buffer); @@ -392,7 +390,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { serialize_location(parser, &((yp_class_variable_operator_write_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_class_variable_operator_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_class_variable_operator_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_class_variable_operator_write_node_t *)node)->operator)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_class_variable_operator_write_node_t *)node)->operator)); break; } case YP_NODE_CLASS_VARIABLE_READ_NODE: { @@ -429,7 +427,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { serialize_location(parser, &((yp_constant_operator_write_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_constant_operator_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_constant_operator_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_constant_operator_write_node_t *)node)->operator)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_constant_operator_write_node_t *)node)->operator)); break; } case YP_NODE_CONSTANT_PATH_NODE: { @@ -458,7 +456,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_serialize_node(parser, (yp_node_t *)((yp_constant_path_operator_write_node_t *)node)->target, buffer); serialize_location(parser, &((yp_constant_path_operator_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_constant_path_operator_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_constant_path_operator_write_node_t *)node)->operator)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_constant_path_operator_write_node_t *)node)->operator)); break; } case YP_NODE_CONSTANT_PATH_WRITE_NODE: { @@ -479,11 +477,26 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { case YP_NODE_CONSTANT_READ_NODE: { break; } + case YP_NODE_CONSTANT_WRITE_NODE: { + serialize_location(parser, &((yp_constant_write_node_t *)node)->name_loc, buffer); + if (((yp_constant_write_node_t *)node)->value == NULL) { + yp_buffer_append_u8(buffer, 0); + } else { + yp_serialize_node(parser, (yp_node_t *)((yp_constant_write_node_t *)node)->value, buffer); + } + if (((yp_constant_write_node_t *)node)->operator_loc.start == NULL) { + yp_buffer_append_u8(buffer, 0); + } else { + yp_buffer_append_u8(buffer, 1); + serialize_location(parser, &((yp_constant_write_node_t *)node)->operator_loc, buffer); + } + break; + } case YP_NODE_DEF_NODE: { - // serialize length - // encoding of location u32s make us need to save this offset. - size_t length_offset = buffer->length; - yp_buffer_append_str(buffer, "\0\0\0\0", 4); /* consume 4 bytes, updated below */ + // serialize length + // encoding of location u32s make us need to save this offset. + size_t length_offset = buffer->length; + yp_buffer_append_str(buffer, "\0\0\0\0", 4); /* consume 4 bytes, updated below */ serialize_location(parser, &((yp_def_node_t *)node)->name_loc, buffer); if (((yp_def_node_t *)node)->receiver == NULL) { yp_buffer_append_u8(buffer, 0); @@ -500,10 +513,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_def_node_t *)node)->statements, buffer); } - uint32_t locals_size = yp_ulong_to_u32(((yp_def_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_def_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_def_node_t *)node)->locals.ids[index])); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_def_node_t *)node)->locals.ids[index])); } serialize_location(parser, &((yp_def_node_t *)node)->def_keyword_loc, buffer); if (((yp_def_node_t *)node)->operator_loc.start == NULL) { @@ -536,9 +549,9 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_buffer_append_u8(buffer, 1); serialize_location(parser, &((yp_def_node_t *)node)->end_keyword_loc, buffer); } - // serialize length - uint32_t length = yp_ulong_to_u32(buffer->length - offset - sizeof(uint32_t)); - memcpy(buffer->value + length_offset, &length, sizeof(uint32_t)); + // serialize length + uint32_t length = yp_sizet_to_u32(buffer->length - offset - sizeof(uint32_t)); + memcpy(buffer->value + length_offset, &length, sizeof(uint32_t)); break; } case YP_NODE_DEFINED_NODE: { @@ -608,7 +621,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_serialize_node(parser, (yp_node_t *)((yp_find_pattern_node_t *)node)->constant, buffer); } yp_serialize_node(parser, (yp_node_t *)((yp_find_pattern_node_t *)node)->left, buffer); - uint32_t requireds_size = yp_ulong_to_u32(((yp_find_pattern_node_t *)node)->requireds.size); + uint32_t requireds_size = yp_sizet_to_u32(((yp_find_pattern_node_t *)node)->requireds.size); yp_buffer_append_u32(buffer, requireds_size); for (uint32_t index = 0; index < requireds_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_find_pattern_node_t *)node)->requireds.nodes[index], buffer); @@ -628,6 +641,21 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } break; } + case YP_NODE_FLIP_FLOP_NODE: { + if (((yp_flip_flop_node_t *)node)->left == NULL) { + yp_buffer_append_u8(buffer, 0); + } else { + yp_serialize_node(parser, (yp_node_t *)((yp_flip_flop_node_t *)node)->left, buffer); + } + if (((yp_flip_flop_node_t *)node)->right == NULL) { + yp_buffer_append_u8(buffer, 0); + } else { + yp_serialize_node(parser, (yp_node_t *)((yp_flip_flop_node_t *)node)->right, buffer); + } + serialize_location(parser, &((yp_flip_flop_node_t *)node)->operator_loc, buffer); + yp_buffer_append_u32(buffer, node->flags >> 1); + break; + } case YP_NODE_FLOAT_NODE: { break; } @@ -680,7 +708,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { serialize_location(parser, &((yp_global_variable_operator_write_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_global_variable_operator_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_global_variable_operator_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_global_variable_operator_write_node_t *)node)->operator)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_global_variable_operator_write_node_t *)node)->operator)); break; } case YP_NODE_GLOBAL_VARIABLE_READ_NODE: { @@ -703,7 +731,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } case YP_NODE_HASH_NODE: { serialize_location(parser, &((yp_hash_node_t *)node)->opening_loc, buffer); - uint32_t elements_size = yp_ulong_to_u32(((yp_hash_node_t *)node)->elements.size); + uint32_t elements_size = yp_sizet_to_u32(((yp_hash_node_t *)node)->elements.size); yp_buffer_append_u32(buffer, elements_size); for (uint32_t index = 0; index < elements_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_hash_node_t *)node)->elements.nodes[index], buffer); @@ -717,7 +745,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_hash_pattern_node_t *)node)->constant, buffer); } - uint32_t assocs_size = yp_ulong_to_u32(((yp_hash_pattern_node_t *)node)->assocs.size); + uint32_t assocs_size = yp_sizet_to_u32(((yp_hash_pattern_node_t *)node)->assocs.size); yp_buffer_append_u32(buffer, assocs_size); for (uint32_t index = 0; index < assocs_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_hash_pattern_node_t *)node)->assocs.nodes[index], buffer); @@ -803,7 +831,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { serialize_location(parser, &((yp_instance_variable_operator_write_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_instance_variable_operator_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_instance_variable_operator_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_instance_variable_operator_write_node_t *)node)->operator)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_instance_variable_operator_write_node_t *)node)->operator)); break; } case YP_NODE_INSTANCE_VARIABLE_READ_NODE: { @@ -829,13 +857,13 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } case YP_NODE_INTERPOLATED_REGULAR_EXPRESSION_NODE: { serialize_location(parser, &((yp_interpolated_regular_expression_node_t *)node)->opening_loc, buffer); - uint32_t parts_size = yp_ulong_to_u32(((yp_interpolated_regular_expression_node_t *)node)->parts.size); + uint32_t parts_size = yp_sizet_to_u32(((yp_interpolated_regular_expression_node_t *)node)->parts.size); yp_buffer_append_u32(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_interpolated_regular_expression_node_t *)node)->parts.nodes[index], buffer); } serialize_location(parser, &((yp_interpolated_regular_expression_node_t *)node)->closing_loc, buffer); - yp_buffer_append_u32(buffer, ((yp_interpolated_regular_expression_node_t *)node)->flags); + yp_buffer_append_u32(buffer, node->flags >> 1); break; } case YP_NODE_INTERPOLATED_STRING_NODE: { @@ -845,7 +873,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_buffer_append_u8(buffer, 1); serialize_location(parser, &((yp_interpolated_string_node_t *)node)->opening_loc, buffer); } - uint32_t parts_size = yp_ulong_to_u32(((yp_interpolated_string_node_t *)node)->parts.size); + uint32_t parts_size = yp_sizet_to_u32(((yp_interpolated_string_node_t *)node)->parts.size); yp_buffer_append_u32(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_interpolated_string_node_t *)node)->parts.nodes[index], buffer); @@ -865,7 +893,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_buffer_append_u8(buffer, 1); serialize_location(parser, &((yp_interpolated_symbol_node_t *)node)->opening_loc, buffer); } - uint32_t parts_size = yp_ulong_to_u32(((yp_interpolated_symbol_node_t *)node)->parts.size); + uint32_t parts_size = yp_sizet_to_u32(((yp_interpolated_symbol_node_t *)node)->parts.size); yp_buffer_append_u32(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_interpolated_symbol_node_t *)node)->parts.nodes[index], buffer); @@ -880,7 +908,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } case YP_NODE_INTERPOLATED_X_STRING_NODE: { serialize_location(parser, &((yp_interpolated_x_string_node_t *)node)->opening_loc, buffer); - uint32_t parts_size = yp_ulong_to_u32(((yp_interpolated_x_string_node_t *)node)->parts.size); + uint32_t parts_size = yp_sizet_to_u32(((yp_interpolated_x_string_node_t *)node)->parts.size); yp_buffer_append_u32(buffer, parts_size); for (uint32_t index = 0; index < parts_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_interpolated_x_string_node_t *)node)->parts.nodes[index], buffer); @@ -889,7 +917,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_KEYWORD_HASH_NODE: { - uint32_t elements_size = yp_ulong_to_u32(((yp_keyword_hash_node_t *)node)->elements.size); + uint32_t elements_size = yp_sizet_to_u32(((yp_keyword_hash_node_t *)node)->elements.size); yp_buffer_append_u32(buffer, elements_size); for (uint32_t index = 0; index < elements_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_keyword_hash_node_t *)node)->elements.nodes[index], buffer); @@ -916,10 +944,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_LAMBDA_NODE: { - uint32_t locals_size = yp_ulong_to_u32(((yp_lambda_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_lambda_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_lambda_node_t *)node)->locals.ids[index])); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_lambda_node_t *)node)->locals.ids[index])); } serialize_location(parser, &((yp_lambda_node_t *)node)->opening_loc, buffer); if (((yp_lambda_node_t *)node)->parameters == NULL) { @@ -938,31 +966,31 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { serialize_location(parser, &((yp_local_variable_operator_and_write_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_local_variable_operator_and_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_local_variable_operator_and_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_local_variable_operator_and_write_node_t *)node)->constant_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_local_variable_operator_and_write_node_t *)node)->constant_id)); break; } case YP_NODE_LOCAL_VARIABLE_OPERATOR_OR_WRITE_NODE: { serialize_location(parser, &((yp_local_variable_operator_or_write_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_local_variable_operator_or_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_local_variable_operator_or_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_local_variable_operator_or_write_node_t *)node)->constant_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_local_variable_operator_or_write_node_t *)node)->constant_id)); break; } case YP_NODE_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: { serialize_location(parser, &((yp_local_variable_operator_write_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_local_variable_operator_write_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_local_variable_operator_write_node_t *)node)->value, buffer); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_local_variable_operator_write_node_t *)node)->constant_id)); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_local_variable_operator_write_node_t *)node)->operator_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_local_variable_operator_write_node_t *)node)->constant_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_local_variable_operator_write_node_t *)node)->operator_id)); break; } case YP_NODE_LOCAL_VARIABLE_READ_NODE: { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_local_variable_read_node_t *)node)->constant_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_local_variable_read_node_t *)node)->constant_id)); yp_buffer_append_u32(buffer, ((yp_local_variable_read_node_t *)node)->depth); break; } case YP_NODE_LOCAL_VARIABLE_WRITE_NODE: { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_local_variable_write_node_t *)node)->constant_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_local_variable_write_node_t *)node)->constant_id)); yp_buffer_append_u32(buffer, ((yp_local_variable_write_node_t *)node)->depth); if (((yp_local_variable_write_node_t *)node)->value == NULL) { yp_buffer_append_u8(buffer, 0); @@ -994,10 +1022,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_MODULE_NODE: { - uint32_t locals_size = yp_ulong_to_u32(((yp_module_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_module_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_module_node_t *)node)->locals.ids[index])); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_module_node_t *)node)->locals.ids[index])); } serialize_location(parser, &((yp_module_node_t *)node)->module_keyword_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_module_node_t *)node)->constant_path, buffer); @@ -1010,7 +1038,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_MULTI_WRITE_NODE: { - uint32_t targets_size = yp_ulong_to_u32(((yp_multi_write_node_t *)node)->targets.size); + uint32_t targets_size = yp_sizet_to_u32(((yp_multi_write_node_t *)node)->targets.size); yp_buffer_append_u32(buffer, targets_size); for (uint32_t index = 0; index < targets_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_multi_write_node_t *)node)->targets.nodes[index], buffer); @@ -1061,7 +1089,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_OPTIONAL_PARAMETER_NODE: { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_optional_parameter_node_t *)node)->constant_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_optional_parameter_node_t *)node)->constant_id)); serialize_location(parser, &((yp_optional_parameter_node_t *)node)->name_loc, buffer); serialize_location(parser, &((yp_optional_parameter_node_t *)node)->operator_loc, buffer); yp_serialize_node(parser, (yp_node_t *)((yp_optional_parameter_node_t *)node)->value, buffer); @@ -1074,17 +1102,17 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_PARAMETERS_NODE: { - uint32_t requireds_size = yp_ulong_to_u32(((yp_parameters_node_t *)node)->requireds.size); + uint32_t requireds_size = yp_sizet_to_u32(((yp_parameters_node_t *)node)->requireds.size); yp_buffer_append_u32(buffer, requireds_size); for (uint32_t index = 0; index < requireds_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_parameters_node_t *)node)->requireds.nodes[index], buffer); } - uint32_t optionals_size = yp_ulong_to_u32(((yp_parameters_node_t *)node)->optionals.size); + uint32_t optionals_size = yp_sizet_to_u32(((yp_parameters_node_t *)node)->optionals.size); yp_buffer_append_u32(buffer, optionals_size); for (uint32_t index = 0; index < optionals_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_parameters_node_t *)node)->optionals.nodes[index], buffer); } - uint32_t posts_size = yp_ulong_to_u32(((yp_parameters_node_t *)node)->posts.size); + uint32_t posts_size = yp_sizet_to_u32(((yp_parameters_node_t *)node)->posts.size); yp_buffer_append_u32(buffer, posts_size); for (uint32_t index = 0; index < posts_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_parameters_node_t *)node)->posts.nodes[index], buffer); @@ -1094,7 +1122,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_parameters_node_t *)node)->rest, buffer); } - uint32_t keywords_size = yp_ulong_to_u32(((yp_parameters_node_t *)node)->keywords.size); + uint32_t keywords_size = yp_sizet_to_u32(((yp_parameters_node_t *)node)->keywords.size); yp_buffer_append_u32(buffer, keywords_size); for (uint32_t index = 0; index < keywords_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_parameters_node_t *)node)->keywords.nodes[index], buffer); @@ -1156,10 +1184,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_PROGRAM_NODE: { - uint32_t locals_size = yp_ulong_to_u32(((yp_program_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_program_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_program_node_t *)node)->locals.ids[index])); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_program_node_t *)node)->locals.ids[index])); } yp_serialize_node(parser, (yp_node_t *)((yp_program_node_t *)node)->statements, buffer); break; @@ -1176,7 +1204,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_serialize_node(parser, (yp_node_t *)((yp_range_node_t *)node)->right, buffer); } serialize_location(parser, &((yp_range_node_t *)node)->operator_loc, buffer); - yp_buffer_append_u32(buffer, ((yp_range_node_t *)node)->flags); + yp_buffer_append_u32(buffer, node->flags >> 1); break; } case YP_NODE_RATIONAL_NODE: { @@ -1190,14 +1218,14 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { serialize_location(parser, &((yp_regular_expression_node_t *)node)->opening_loc, buffer); serialize_location(parser, &((yp_regular_expression_node_t *)node)->content_loc, buffer); serialize_location(parser, &((yp_regular_expression_node_t *)node)->closing_loc, buffer); - uint32_t unescaped_length = yp_ulong_to_u32(yp_string_length(&((yp_regular_expression_node_t *)node)->unescaped)); + uint32_t unescaped_length = yp_sizet_to_u32(yp_string_length(&((yp_regular_expression_node_t *)node)->unescaped)); yp_buffer_append_u32(buffer, unescaped_length); yp_buffer_append_str(buffer, yp_string_source(&((yp_regular_expression_node_t *)node)->unescaped), unescaped_length); - yp_buffer_append_u32(buffer, ((yp_regular_expression_node_t *)node)->flags); + yp_buffer_append_u32(buffer, node->flags >> 1); break; } case YP_NODE_REQUIRED_DESTRUCTURED_PARAMETER_NODE: { - uint32_t parameters_size = yp_ulong_to_u32(((yp_required_destructured_parameter_node_t *)node)->parameters.size); + uint32_t parameters_size = yp_sizet_to_u32(((yp_required_destructured_parameter_node_t *)node)->parameters.size); yp_buffer_append_u32(buffer, parameters_size); for (uint32_t index = 0; index < parameters_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_required_destructured_parameter_node_t *)node)->parameters.nodes[index], buffer); @@ -1207,7 +1235,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_REQUIRED_PARAMETER_NODE: { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_required_parameter_node_t *)node)->constant_id)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_required_parameter_node_t *)node)->constant_id)); break; } case YP_NODE_RESCUE_MODIFIER_NODE: { @@ -1218,7 +1246,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } case YP_NODE_RESCUE_NODE: { serialize_location(parser, &((yp_rescue_node_t *)node)->keyword_loc, buffer); - uint32_t exceptions_size = yp_ulong_to_u32(((yp_rescue_node_t *)node)->exceptions.size); + uint32_t exceptions_size = yp_sizet_to_u32(((yp_rescue_node_t *)node)->exceptions.size); yp_buffer_append_u32(buffer, exceptions_size); for (uint32_t index = 0; index < exceptions_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_rescue_node_t *)node)->exceptions.nodes[index], buffer); @@ -1229,10 +1257,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_buffer_append_u8(buffer, 1); serialize_location(parser, &((yp_rescue_node_t *)node)->operator_loc, buffer); } - if (((yp_rescue_node_t *)node)->exception == NULL) { + if (((yp_rescue_node_t *)node)->reference == NULL) { yp_buffer_append_u8(buffer, 0); } else { - yp_serialize_node(parser, (yp_node_t *)((yp_rescue_node_t *)node)->exception, buffer); + yp_serialize_node(parser, (yp_node_t *)((yp_rescue_node_t *)node)->reference, buffer); } if (((yp_rescue_node_t *)node)->statements == NULL) { yp_buffer_append_u8(buffer, 0); @@ -1272,10 +1300,10 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_SINGLETON_CLASS_NODE: { - uint32_t locals_size = yp_ulong_to_u32(((yp_singleton_class_node_t *)node)->locals.size); + uint32_t locals_size = yp_sizet_to_u32(((yp_singleton_class_node_t *)node)->locals.size); yp_buffer_append_u32(buffer, locals_size); for (uint32_t index = 0; index < locals_size; index++) { - yp_buffer_append_u32(buffer, yp_ulong_to_u32(((yp_singleton_class_node_t *)node)->locals.ids[index])); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(((yp_singleton_class_node_t *)node)->locals.ids[index])); } serialize_location(parser, &((yp_singleton_class_node_t *)node)->class_keyword_loc, buffer); serialize_location(parser, &((yp_singleton_class_node_t *)node)->operator_loc, buffer); @@ -1292,7 +1320,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_SOURCE_FILE_NODE: { - uint32_t filepath_length = yp_ulong_to_u32(yp_string_length(&((yp_source_file_node_t *)node)->filepath)); + uint32_t filepath_length = yp_sizet_to_u32(yp_string_length(&((yp_source_file_node_t *)node)->filepath)); yp_buffer_append_u32(buffer, filepath_length); yp_buffer_append_str(buffer, yp_string_source(&((yp_source_file_node_t *)node)->filepath), filepath_length); break; @@ -1310,7 +1338,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_STATEMENTS_NODE: { - uint32_t body_size = yp_ulong_to_u32(((yp_statements_node_t *)node)->body.size); + uint32_t body_size = yp_sizet_to_u32(((yp_statements_node_t *)node)->body.size); yp_buffer_append_u32(buffer, body_size); for (uint32_t index = 0; index < body_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_statements_node_t *)node)->body.nodes[index], buffer); @@ -1336,7 +1364,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_buffer_append_u8(buffer, 1); serialize_location(parser, &((yp_string_node_t *)node)->closing_loc, buffer); } - uint32_t unescaped_length = yp_ulong_to_u32(yp_string_length(&((yp_string_node_t *)node)->unescaped)); + uint32_t unescaped_length = yp_sizet_to_u32(yp_string_length(&((yp_string_node_t *)node)->unescaped)); yp_buffer_append_u32(buffer, unescaped_length); yp_buffer_append_str(buffer, yp_string_source(&((yp_string_node_t *)node)->unescaped), unescaped_length); break; @@ -1381,7 +1409,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { yp_buffer_append_u8(buffer, 1); serialize_location(parser, &((yp_symbol_node_t *)node)->closing_loc, buffer); } - uint32_t unescaped_length = yp_ulong_to_u32(yp_string_length(&((yp_symbol_node_t *)node)->unescaped)); + uint32_t unescaped_length = yp_sizet_to_u32(yp_string_length(&((yp_symbol_node_t *)node)->unescaped)); yp_buffer_append_u32(buffer, unescaped_length); yp_buffer_append_str(buffer, yp_string_source(&((yp_symbol_node_t *)node)->unescaped), unescaped_length); break; @@ -1390,7 +1418,7 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { break; } case YP_NODE_UNDEF_NODE: { - uint32_t names_size = yp_ulong_to_u32(((yp_undef_node_t *)node)->names.size); + uint32_t names_size = yp_sizet_to_u32(((yp_undef_node_t *)node)->names.size); yp_buffer_append_u32(buffer, names_size); for (uint32_t index = 0; index < names_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_undef_node_t *)node)->names.nodes[index], buffer); @@ -1427,11 +1455,12 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_until_node_t *)node)->statements, buffer); } + yp_buffer_append_u32(buffer, node->flags >> 1); break; } case YP_NODE_WHEN_NODE: { serialize_location(parser, &((yp_when_node_t *)node)->keyword_loc, buffer); - uint32_t conditions_size = yp_ulong_to_u32(((yp_when_node_t *)node)->conditions.size); + uint32_t conditions_size = yp_sizet_to_u32(((yp_when_node_t *)node)->conditions.size); yp_buffer_append_u32(buffer, conditions_size); for (uint32_t index = 0; index < conditions_size; index++) { yp_serialize_node(parser, (yp_node_t *) ((yp_when_node_t *)node)->conditions.nodes[index], buffer); @@ -1451,13 +1480,14 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } else { yp_serialize_node(parser, (yp_node_t *)((yp_while_node_t *)node)->statements, buffer); } + yp_buffer_append_u32(buffer, node->flags >> 1); break; } case YP_NODE_X_STRING_NODE: { serialize_location(parser, &((yp_x_string_node_t *)node)->opening_loc, buffer); serialize_location(parser, &((yp_x_string_node_t *)node)->content_loc, buffer); serialize_location(parser, &((yp_x_string_node_t *)node)->closing_loc, buffer); - uint32_t unescaped_length = yp_ulong_to_u32(yp_string_length(&((yp_x_string_node_t *)node)->unescaped)); + uint32_t unescaped_length = yp_sizet_to_u32(yp_string_length(&((yp_x_string_node_t *)node)->unescaped)); yp_buffer_append_u32(buffer, unescaped_length); yp_buffer_append_str(buffer, yp_string_source(&((yp_x_string_node_t *)node)->unescaped), unescaped_length); break; @@ -1486,27 +1516,75 @@ yp_serialize_node(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { } } +void yp_serialize_comment(yp_parser_t *parser, yp_comment_t *comment, yp_buffer_t *buffer) { + // serialize type + yp_buffer_append_u8(buffer, (uint8_t) comment->type); + + // serialize location + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(comment->start - parser->start)); + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(comment->end - comment->start)); +} + +void yp_serialize_comment_list(yp_parser_t *parser, yp_list_t list, yp_buffer_t *buffer) { + yp_buffer_append_u32(buffer, yp_list_size(&list)); + + yp_comment_t *comment; + for (comment = (yp_comment_t *) list.head; comment != NULL; comment = (yp_comment_t *) comment->node.next) { + yp_serialize_comment(parser, comment, buffer); + } +} + +void yp_serialize_diagnostic(yp_parser_t *parser, yp_diagnostic_t *diagnostic, yp_buffer_t *buffer) { + // serialize message + size_t message_length = strlen(diagnostic->message); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(message_length)); + yp_buffer_append_str(buffer, diagnostic->message, message_length); + + // serialize location + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(diagnostic->start - parser->start)); + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(diagnostic->end - diagnostic->start)); +} + +void yp_serialize_diagnostic_list(yp_parser_t *parser, yp_list_t list, yp_buffer_t *buffer) { + yp_buffer_append_u32(buffer, yp_list_size(&list)); + + yp_diagnostic_t *diagnostic; + for (diagnostic = (yp_diagnostic_t *) list.head; diagnostic != NULL; diagnostic = (yp_diagnostic_t *) diagnostic->node.next) { + yp_serialize_diagnostic(parser, diagnostic, buffer); + } +} + +#line 145 "serialize.c.erb" void yp_serialize_content(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) { // First, serialize the encoding of the parser. size_t encoding_length = strlen(parser->encoding.name); - yp_buffer_append_u32(buffer, yp_ulong_to_u32(encoding_length)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(encoding_length)); yp_buffer_append_str(buffer, parser->encoding.name, encoding_length); + // Serialize the comments + yp_serialize_comment_list(parser, parser->comment_list, buffer); + + // Serialize the errors + yp_serialize_diagnostic_list(parser, parser->error_list, buffer); + + // Serialize the warnings + yp_serialize_diagnostic_list(parser, parser->warning_list, buffer); + // Here we're going to leave space for the offset of the constant pool in // the buffer. size_t offset = buffer->length; yp_buffer_append_zeroes(buffer, 4); // Next, encode the length of the constant pool. - yp_buffer_append_u32(buffer, yp_ulong_to_u32(parser->constant_pool.size)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(parser->constant_pool.size)); // Now we're going to serialize the content of the node. yp_serialize_node(parser, node, buffer); // Now we're going to serialize the offset of the constant pool back where // we left space for it. - uint32_t length = yp_ulong_to_u32(buffer->length); + uint32_t length = yp_sizet_to_u32(buffer->length); memcpy(buffer->value + offset, &length, sizeof(uint32_t)); // Now we're going to serialize the constant pool. @@ -1522,11 +1600,50 @@ yp_serialize_content(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer) if (constant->id != 0) { size_t buffer_offset = offset + ((constant->id - 1) * 8); - uint32_t source_offset = yp_long_to_u32(constant->start - parser->start); - uint32_t constant_length = yp_ulong_to_u32(constant->length); + uint32_t source_offset = yp_ptrdifft_to_u32(constant->start - parser->start); + uint32_t constant_length = yp_sizet_to_u32(constant->length); memcpy(buffer->value + buffer_offset, &source_offset, 4); memcpy(buffer->value + buffer_offset + 4, &constant_length, 4); } } } + +static void +serialize_token(void *data, yp_parser_t *parser, yp_token_t *token) { + yp_buffer_t *buffer = (yp_buffer_t *) data; + + yp_buffer_append_u32(buffer, token->type); + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(token->start - parser->start)); + yp_buffer_append_u32(buffer, yp_ptrdifft_to_u32(token->end - token->start)); + yp_buffer_append_u32(buffer, parser->lex_state); +} + +YP_EXPORTED_FUNCTION void +yp_lex_serialize(const char *source, size_t size, const char *filepath, yp_buffer_t *buffer) { + yp_parser_t parser; + yp_parser_init(&parser, source, size, filepath); + + yp_lex_callback_t lex_callback = (yp_lex_callback_t) { + .data = (void *) buffer, + .callback = serialize_token, + }; + + parser.lex_callback = &lex_callback; + yp_node_t *node = yp_parse(&parser); + + // Append 0 to mark end of tokens + yp_buffer_append_u32(buffer, 0); + + // Serialize the comments + yp_serialize_comment_list(&parser, parser.comment_list, buffer); + + // Serialize the errors + yp_serialize_diagnostic_list(&parser, parser.error_list, buffer); + + // Serialize the warnings + yp_serialize_diagnostic_list(&parser, parser.warning_list, buffer); + + yp_node_destroy(&parser, node); + yp_parser_free(&parser); +} diff --git a/yarp/token_type.c b/yarp/token_type.c index 882eecc6a05602..23b884749d8c88 100644 --- a/yarp/token_type.c +++ b/yarp/token_type.c @@ -102,6 +102,12 @@ yp_token_type_to_str(yp_token_type_t token_type) return "EQUAL_TILDE"; case YP_TOKEN_FLOAT: return "FLOAT"; + case YP_TOKEN_FLOAT_IMAGINARY: + return "FLOAT_IMAGINARY"; + case YP_TOKEN_FLOAT_RATIONAL: + return "FLOAT_RATIONAL"; + case YP_TOKEN_FLOAT_RATIONAL_IMAGINARY: + return "FLOAT_RATIONAL_IMAGINARY"; case YP_TOKEN_GLOBAL_VARIABLE: return "GLOBAL_VARIABLE"; case YP_TOKEN_GREATER: @@ -120,12 +126,16 @@ yp_token_type_to_str(yp_token_type_t token_type) return "IDENTIFIER"; case YP_TOKEN_IGNORED_NEWLINE: return "IGNORED_NEWLINE"; - case YP_TOKEN_IMAGINARY_NUMBER: - return "IMAGINARY_NUMBER"; case YP_TOKEN_INSTANCE_VARIABLE: return "INSTANCE_VARIABLE"; case YP_TOKEN_INTEGER: return "INTEGER"; + case YP_TOKEN_INTEGER_IMAGINARY: + return "INTEGER_IMAGINARY"; + case YP_TOKEN_INTEGER_RATIONAL: + return "INTEGER_RATIONAL"; + case YP_TOKEN_INTEGER_RATIONAL_IMAGINARY: + return "INTEGER_RATIONAL_IMAGINARY"; case YP_TOKEN_KEYWORD_ALIAS: return "KEYWORD_ALIAS"; case YP_TOKEN_KEYWORD_AND: @@ -280,8 +290,6 @@ yp_token_type_to_str(yp_token_type_t token_type) return "PLUS_EQUAL"; case YP_TOKEN_QUESTION_MARK: return "QUESTION_MARK"; - case YP_TOKEN_RATIONAL_NUMBER: - return "RATIONAL_NUMBER"; case YP_TOKEN_REGEXP_BEGIN: return "REGEXP_BEGIN"; case YP_TOKEN_REGEXP_END: @@ -310,6 +318,8 @@ yp_token_type_to_str(yp_token_type_t token_type) return "SYMBOL_BEGIN"; case YP_TOKEN_TILDE: return "TILDE"; + case YP_TOKEN_UAMPERSAND: + return "UAMPERSAND"; case YP_TOKEN_UCOLON_COLON: return "UCOLON_COLON"; case YP_TOKEN_UDOT_DOT: diff --git a/yarp/unescape.c b/yarp/unescape.c index 32bfb6e53d02a2..51ab2b3597a1b3 100644 --- a/yarp/unescape.c +++ b/yarp/unescape.c @@ -445,7 +445,7 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len return; } - const char *backslash = yp_memchr(parser, value, '\\', length); + const char *backslash = yp_memchr(value, '\\', length, parser->encoding_changed, &parser->encoding); if (backslash == NULL) { // Here there are no escapes, so we can reference the source directly. @@ -507,7 +507,7 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len } if (end > cursor) { - backslash = yp_memchr(parser, cursor, '\\', (size_t) (end - cursor)); + backslash = yp_memchr(cursor, '\\', (size_t) (end - cursor), parser->encoding_changed, &parser->encoding); } else { backslash = NULL; } diff --git a/yarp/util/yp_buffer.h b/yarp/util/yp_buffer.h index 6a2c0b8f46ee67..722315b96fa0a1 100644 --- a/yarp/util/yp_buffer.h +++ b/yarp/util/yp_buffer.h @@ -12,6 +12,7 @@ // A yp_buffer_t is a simple memory buffer that stores data in a contiguous // block of memory. It is used to store the serialized representation of a // YARP tree. +// NOTE: keep in sync with YARP::LibRubyParser::Buffer in lib/yarp.rb typedef struct { char *value; size_t length; diff --git a/yarp/util/yp_list.c b/yarp/util/yp_list.c index dcb072b7d1437c..9945e72ffe1f76 100644 --- a/yarp/util/yp_list.c +++ b/yarp/util/yp_list.c @@ -12,6 +12,19 @@ yp_list_empty_p(yp_list_t *list) { return list->head == NULL; } +YP_EXPORTED_FUNCTION uint32_t +yp_list_size(yp_list_t *list) { + yp_list_node_t *node = list->head; + uint32_t length = 0; + + while (node != NULL) { + length++; + node = node->next; + } + + return length; +} + // Append a node to the given list. void yp_list_append(yp_list_t *list, yp_list_node_t *node) { diff --git a/yarp/util/yp_list.h b/yarp/util/yp_list.h index 9c672b34ae197b..46f67bd96fdf6a 100644 --- a/yarp/util/yp_list.h +++ b/yarp/util/yp_list.h @@ -55,6 +55,9 @@ YP_EXPORTED_FUNCTION void yp_list_init(yp_list_t *list); // Returns true if the given list is empty. YP_EXPORTED_FUNCTION bool yp_list_empty_p(yp_list_t *list); +// Returns the size of the list in O(n) time. +YP_EXPORTED_FUNCTION uint32_t yp_list_size(yp_list_t *list); + // Append a node to the given list. void yp_list_append(yp_list_t *list, yp_list_node_t *node); diff --git a/yarp/util/yp_memchr.c b/yarp/util/yp_memchr.c index 3f63a2cfabe7eb..c323f37a6658e7 100644 --- a/yarp/util/yp_memchr.c +++ b/yarp/util/yp_memchr.c @@ -6,8 +6,8 @@ // we need to search for a character in a buffer that could be the trailing byte // of a multibyte character. void * -yp_memchr(yp_parser_t *parser, const void *memory, int character, size_t number) { - if (parser->encoding_changed && parser->encoding.multibyte && character >= YP_MEMCHR_TRAILING_BYTE_MINIMUM) { +yp_memchr(const void *memory, int character, size_t number, bool encoding_changed, yp_encoding_t *encoding) { + if (encoding_changed && encoding->multibyte && character >= YP_MEMCHR_TRAILING_BYTE_MINIMUM) { const char *source = (const char *) memory; size_t index = 0; @@ -16,7 +16,7 @@ yp_memchr(yp_parser_t *parser, const void *memory, int character, size_t number) return (void *) (source + index); } - size_t width = parser->encoding.char_width(source + index); + size_t width = encoding->char_width(source + index, (ptrdiff_t) (number - index)); if (width == 0) { return NULL; } diff --git a/yarp/util/yp_memchr.h b/yarp/util/yp_memchr.h index 3dae01eebd3af9..97f4b15a839b02 100644 --- a/yarp/util/yp_memchr.h +++ b/yarp/util/yp_memchr.h @@ -2,13 +2,13 @@ #define YP_MEMCHR_H #include "yarp/defines.h" -#include "yarp/parser.h" +#include "yarp/enc/yp_encoding.h" #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. -void * yp_memchr(yp_parser_t *parser, const void *source, int character, size_t number); +void * yp_memchr(const void *source, int character, size_t number, bool encoding_changed, yp_encoding_t *encoding); #endif diff --git a/yarp/util/yp_string.c b/yarp/util/yp_string.c index ada42e27795a40..bdd001d2b0f4f3 100644 --- a/yarp/util/yp_string.c +++ b/yarp/util/yp_string.c @@ -97,10 +97,8 @@ yp_string_free(yp_string_t *string) { void *memory = (void *) string->source; #if defined(_WIN32) UnmapViewOfFile(memory); - #elif defined(HAVE_MMAP) - munmap(memory, string->length); #else - free(memory); + munmap(memory, string->length); #endif } } @@ -128,7 +126,8 @@ yp_string_mapped_init(yp_string_t *string, const char *filepath) { // the source to a constant empty string and return. if (file_size == 0) { CloseHandle(file); - yp_string_mapped_init_internal(string, "", 0); + char empty_string[] = ""; + yp_string_mapped_init_internal(string, empty_string, 0); return true; } @@ -174,32 +173,26 @@ yp_string_mapped_init(yp_string_t *string, const char *filepath) { if (size == 0) { close(fd); - yp_string_mapped_init_internal(string, "", 0); + char empty_string[] = ""; + yp_string_mapped_init_internal(string, empty_string, 0); return true; } -#ifdef HAVE_MMAP source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (source == MAP_FAILED) { perror("Map failed"); return false; } -#else - source = malloc(size); - if (source == NULL) { - return false; - } - - ssize_t read_size = read(fd, (void *) source, size); - if (read_size < 0 || (size_t)read_size != size) { - perror("Read size is incorrect"); - free((void *) source); - return false; - } -#endif close(fd); yp_string_mapped_init_internal(string, source, size); return true; #endif } + +// Returns the size of the yp_string_t struct. This is necessary to allocate the +// correct amount of memory in the FFI backend. +YP_EXPORTED_FUNCTION size_t +yp_string_sizeof(void) { + return sizeof(yp_string_t); +} diff --git a/yarp/util/yp_string.h b/yarp/util/yp_string.h index 108915ce2dac91..8d5a925232df59 100644 --- a/yarp/util/yp_string.h +++ b/yarp/util/yp_string.h @@ -36,7 +36,7 @@ void yp_string_constant_init(yp_string_t *string, const char *source, size_t len // 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`. -bool yp_string_mapped_init(yp_string_t *string, const char *filepath); +YP_EXPORTED_FUNCTION bool yp_string_mapped_init(yp_string_t *string, const char *filepath); // Returns the memory size associated with the string. size_t yp_string_memsize(const yp_string_t *string); @@ -54,4 +54,8 @@ YP_EXPORTED_FUNCTION const char * yp_string_source(const yp_string_t *string); // Free the associated memory of the given string. YP_EXPORTED_FUNCTION void yp_string_free(yp_string_t *string); +// Returns the size of the yp_string_t struct. This is necessary to allocate the +// correct amount of memory in the FFI backend. +YP_EXPORTED_FUNCTION size_t yp_string_sizeof(void); + #endif // YARP_STRING_H diff --git a/yarp/util/yp_strpbrk.c b/yarp/util/yp_strpbrk.c index 1c32398b559cfd..14a032f3f59708 100644 --- a/yarp/util/yp_strpbrk.c +++ b/yarp/util/yp_strpbrk.c @@ -10,7 +10,7 @@ yp_strpbrk_multi_byte(yp_parser_t *parser, const char *source, const char *chars return source + index; } - size_t width = parser->encoding.char_width(source + index); + size_t width = parser->encoding.char_width(source + index, (ptrdiff_t) (maximum - index)); if (width == 0) { return NULL; } diff --git a/yarp/version.h b/yarp/version.h index d8d9b024de4304..a798d76c7ad6b8 100644 --- a/yarp/version.h +++ b/yarp/version.h @@ -1,5 +1,4 @@ #define YP_VERSION_MAJOR 0 -#define YP_VERSION_MINOR 4 +#define YP_VERSION_MINOR 7 #define YP_VERSION_PATCH 0 - -#define YP_VERSION "0.4.0" +#define YP_VERSION "0.7.0" diff --git a/yarp/yarp.c b/yarp/yarp.c index 59ec35a03d5e9a..e474a46d081753 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -459,7 +459,14 @@ yp_flip_flop(yp_node_t *node) { } case YP_NODE_RANGE_NODE: { yp_range_node_t *cast = (yp_range_node_t *) node; - cast->flags |= YP_RANGE_NODE_FLAGS_FLIP_FLOP; + yp_flip_flop(cast->left); + yp_flip_flop(cast->right); + + // Here we change the range node into a flip flop node. We can do + // this since the nodes are exactly the same except for the type. + assert(sizeof(yp_range_node_t) == sizeof(yp_flip_flop_node_t)); + node->type = YP_NODE_FLIP_FLOP_NODE; + break; } default: @@ -497,18 +504,42 @@ typedef struct { yp_arguments_node_t *arguments; yp_location_t closing_loc; yp_block_node_t *block; + + // This boolean is used to tell if there is an implicit block (i.e., an + // argument passed with an & operator). + bool implicit_block; } yp_arguments_t; -#define YP_EMPTY_ARGUMENTS ((yp_arguments_t) { .opening_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .arguments = NULL, .closing_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .block = NULL }) +#define YP_EMPTY_ARGUMENTS ((yp_arguments_t) { \ + .opening_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, \ + .arguments = NULL, \ + .closing_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, \ + .block = NULL, \ + .implicit_block = false \ +}) + +// Check that the set of arguments parsed for a given node is valid. This means +// checking that we don't have both an implicit and explicit block. +static void +yp_arguments_validate(yp_parser_t *parser, yp_arguments_t *arguments) { + if (arguments->block != NULL && arguments->implicit_block) { + yp_diagnostic_list_append( + &parser->error_list, + arguments->block->base.location.start, + arguments->block->base.location.end, + "both block arg and actual block given" + ); + } +} /******************************************************************************/ /* Node creation functions */ /******************************************************************************/ // Parse out the options for a regular expression. -static inline uint32_t +static inline yp_node_flags_t yp_regular_expression_flags_create(const yp_token_t *closing) { - uint32_t flags = 0; + yp_node_flags_t flags = 0; if (closing->type == YP_TOKEN_REGEXP_END) { for (const char *flag = closing->start + 1; flag < closing->end; flag++) { @@ -729,7 +760,7 @@ yp_array_pattern_node_node_list_create(yp_parser_t *parser, yp_node_list_t *node for (size_t index = 0; index < nodes->size; index++) { yp_node_t *child = nodes->nodes[index]; - if (!found_rest && child->type == YP_NODE_SPLAT_NODE) { + if (!found_rest && YP_NODE_TYPE_P(child, YP_NODE_SPLAT_NODE)) { node->rest = child; found_rest = true; } else if (found_rest) { @@ -983,7 +1014,7 @@ yp_block_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y // Allocate and initialize a new BlockParameterNode node. static yp_block_parameter_node_t * yp_block_parameter_node_create(yp_parser_t *parser, const yp_token_t *name, const yp_token_t *operator) { - assert(operator->type == YP_TOKEN_NOT_PROVIDED || operator->type == YP_TOKEN_AMPERSAND); + assert(operator->type == YP_TOKEN_NOT_PROVIDED || operator->type == YP_TOKEN_UAMPERSAND || operator->type == YP_TOKEN_AMPERSAND); yp_block_parameter_node_t *node = YP_ALLOC_NODE(parser, yp_block_parameter_node_t); *node = (yp_block_parameter_node_t) { @@ -1099,8 +1130,7 @@ yp_call_node_create(yp_parser_t *parser) { .opening_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, .arguments = NULL, .closing_loc = YP_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE, - .block = NULL, - .flags = 0 + .block = NULL }; return node; @@ -1176,7 +1206,7 @@ yp_call_node_call_create(yp_parser_t *parser, yp_node_t *receiver, yp_token_t *o node->block = arguments->block; if (operator->type == YP_TOKEN_AMPERSAND_DOT) { - node->flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION; + node->base.flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION; } yp_string_shared_init(&node->name, message->start, message->end); @@ -1252,7 +1282,7 @@ yp_call_node_shorthand_create(yp_parser_t *parser, yp_node_t *receiver, yp_token node->block = arguments->block; if (operator->type == YP_TOKEN_AMPERSAND_DOT) { - node->flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION; + node->base.flags |= YP_CALL_NODE_FLAGS_SAFE_NAVIGATION; } yp_string_constant_init(&node->name, "call", 4); @@ -1277,7 +1307,7 @@ yp_call_node_unary_create(yp_parser_t *parser, yp_token_t *operator, yp_node_t * // Allocate and initialize a new CallNode node from a call to a method name // without a receiver that could also have been a local variable read. static yp_call_node_t * -yp_call_node_vcall_create(yp_parser_t *parser, yp_token_t *message) { +yp_call_node_variable_call_create(yp_parser_t *parser, yp_token_t *message) { yp_call_node_t *node = yp_call_node_create(parser); node->base.location.start = message->start; @@ -1292,13 +1322,8 @@ yp_call_node_vcall_create(yp_parser_t *parser, yp_token_t *message) { // Returns whether or not this call node is a "vcall" (a call to a method name // without a receiver that could also have been a local variable read). static inline bool -yp_call_node_vcall_p(yp_call_node_t *node) { - return ( - (node->opening_loc.start == NULL) && - (node->arguments == NULL) && - (node->block == NULL) && - (node->receiver == NULL) - ); +yp_call_node_variable_call_p(yp_call_node_t *node) { + return node->base.flags & YP_CALL_NODE_FLAGS_VARIABLE_CALL; } // Allocate and initialize a new CallOperatorAndWriteNode node. @@ -1414,7 +1439,7 @@ yp_case_node_create(yp_parser_t *parser, const yp_token_t *case_keyword, yp_node // Append a new condition to a CaseNode node. static void yp_case_node_condition_append(yp_case_node_t *node, yp_node_t *condition) { - assert(condition->type == YP_NODE_WHEN_NODE || condition->type == YP_NODE_IN_NODE); + assert(YP_NODE_TYPE_P(condition, YP_NODE_WHEN_NODE) || YP_NODE_TYPE_P(condition, YP_NODE_IN_NODE)); yp_node_list_append(&node->conditions, condition); node->base.location.end = condition->location.end; @@ -1459,7 +1484,7 @@ yp_class_node_create(yp_parser_t *parser, yp_constant_id_list_t *locals, const y // Allocate and initialize a new ClassVariableOperatorAndWriteNode node. static yp_class_variable_operator_and_write_node_t * yp_class_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_CLASS_VARIABLE_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE)); assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL); yp_class_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_and_write_node_t); @@ -1504,7 +1529,7 @@ yp_class_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *tar // Allocate and initialize a new ClassVariableOperatorOrWriteNode node. static yp_class_variable_operator_or_write_node_t * yp_class_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_CLASS_VARIABLE_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_CLASS_VARIABLE_READ_NODE)); assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL); yp_class_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_class_variable_operator_or_write_node_t); @@ -1665,7 +1690,7 @@ yp_constant_path_write_node_create(yp_parser_t *parser, yp_constant_path_node_t // Allocate and initialize a new ConstantOperatorAndWriteNode node. static yp_constant_operator_and_write_node_t * yp_constant_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_CONSTANT_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE)); assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL); yp_constant_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_and_write_node_t); @@ -1710,7 +1735,7 @@ yp_constant_operator_write_node_create(yp_parser_t *parser, yp_node_t *target, c // Allocate and initialize a new ConstantOperatorOrWriteNode node. static yp_constant_operator_or_write_node_t * yp_constant_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_CONSTANT_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_CONSTANT_READ_NODE)); assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL); yp_constant_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_constant_operator_or_write_node_t); @@ -2167,7 +2192,7 @@ yp_hash_pattern_node_node_list_create(yp_parser_t *parser, yp_node_list_t *assoc // Allocate and initialize a new GlobalVariableOperatorAndWriteNode node. static yp_global_variable_operator_and_write_node_t * yp_global_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_GLOBAL_VARIABLE_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE)); assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL); yp_global_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_and_write_node_t); @@ -2212,7 +2237,7 @@ yp_global_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *ta // Allocate and initialize a new GlobalVariableOperatorOrWriteNode node. static yp_global_variable_operator_or_write_node_t * yp_global_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_GLOBAL_VARIABLE_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_GLOBAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_NUMBERED_REFERENCE_READ_NODE)); assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL); yp_global_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_global_variable_operator_or_write_node_t); @@ -2525,7 +2550,7 @@ yp_in_node_create(yp_parser_t *parser, yp_node_t *pattern, yp_statements_node_t // Allocate and initialize a new InstanceVariableOperatorAndWriteNode node. static yp_instance_variable_operator_and_write_node_t * yp_instance_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_INSTANCE_VARIABLE_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE)); assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL); yp_instance_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_and_write_node_t); @@ -2570,7 +2595,7 @@ yp_instance_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t * // Allocate and initialize a new InstanceVariableOperatorOrWriteNode node. static yp_instance_variable_operator_or_write_node_t * yp_instance_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value) { - assert(target->type == YP_NODE_INSTANCE_VARIABLE_READ_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_INSTANCE_VARIABLE_READ_NODE)); assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL); yp_instance_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_instance_variable_operator_or_write_node_t); @@ -2638,7 +2663,6 @@ yp_interpolated_regular_expression_node_create(yp_parser_t *parser, const yp_tok }, .opening_loc = YP_LOCATION_TOKEN_VALUE(opening), .closing_loc = YP_LOCATION_TOKEN_VALUE(opening), - .flags = 0, .parts = YP_EMPTY_NODE_LIST }; @@ -2655,7 +2679,7 @@ static inline void yp_interpolated_regular_expression_node_closing_set(yp_interpolated_regular_expression_node_t *node, const yp_token_t *closing) { node->closing_loc = YP_LOCATION_TOKEN_VALUE(closing); node->base.location.end = closing->end; - node->flags = yp_regular_expression_flags_create(closing); + node->base.flags |= yp_regular_expression_flags_create(closing); } // Allocate and initialize a new InterpolatedStringNode node. @@ -2863,7 +2887,7 @@ yp_lambda_node_create( // Allocate and initialize a new LocalVariableOperatorAndWriteNode node. static yp_local_variable_operator_and_write_node_t * yp_local_variable_operator_and_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) { - assert(target->type == YP_NODE_LOCAL_VARIABLE_READ_NODE || target->type == YP_NODE_CALL_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE)); assert(operator->type == YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL); yp_local_variable_operator_and_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_and_write_node_t); @@ -2910,7 +2934,7 @@ yp_local_variable_operator_write_node_create(yp_parser_t *parser, yp_node_t *tar // Allocate and initialize a new LocalVariableOperatorOrWriteNode node. static yp_local_variable_operator_or_write_node_t * yp_local_variable_operator_or_write_node_create(yp_parser_t *parser, yp_node_t *target, const yp_token_t *operator, yp_node_t *value, yp_constant_id_t constant_id) { - assert(target->type == YP_NODE_LOCAL_VARIABLE_READ_NODE || target->type == YP_NODE_CALL_NODE); + assert(YP_NODE_TYPE_P(target, YP_NODE_LOCAL_VARIABLE_READ_NODE) || YP_NODE_TYPE_P(target, YP_NODE_CALL_NODE)); assert(operator->type == YP_TOKEN_PIPE_PIPE_EQUAL); yp_local_variable_operator_or_write_node_t *node = YP_ALLOC_NODE(parser, yp_local_variable_operator_or_write_node_t); @@ -3439,14 +3463,13 @@ yp_range_node_create(yp_parser_t *parser, yp_node_t *left, const yp_token_t *ope }, .left = left, .right = right, - .operator_loc = YP_LOCATION_TOKEN_VALUE(operator), - .flags = 0, + .operator_loc = YP_LOCATION_TOKEN_VALUE(operator) }; switch (operator->type) { case YP_TOKEN_DOT_DOT_DOT: case YP_TOKEN_UDOT_DOT_DOT: - node->flags |= YP_RANGE_NODE_FLAGS_EXCLUDE_END; + node->base.flags |= YP_RANGE_FLAGS_EXCLUDE_END; break; default: break; @@ -3473,6 +3496,7 @@ yp_regular_expression_node_create(yp_parser_t *parser, const yp_token_t *opening *node = (yp_regular_expression_node_t) { { .type = YP_NODE_REGULAR_EXPRESSION_NODE, + .flags = yp_regular_expression_flags_create(closing), .location = { .start = opening->start, .end = closing->end @@ -3481,7 +3505,7 @@ yp_regular_expression_node_create(yp_parser_t *parser, const yp_token_t *opening .opening_loc = YP_LOCATION_TOKEN_VALUE(opening), .content_loc = YP_LOCATION_TOKEN_VALUE(content), .closing_loc = YP_LOCATION_TOKEN_VALUE(closing), - .flags = yp_regular_expression_flags_create(closing) + .unescaped = YP_EMPTY_STRING }; return node; @@ -3794,7 +3818,7 @@ yp_statements_node_body_append(yp_statements_node_t *node, yp_node_t *statement) node->base.location.end = statement->location.end; // Every statement gets marked as a place where a newline can occur. - statement->flags = YP_NODE_FLAG_NEWLINE; + statement->flags |= YP_NODE_FLAG_NEWLINE; } // Allocate a new StringConcatNode node. @@ -3938,7 +3962,7 @@ static bool yp_symbol_node_label_p(yp_node_t *node) { const char *end = NULL; - switch (node->type) { + switch (YP_NODE_TYPE(node)) { case YP_NODE_SYMBOL_NODE: end = ((yp_symbol_node_t *) node)->closing_loc.end; break; @@ -3952,6 +3976,33 @@ yp_symbol_node_label_p(yp_node_t *node) { return (end != NULL) && (end[-1] == ':'); } +// Convert the given StringNode node to a SymbolNode node. +static yp_symbol_node_t * +yp_string_node_to_symbol_node(yp_parser_t *parser, yp_string_node_t *node) { + yp_symbol_node_t *new_node = YP_ALLOC_NODE(parser, yp_symbol_node_t); + + *new_node = (yp_symbol_node_t) { + { + .type = YP_NODE_SYMBOL_NODE, + .location = { + .start = node->base.location.start - 2, + .end = node->base.location.end + 1 + } + }, + .opening_loc = node->opening_loc, + .value_loc = node->content_loc, + .closing_loc = node->closing_loc, + .unescaped = node->unescaped + }; + + // We are explicitly _not_ using yp_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. + free(node); + + return new_node; +} + // Convert the given SymbolNode node to a StringNode node. static yp_string_node_t * yp_symbol_node_to_string_node(yp_parser_t *parser, yp_symbol_node_t *node) { @@ -4079,7 +4130,7 @@ yp_unless_node_end_keyword_loc_set(yp_unless_node_t *node, const yp_token_t *end // Allocate a new UntilNode node. static yp_until_node_t * -yp_until_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements) { +yp_until_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements, yp_node_flags_t flags) { yp_until_node_t *node = YP_ALLOC_NODE(parser, yp_until_node_t); bool has_statements = (statements != NULL) && (statements->body.size != 0); @@ -4100,6 +4151,7 @@ yp_until_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t * *node = (yp_until_node_t) { { .type = YP_NODE_UNTIL_NODE, + .flags = flags, .location = { .start = start, .end = end, @@ -4153,7 +4205,7 @@ yp_when_node_statements_set(yp_when_node_t *node, yp_statements_node_t *statemen // Allocate a new WhileNode node. static yp_while_node_t * -yp_while_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements) { +yp_while_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t *predicate, yp_statements_node_t *statements, yp_node_flags_t flags) { yp_while_node_t *node = YP_ALLOC_NODE(parser, yp_while_node_t); const char *start = NULL; @@ -4174,6 +4226,7 @@ yp_while_node_create(yp_parser_t *parser, const yp_token_t *keyword, yp_node_t * *node = (yp_while_node_t) { { .type = YP_NODE_WHILE_NODE, + .flags = flags, .location = { .start = start, .end = end, @@ -4338,12 +4391,13 @@ static inline size_t char_is_identifier_start(yp_parser_t *parser, const char *c) { const unsigned char uc = (unsigned char) *c; - return ( - (parser->encoding_changed - ? parser->encoding.alpha_char(c) - : (uc < 0x80 ? (yp_encoding_unicode_table[uc] & YP_ENCODING_ALPHABETIC_BIT ? 1 : 0) : yp_encoding_utf_8_alpha_char(c)) - ) || (uc == '_') || (uc >= 0x80) - ); + if (parser->encoding_changed) { + return parser->encoding.alpha_char(c, parser->end - c) || (uc == '_') || (uc >= 0x80); + } else if (uc < 0x80) { + return (yp_encoding_unicode_table[uc] & YP_ENCODING_ALPHABETIC_BIT ? 1 : 0) || (uc == '_'); + } else { + return (size_t) (yp_encoding_utf_8_alpha_char(c, parser->end - c) || 1u); + } } // Like the above, this function is also used extremely frequently to lex all of @@ -4353,12 +4407,13 @@ static inline size_t char_is_identifier(yp_parser_t *parser, const char *c) { const unsigned char uc = (unsigned char) *c; - return ( - (parser->encoding_changed - ? parser->encoding.alnum_char(c) - : (uc < 0x80 ? (yp_encoding_unicode_table[uc] & YP_ENCODING_ALPHANUMERIC_BIT ? 1 : 0) : yp_encoding_utf_8_alnum_char(c)) - ) || (uc == '_') || (uc >= 0x80) - ); + if (parser->encoding_changed) { + return parser->encoding.alnum_char(c, parser->end - c) || (uc == '_') || (uc >= 0x80); + } else if (uc < 0x80) { + return (yp_encoding_unicode_table[uc] & YP_ENCODING_ALPHANUMERIC_BIT ? 1 : 0) || (uc == '_'); + } else { + return (size_t) (yp_encoding_utf_8_alnum_char(c, parser->end - c) || 1u); + } } // Here we're defining a perfect hash for the characters that are allowed in @@ -4506,7 +4561,7 @@ parser_lex_encoding_comment_start(yp_parser_t *parser, const char *cursor, ptrdi if (key_length > length) return NULL; const char *cursor_limit = cursor + length - key_length + 1; - while ((cursor = yp_memchr(parser, cursor, 'c', (size_t) (cursor_limit - cursor))) != NULL) { + while ((cursor = yp_memchr(cursor, 'c', (size_t) (cursor_limit - cursor), parser->encoding_changed, &parser->encoding)) != NULL) { if ( (strncmp(cursor, "coding", key_length - 1) == 0) && (cursor[key_length - 1] == ':' || cursor[key_length - 1] == '=') @@ -4615,6 +4670,7 @@ parser_lex_encoding_comment(yp_parser_t *parser) { ENCODING("cp1252", yp_encoding_windows_1252); ENCODING("cp932", yp_encoding_windows_31j); ENCODING("sjis", yp_encoding_windows_31j); + ENCODING("utf8-mac", yp_encoding_utf8_mac); #undef ENCODING @@ -5164,7 +5220,7 @@ lex_identifier(yp_parser_t *parser, bool previous_command_start) { } } - return parser->encoding.isupper_char(parser->current.start) ? YP_TOKEN_CONSTANT : YP_TOKEN_IDENTIFIER; + return parser->encoding.isupper_char(parser->current.start, parser->end - parser->current.start) ? YP_TOKEN_CONSTANT : YP_TOKEN_IDENTIFIER; } // Returns true if the current token that the parser is considering is at the @@ -5358,15 +5414,16 @@ lex_question_mark(yp_parser_t *parser) { parser->current.end += yp_unescape_calculate_difference(parser->current.start + 1, parser->end, YP_UNESCAPE_ALL, true, &parser->error_list); return YP_TOKEN_CHARACTER_LITERAL; } else { - size_t encoding_width = parser->encoding.char_width(parser->current.end); + size_t encoding_width = parser->encoding.char_width(parser->current.end, parser->end - parser->current.end); - // We only want to return a character literal if there's exactly one - // alphanumeric character right after the `?` + // Ternary operators can have a ? immediately followed by an identifier which starts with + // an underscore. We check for this case if ( - !parser->encoding.alnum_char(parser->current.end) || + !(parser->encoding.alnum_char(parser->current.end, parser->end - parser->current.end) || + *parser->current.end == '_') || ( (parser->current.end + encoding_width >= parser->end) || - !parser->encoding.alnum_char(parser->current.end + encoding_width) + !char_is_identifier(parser, parser->current.end + encoding_width) ) ) { lex_state_set(parser, YP_LEX_STATE_END); @@ -6159,7 +6216,7 @@ parser_lex(yp_parser_t *parser) { LEX(lex_question_mark(parser)); // & && &&= &= - case '&': + case '&': { if (match(parser, '&')) { lex_state_set(parser, YP_LEX_STATE_BEG); @@ -6180,13 +6237,19 @@ parser_lex(yp_parser_t *parser) { LEX(YP_TOKEN_AMPERSAND_DOT); } + yp_token_type_t type = YP_TOKEN_AMPERSAND; + if (lex_state_spcarg_p(parser, space_seen) || lex_state_beg_p(parser)) { + type = YP_TOKEN_UAMPERSAND; + } + if (lex_state_operator_p(parser)) { lex_state_set(parser, YP_LEX_STATE_ARG); } else { lex_state_set(parser, YP_LEX_STATE_BEG); } - LEX(YP_TOKEN_AMPERSAND); + LEX(type); + } // | || ||= |= case '|': @@ -6442,7 +6505,7 @@ parser_lex(yp_parser_t *parser) { (lex_state_p(parser, YP_LEX_STATE_FITEM) && (*parser->current.end == 's')) || lex_state_spcarg_p(parser, space_seen) ) { - if (!parser->encoding.alnum_char(parser->current.end)) { + if (!parser->encoding.alnum_char(parser->current.end, parser->end - parser->current.end)) { lex_mode_push_string(parser, true, false, lex_mode_incrementor(*parser->current.end), lex_mode_terminator(*parser->current.end)); if (*parser->current.end == '\r') { @@ -7094,14 +7157,14 @@ parser_lex(yp_parser_t *parser) { breakpoint = yp_strpbrk(parser, breakpoint + 1, breakpoints, parser->end - (breakpoint + 1)); break; case '\n': { - yp_newline_list_append(&parser->newline_list, breakpoint); - if (parser->heredoc_end != NULL && (parser->heredoc_end > breakpoint)) { parser_flush_heredoc_end(parser); parser->current.end = breakpoint + 1; LEX(YP_TOKEN_STRING_CONTENT); } + yp_newline_list_append(&parser->newline_list, breakpoint); + const char *start = breakpoint + 1; if (parser->lex_modes.current->as.heredoc.indent != YP_HEREDOC_INDENT_NONE) { start += yp_strspn_inline_whitespace(start, parser->end - start); @@ -7552,6 +7615,10 @@ token_begins_expression_p(yp_token_type_t type) { // and let it be handled by the default case below. assert(yp_binding_powers[type].left == YP_BINDING_POWER_UNSET); return false; + case YP_TOKEN_UAMPERSAND: + // This is a special case because this unary operator cannot appear + // as a general operator, it only appears in certain circumstances. + return false; case YP_TOKEN_UCOLON_COLON: case YP_TOKEN_UMINUS: case YP_TOKEN_UMINUS_NUM: @@ -7586,7 +7653,7 @@ parse_starred_expression(yp_parser_t *parser, yp_binding_power_t binding_power, // Convert the given node into a valid target node. static yp_node_t * parse_target(yp_parser_t *parser, yp_node_t *target, yp_token_t *operator, yp_node_t *value) { - switch (target->type) { + switch (YP_NODE_TYPE(target)) { case YP_NODE_MISSING_NODE: return target; case YP_NODE_CLASS_VARIABLE_READ_NODE: { @@ -7711,7 +7778,7 @@ parse_target(yp_parser_t *parser, yp_node_t *target, yp_token_t *operator, yp_no char *name = calloc(length + 2, sizeof(char)); if (name == NULL) return NULL; - yp_snprintf(name, length + 2, "%.*s=", (int) length, yp_string_source(&call->name)); + snprintf(name, length + 2, "%.*s=", (int) length, yp_string_source(&call->name)); // Now switch the name to the new string. yp_string_free(&call->name); @@ -7830,7 +7897,7 @@ parse_targets(yp_parser_t *parser, yp_node_t *first_target, yp_binding_power_t b expect(parser, YP_TOKEN_PARENTHESIS_RIGHT, "Expected an ')' after multi-assignment."); yp_token_t rparen = parser->previous; - if (child_target->type == YP_NODE_MULTI_WRITE_NODE && first_target == NULL && result->targets.size == 0) { + if (YP_NODE_TYPE_P(child_target, YP_NODE_MULTI_WRITE_NODE) && first_target == NULL && result->targets.size == 0) { yp_node_destroy(parser, (yp_node_t *) result); result = (yp_multi_write_node_t *) child_target; result->base.location.start = lparen.start; @@ -7840,7 +7907,7 @@ parse_targets(yp_parser_t *parser, yp_node_t *first_target, yp_binding_power_t b } else { yp_multi_write_node_t *target; - if (child_target->type == YP_NODE_MULTI_WRITE_NODE) { + if (YP_NODE_TYPE_P(child_target, YP_NODE_MULTI_WRITE_NODE)) { target = (yp_multi_write_node_t *) child_target; target->lparen_loc = (yp_location_t) { .start = lparen.start, .end = lparen.end }; target->rparen_loc = (yp_location_t) { .start = rparen.start, .end = rparen.end }; @@ -7946,7 +8013,7 @@ parse_statements(yp_parser_t *parser, yp_context_t context) { // were unable to parse an expression, then we will skip past this token and // continue parsing the statements list. Otherwise we'll add an error and // continue parsing the statements list. - if (node->type == YP_NODE_MISSING_NODE) { + if (YP_NODE_TYPE_P(node, YP_NODE_MISSING_NODE)) { parser_lex(parser); while (accept_any(parser, 2, YP_TOKEN_NEWLINE, YP_TOKEN_SEMICOLON)); @@ -7963,7 +8030,8 @@ parse_statements(yp_parser_t *parser, yp_context_t context) { // Parse all of the elements of a hash. static void parse_assocs(yp_parser_t *parser, yp_node_t *node) { - assert((node->type == YP_NODE_HASH_NODE) || (node->type == YP_NODE_KEYWORD_HASH_NODE)); + assert(YP_NODE_TYPE_P(node, YP_NODE_HASH_NODE) || YP_NODE_TYPE_P(node, YP_NODE_KEYWORD_HASH_NODE)); + while (true) { yp_node_t *element; @@ -8013,7 +8081,7 @@ parse_assocs(yp_parser_t *parser, yp_node_t *node) { } } - if (node->type == YP_NODE_HASH_NODE) { + if (YP_NODE_TYPE_P(node, YP_NODE_HASH_NODE)) { yp_hash_node_elements_append((yp_hash_node_t *) node, element); } else { yp_keyword_hash_node_elements_append((yp_keyword_hash_node_t *) node, element); @@ -8037,7 +8105,7 @@ parse_assocs(yp_parser_t *parser, yp_node_t *node) { // Parse a list of arguments. static void -parse_arguments(yp_parser_t *parser, yp_arguments_node_t *arguments, bool accepts_forwarding, yp_token_type_t terminator) { +parse_arguments(yp_parser_t *parser, yp_arguments_t *arguments, bool accepts_forwarding, yp_token_type_t terminator) { yp_binding_power_t binding_power = yp_binding_powers[parser->current.type].left; // First we need to check if the next token is one that could be the start of @@ -8077,7 +8145,7 @@ parse_arguments(yp_parser_t *parser, yp_arguments_node_t *arguments, bool accept parsed_bare_hash = true; break; } - case YP_TOKEN_AMPERSAND: { + case YP_TOKEN_UAMPERSAND: { parser_lex(parser); yp_token_t operator = parser->previous; yp_node_t *expression = NULL; @@ -8090,6 +8158,7 @@ parse_arguments(yp_parser_t *parser, yp_arguments_node_t *arguments, bool accept argument = (yp_node_t *)yp_block_argument_node_create(parser, &operator, expression); parsed_block_argument = true; + arguments->implicit_block = true; break; } case YP_TOKEN_USTAR: { @@ -8176,10 +8245,10 @@ parse_arguments(yp_parser_t *parser, yp_arguments_node_t *arguments, bool accept } } - yp_arguments_node_arguments_append(arguments, argument); + yp_arguments_node_arguments_append(arguments->arguments, argument); // If parsing the argument failed, we need to stop parsing arguments. - if (argument->type == YP_NODE_MISSING_NODE || parser->recovering) break; + if (YP_NODE_TYPE_P(argument, YP_NODE_MISSING_NODE) || parser->recovering) break; // If the terminator of these arguments is not EOF, then we have a specific // token we're looking for. In that case we can accept a newline here @@ -8283,6 +8352,7 @@ typedef enum { // This matches parameters tokens with parameters state. static yp_parameters_order_t parameters_ordering[YP_TOKEN_MAXIMUM] = { [0] = YP_PARAMETERS_NO_CHANGE, + [YP_TOKEN_UAMPERSAND] = YP_PARAMETERS_ORDER_NOTHING_AFTER, [YP_TOKEN_AMPERSAND] = YP_PARAMETERS_ORDER_NOTHING_AFTER, [YP_TOKEN_UDOT_DOT_DOT] = YP_PARAMETERS_ORDER_NOTHING_AFTER, [YP_TOKEN_IDENTIFIER] = YP_PARAMETERS_ORDER_NAMED, @@ -8353,6 +8423,7 @@ parse_parameters( } break; } + case YP_TOKEN_UAMPERSAND: case YP_TOKEN_AMPERSAND: { update_parameter_state(parser, &parser->current, &order); parser_lex(parser); @@ -8839,7 +8910,7 @@ parse_block(yp_parser_t *parser) { } if (match_any_type_p(parser, 2, YP_TOKEN_KEYWORD_RESCUE, YP_TOKEN_KEYWORD_ENSURE)) { - assert(statements == NULL || statements->type == YP_NODE_STATEMENTS_NODE); + assert(statements == NULL || YP_NODE_TYPE_P(statements, YP_NODE_STATEMENTS_NODE)); statements = (yp_node_t *) parse_rescues_as_begin(parser, (yp_statements_node_t *) statements); } } @@ -8854,10 +8925,14 @@ parse_block(yp_parser_t *parser) { } // Parse a list of arguments and their surrounding parentheses if they are -// present. -static void +// present. It returns true if it found any pieces of arguments (parentheses, +// arguments, or blocks). +static bool parse_arguments_list(yp_parser_t *parser, yp_arguments_t *arguments, bool accepts_block) { + bool found = false; + if (accept(parser, YP_TOKEN_PARENTHESIS_LEFT)) { + found |= true; arguments->opening_loc = ((yp_location_t) { .start = parser->previous.start, .end = parser->previous.end }); if (accept(parser, YP_TOKEN_PARENTHESIS_RIGHT)) { @@ -8866,20 +8941,21 @@ parse_arguments_list(yp_parser_t *parser, yp_arguments_t *arguments, bool accept arguments->arguments = yp_arguments_node_create(parser); yp_accepts_block_stack_push(parser, true); - parse_arguments(parser, arguments->arguments, true, YP_TOKEN_PARENTHESIS_RIGHT); + parse_arguments(parser, arguments, true, YP_TOKEN_PARENTHESIS_RIGHT); expect(parser, YP_TOKEN_PARENTHESIS_RIGHT, "Expected a ')' to close the argument list."); yp_accepts_block_stack_pop(parser); arguments->closing_loc = ((yp_location_t) { .start = parser->previous.start, .end = parser->previous.end }); } - } else if ((token_begins_expression_p(parser->current.type) || match_any_type_p(parser, 2, YP_TOKEN_USTAR, YP_TOKEN_USTAR_STAR)) && !match_type_p(parser, YP_TOKEN_BRACE_LEFT)) { + } else if ((token_begins_expression_p(parser->current.type) || match_any_type_p(parser, 3, YP_TOKEN_USTAR, YP_TOKEN_USTAR_STAR, YP_TOKEN_UAMPERSAND)) && !match_type_p(parser, YP_TOKEN_BRACE_LEFT)) { + found |= true; yp_accepts_block_stack_push(parser, false); // 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. arguments->arguments = yp_arguments_node_create(parser); - parse_arguments(parser, arguments->arguments, true, YP_TOKEN_EOF); + parse_arguments(parser, arguments, true, YP_TOKEN_EOF); yp_accepts_block_stack_pop(parser); } @@ -8889,11 +8965,16 @@ parse_arguments_list(yp_parser_t *parser, yp_arguments_t *arguments, bool accept // the arguments. if (accepts_block) { if (accept(parser, YP_TOKEN_BRACE_LEFT)) { + found |= true; arguments->block = parse_block(parser); } else if (yp_accepts_block_stack_p(parser) && accept(parser, YP_TOKEN_KEYWORD_DO)) { + found |= true; arguments->block = parse_block(parser); } } + + yp_arguments_validate(parser, arguments); + return found; } static inline yp_node_t * @@ -8974,12 +9055,13 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) { switch (context) { case YP_CONTEXT_IF: ((yp_if_node_t *) current)->consequent = (yp_node_t *) else_node; - // Recurse down if nodes setting the appropriate end location in all cases - yp_node_t * recursing_node = parent; + // Recurse down if nodes setting the appropriate end location in + // all cases. + yp_node_t *recursing_node = parent; bool recursing = true; while (recursing) { - switch (recursing_node->type) { + switch (YP_NODE_TYPE(recursing_node)) { case YP_NODE_IF_NODE: yp_if_node_end_keyword_loc_set((yp_if_node_t *) recursing_node, &parser->previous); recursing_node = ((yp_if_node_t *) recursing_node)->consequent; @@ -9045,8 +9127,8 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) { case YP_TOKEN_EQUAL_TILDE: case YP_TOKEN_GREATER_EQUAL: case YP_TOKEN_GREATER_GREATER: case YP_TOKEN_GREATER: \ case YP_TOKEN_LESS_EQUAL_GREATER: case YP_TOKEN_LESS_EQUAL: case YP_TOKEN_LESS_LESS: case YP_TOKEN_LESS: \ case YP_TOKEN_MINUS: case YP_TOKEN_PERCENT: case YP_TOKEN_PIPE: case YP_TOKEN_PLUS: case YP_TOKEN_SLASH: \ - case YP_TOKEN_STAR_STAR: case YP_TOKEN_STAR: case YP_TOKEN_TILDE: case YP_TOKEN_UMINUS: case YP_TOKEN_UMINUS_NUM: \ - case YP_TOKEN_UPLUS: case YP_TOKEN_USTAR: case YP_TOKEN_USTAR_STAR + case YP_TOKEN_STAR_STAR: case YP_TOKEN_STAR: case YP_TOKEN_TILDE: case YP_TOKEN_UAMPERSAND: case YP_TOKEN_UMINUS: \ + case YP_TOKEN_UMINUS_NUM: case YP_TOKEN_UPLUS: case YP_TOKEN_USTAR: case YP_TOKEN_USTAR_STAR // This macro allows you to define a case statement for all of the token types // that represent the beginning of nodes that are "primitives" in a pattern @@ -9063,9 +9145,10 @@ parse_conditional(yp_parser_t *parser, yp_context_t context) { // This macro allows you to define a case statement for all of the token types // that could begin a parameter. -#define YP_CASE_PARAMETER YP_TOKEN_AMPERSAND: case YP_TOKEN_UDOT_DOT_DOT: case YP_TOKEN_IDENTIFIER: \ - case YP_TOKEN_LABEL: case YP_TOKEN_USTAR: case YP_TOKEN_STAR: case YP_TOKEN_STAR_STAR: case YP_TOKEN_USTAR_STAR: case YP_TOKEN_CONSTANT: \ - case YP_TOKEN_INSTANCE_VARIABLE: case YP_TOKEN_GLOBAL_VARIABLE: case YP_TOKEN_CLASS_VARIABLE +#define YP_CASE_PARAMETER YP_TOKEN_UAMPERSAND: case YP_TOKEN_AMPERSAND: case YP_TOKEN_UDOT_DOT_DOT: \ + case YP_TOKEN_IDENTIFIER: case YP_TOKEN_LABEL: case YP_TOKEN_USTAR: case YP_TOKEN_STAR: case YP_TOKEN_STAR_STAR: \ + case YP_TOKEN_USTAR_STAR: case YP_TOKEN_CONSTANT: case YP_TOKEN_INSTANCE_VARIABLE: case YP_TOKEN_GLOBAL_VARIABLE: \ + case YP_TOKEN_CLASS_VARIABLE // This macro allows you to define a case statement for all of the nodes that // can be transformed into write targets. @@ -9198,7 +9281,7 @@ parse_string_part(yp_parser_t *parser) { static yp_node_t * parse_symbol(yp_parser_t *parser, yp_lex_mode_t *lex_mode, yp_lex_state_t next_state) { bool lex_string = lex_mode->mode == YP_LEX_STRING; - bool lex_interpolation = lex_string && lex_mode->as.string.interpolation; + bool can_be_interpolated = lex_string && lex_mode->as.string.interpolation; yp_token_t opening = parser->previous; if (!lex_string) { @@ -9234,26 +9317,37 @@ parse_symbol(yp_parser_t *parser, yp_lex_mode_t *lex_mode, yp_lex_state_t next_s return (yp_node_t *) yp_symbol_node_create_and_unescape(parser, &opening, &symbol, &closing, YP_UNESCAPE_ALL); } - // If we weren't in a string in the previous check then we have to be now. - assert(lex_string); - - if (lex_interpolation) { - yp_interpolated_symbol_node_t *interpolated = yp_interpolated_symbol_node_create(parser, &opening, NULL, &opening); + if (can_be_interpolated) { + // Create a node_list first. We'll use this to check if it should be an InterpolatedSymbolNode + // or a SymbolNode + yp_node_list_t node_list = YP_EMPTY_NODE_LIST; while (!match_any_type_p(parser, 2, YP_TOKEN_STRING_END, YP_TOKEN_EOF)) { yp_node_t *part = parse_string_part(parser); if (part != NULL) { - yp_interpolated_symbol_node_append(interpolated, part); + yp_node_list_append(&node_list, part); } } + yp_node_t *res; + // If the only element on the node_list is a StringNode, we know this is a SymbolNode + // and not an InterpolatedSymbolNode + if (node_list.size == 1 && YP_NODE_TYPE_P(node_list.nodes[0], YP_NODE_STRING_NODE)) { + res = (yp_node_t *)yp_string_node_to_symbol_node(parser, (yp_string_node_t *)node_list.nodes[0]); + free(node_list.nodes); + } + else { + yp_interpolated_symbol_node_t *interpolated = yp_interpolated_symbol_node_create(parser, &opening, &node_list, &opening); + yp_interpolated_symbol_node_closing_set(interpolated, &parser->current); + res = (yp_node_t *) interpolated; + } + if (next_state != YP_LEX_STATE_NONE) { lex_state_set(parser, next_state); } expect(parser, YP_TOKEN_STRING_END, "Expected a closing delimiter for an interpolated symbol."); - yp_interpolated_symbol_node_closing_set(interpolated, &parser->previous); - return (yp_node_t *) interpolated; + return res; } yp_token_t content; @@ -9343,19 +9437,22 @@ parse_alias_argument(yp_parser_t *parser, bool first) { // Parse an identifier into either a local variable read or a call. static yp_node_t * -parse_vcall(yp_parser_t *parser) { - int depth; +parse_variable_call(yp_parser_t *parser) { + yp_node_flags_t flags = 0; - if ( - (parser->current.type != YP_TOKEN_PARENTHESIS_LEFT) && - (parser->previous.end[-1] != '!') && - (parser->previous.end[-1] != '?') && - (depth = yp_parser_local_depth(parser, &parser->previous)) != -1 - ) { - return (yp_node_t *) yp_local_variable_read_node_create(parser, &parser->previous, (uint32_t) depth); + if (!match_type_p(parser, YP_TOKEN_PARENTHESIS_LEFT) && (parser->previous.end[-1] != '!') && (parser->previous.end[-1] != '?')) { + int depth; + if ((depth = yp_parser_local_depth(parser, &parser->previous)) != -1) { + return (yp_node_t *) yp_local_variable_read_node_create(parser, &parser->previous, (uint32_t) depth); + } + + flags |= YP_CALL_NODE_FLAGS_VARIABLE_CALL; } - return (yp_node_t *) yp_call_node_vcall_create(parser, &parser->previous); + yp_call_node_t *node = yp_call_node_variable_call_create(parser, &parser->previous); + node->base.flags |= flags; + + return (yp_node_t *) node; } static inline yp_token_t @@ -9383,13 +9480,13 @@ parse_heredoc_common_whitespace(yp_parser_t *parser, yp_node_list_t *nodes) { for (size_t index = 0; index < nodes->size; index++) { yp_node_t *node = nodes->nodes[index]; - if (node->type != YP_NODE_STRING_NODE) continue; + if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) continue; yp_location_t *content_loc = &((yp_string_node_t *) node)->content_loc; // If the previous node wasn't a string node, we don't want to trim // whitespace. This could happen after an interpolated expression or // variable. - if (index == 0 || nodes->nodes[index - 1]->type == YP_NODE_STRING_NODE) { + if (index == 0 || YP_NODE_TYPE_P(nodes->nodes[index - 1], YP_NODE_STRING_NODE)) { int cur_whitespace; const char *cur_char = content_loc->start; @@ -9451,7 +9548,7 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu // Iterate over all nodes, and trim whitespace accordingly. for (size_t index = 0; index < nodes->size; index++) { yp_node_t *node = nodes->nodes[index]; - if (node->type != YP_NODE_STRING_NODE) continue; + if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) continue; // Get a reference to the string struct that is being held by the string // node. This is the value we're going to actual manipulate. @@ -9471,7 +9568,7 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu // whitespace, so we'll maintain a pointer to the current position in the // string that we're writing to. char *dest_cursor = source_start; - bool dedent_next = (index == 0) || (nodes->nodes[index - 1]->type == YP_NODE_STRING_NODE); + bool dedent_next = (index == 0) || YP_NODE_TYPE_P(nodes->nodes[index - 1], YP_NODE_STRING_NODE); while (source_cursor < source_end) { // If we need to dedent the next element within the heredoc or the next @@ -9580,7 +9677,7 @@ parse_pattern_constant_path(yp_parser_t *parser, yp_node_t *node) { // or hash pattern. If it is, then we'll attach our constant path to it if // it doesn't already have a constant. If it's not one of those node types // or it does have a constant, then we'll create an array pattern. - switch (inner->type) { + switch (YP_NODE_TYPE(inner)) { case YP_NODE_ARRAY_PATTERN_NODE: { yp_array_pattern_node_t *pattern_node = (yp_array_pattern_node_t *) inner; @@ -9685,7 +9782,7 @@ parse_pattern_keyword_rest(yp_parser_t *parser) { // Parse a hash pattern. static yp_hash_pattern_node_t * parse_pattern_hash(yp_parser_t *parser, yp_node_t *first_assoc) { - if (first_assoc->type == YP_NODE_ASSOC_NODE) { + if (YP_NODE_TYPE_P(first_assoc, YP_NODE_ASSOC_NODE)) { if (!match_any_type_p(parser, 7, YP_TOKEN_COMMA, YP_TOKEN_KEYWORD_THEN, YP_TOKEN_BRACE_RIGHT, YP_TOKEN_BRACKET_RIGHT, YP_TOKEN_PARENTHESIS_RIGHT, YP_TOKEN_NEWLINE, YP_TOKEN_SEMICOLON)) { // Here we have a value for the first assoc in the list, so we will parse it // now and update the first assoc. @@ -9697,7 +9794,7 @@ parse_pattern_hash(yp_parser_t *parser, yp_node_t *first_assoc) { } else { yp_node_t *key = ((yp_assoc_node_t *) first_assoc)->key; - if (key->type == YP_NODE_SYMBOL_NODE) { + if (YP_NODE_TYPE_P(key, YP_NODE_SYMBOL_NODE)) { yp_location_t *value_loc = &((yp_symbol_node_t *) key)->value_loc; yp_parser_local_add_location(parser, value_loc->start, value_loc->end); } @@ -9771,7 +9868,7 @@ parse_pattern_primitive(yp_parser_t *parser, const char *message) { expect(parser, YP_TOKEN_BRACKET_RIGHT, "Expected a ] to close the pattern expression."); yp_token_t closing = parser->previous; - switch (inner->type) { + switch (YP_NODE_TYPE(inner)) { case YP_NODE_ARRAY_PATTERN_NODE: { yp_array_pattern_node_t *pattern_node = (yp_array_pattern_node_t *) inner; if (pattern_node->opening_loc.start == NULL) { @@ -10138,7 +10235,7 @@ parse_pattern(yp_parser_t *parser, bool top_pattern, const char *message) { // call this a find pattern, regardless of how many rest patterns are in // between because we know we already added the appropriate errors. // Otherwise we will create an array pattern. - if (nodes.nodes[0]->type == YP_NODE_SPLAT_NODE && nodes.nodes[nodes.size - 1]->type == YP_NODE_SPLAT_NODE) { + if (YP_NODE_TYPE_P(nodes.nodes[0], YP_NODE_SPLAT_NODE) && YP_NODE_TYPE_P(nodes.nodes[nodes.size - 1], YP_NODE_SPLAT_NODE)) { node = (yp_node_t *) yp_find_pattern_node_create(parser, &nodes); } else { node = (yp_node_t *) yp_array_pattern_node_node_list_create(parser, &nodes); @@ -10154,6 +10251,30 @@ parse_pattern(yp_parser_t *parser, bool top_pattern, const char *message) { return node; } +// Incorporate a negative sign into a numeric node by subtracting 1 character +// from its start bounds. If it's a compound node, then we will recursively +// apply this function to its value. +static inline void +parse_negative_numeric(yp_node_t *node) { + switch (YP_NODE_TYPE(node)) { + case YP_NODE_INTEGER_NODE: + case YP_NODE_FLOAT_NODE: + node->location.start--; + break; + case YP_NODE_RATIONAL_NODE: + node->location.start--; + parse_negative_numeric(((yp_rational_node_t *) node)->numeric); + break; + case YP_NODE_IMAGINARY_NODE: + node->location.start--; + parse_negative_numeric(((yp_imaginary_node_t *) node)->numeric); + break; + default: + assert(false && "unreachable"); + break; + } +} + // Parse an expression that begins with the previous node that we just lexed. static inline yp_node_t * parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { @@ -10230,7 +10351,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } yp_array_node_elements_append(array, element); - if (element->type == YP_NODE_MISSING_NODE) break; + if (YP_NODE_TYPE_P(element, YP_NODE_MISSING_NODE)) break; } accept(parser, YP_TOKEN_NEWLINE); @@ -10242,6 +10363,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } case YP_TOKEN_PARENTHESIS_LEFT: case YP_TOKEN_PARENTHESIS_LEFT_PARENTHESES: { + yp_token_type_t current_token_type = parser->current.type; parser_lex(parser); yp_token_t opening = parser->previous; @@ -10262,12 +10384,16 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { // If we hit a right parenthesis, then we're done parsing the parentheses // node, and we can check which kind of node we should return. - if (accept(parser, YP_TOKEN_PARENTHESIS_RIGHT)) { + if (match_type_p(parser, YP_TOKEN_PARENTHESIS_RIGHT)) { + if (current_token_type == YP_TOKEN_PARENTHESIS_LEFT_PARENTHESES) { + lex_state_set(parser, YP_LEX_STATE_ENDARG); + } + parser_lex(parser); yp_accepts_block_stack_pop(parser); // If we have a single statement and are ending on a right parenthesis, // then we need to check if this is possibly a multiple assignment node. - if (binding_power == YP_BINDING_POWER_STATEMENT && statement->type == YP_NODE_MULTI_WRITE_NODE) { + if (binding_power == YP_BINDING_POWER_STATEMENT && YP_NODE_TYPE_P(statement, YP_NODE_MULTI_WRITE_NODE)) { yp_multi_write_node_t *multi_statement = (yp_multi_write_node_t *) statement; if (multi_statement->value == NULL) { @@ -10465,36 +10591,42 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { case YP_TOKEN_IDENTIFIER: { parser_lex(parser); yp_token_t identifier = parser->previous; - yp_node_t *node = parse_vcall(parser); + yp_node_t *node = parse_variable_call(parser); - if (node->type == YP_NODE_CALL_NODE) { - // If parse_vcall returned with a call node, then we know the identifier - // is not in the local table. In that case we need to check if there are - // arguments following the identifier. + if (YP_NODE_TYPE_P(node, YP_NODE_CALL_NODE)) { + // If parse_variable_call returned with a call node, then we + // know the identifier is not in the local table. In that case + // we need to check if there are arguments following the + // identifier. yp_call_node_t *call = (yp_call_node_t *) node; yp_arguments_t arguments = YP_EMPTY_ARGUMENTS; - parse_arguments_list(parser, &arguments, true); - - call->opening_loc = arguments.opening_loc; - call->arguments = arguments.arguments; - call->closing_loc = arguments.closing_loc; - call->block = arguments.block; - if (arguments.block != NULL) { - call->base.location.end = arguments.block->base.location.end; - } else if (arguments.closing_loc.start == NULL) { - if (arguments.arguments != NULL) { - call->base.location.end = arguments.arguments->base.location.end; + if (parse_arguments_list(parser, &arguments, true)) { + // Since we found arguments, we need to turn off the + // variable call bit in the flags. + call->base.flags &= (yp_node_flags_t) ~YP_CALL_NODE_FLAGS_VARIABLE_CALL; + + call->opening_loc = arguments.opening_loc; + call->arguments = arguments.arguments; + call->closing_loc = arguments.closing_loc; + call->block = arguments.block; + + if (arguments.block != NULL) { + call->base.location.end = arguments.block->base.location.end; + } else if (arguments.closing_loc.start == NULL) { + if (arguments.arguments != NULL) { + call->base.location.end = arguments.arguments->base.location.end; + } else { + call->base.location.end = call->message_loc.end; + } } else { - call->base.location.end = call->message_loc.end; + call->base.location.end = arguments.closing_loc.end; } - } else { - call->base.location.end = arguments.closing_loc.end; } } else { - // Otherwise, we know the identifier is in the local table. This can - // still be a method call if it is followed by arguments or a block, so - // we need to check for that here. + // Otherwise, we know the identifier is in the local table. This + // can still be a method call if it is followed by arguments or + // a block, so we need to check for that here. if ( (binding_power <= YP_BINDING_POWER_ASSIGNMENT && (token_begins_expression_p(parser->current.type) || match_any_type_p(parser, 2, YP_TOKEN_USTAR, YP_TOKEN_USTAR_STAR))) || (yp_accepts_block_stack_p(parser) && match_any_type_p(parser, 2, YP_TOKEN_KEYWORD_DO, YP_TOKEN_BRACE_LEFT)) @@ -10542,10 +10674,10 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { lex_state_set(parser, YP_LEX_STATE_END); expect(parser, YP_TOKEN_HEREDOC_END, "Expected a closing delimiter for heredoc."); if (quote == YP_HEREDOC_QUOTE_BACKTICK) { - assert(node->type == YP_NODE_INTERPOLATED_X_STRING_NODE); + assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_X_STRING_NODE)); yp_interpolated_xstring_node_closing_set(((yp_interpolated_x_string_node_t *) node), &parser->previous); } else { - assert(node->type == YP_NODE_INTERPOLATED_STRING_NODE); + assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_STRING_NODE)); yp_interpolated_string_node_closing_set((yp_interpolated_string_node_t *) node, &parser->previous); } @@ -10606,10 +10738,10 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_node_t *new_name = parse_alias_argument(parser, true); yp_node_t *old_name = parse_alias_argument(parser, false); - switch (new_name->type) { + switch (YP_NODE_TYPE(new_name)) { case YP_NODE_SYMBOL_NODE: case YP_NODE_INTERPOLATED_SYMBOL_NODE: { - if (old_name->type != YP_NODE_SYMBOL_NODE && old_name->type != YP_NODE_INTERPOLATED_SYMBOL_NODE) { + if (!YP_NODE_TYPE_P(old_name, YP_NODE_SYMBOL_NODE) && !YP_NODE_TYPE_P(old_name, YP_NODE_INTERPOLATED_SYMBOL_NODE)) { yp_diagnostic_list_append(&parser->error_list, old_name->location.start, old_name->location.end, "Expected a bare word or symbol argument."); } break; @@ -10617,8 +10749,8 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { case YP_NODE_BACK_REFERENCE_READ_NODE: case YP_NODE_NUMBERED_REFERENCE_READ_NODE: case YP_NODE_GLOBAL_VARIABLE_READ_NODE: { - if (old_name->type == YP_NODE_BACK_REFERENCE_READ_NODE || old_name->type == YP_NODE_NUMBERED_REFERENCE_READ_NODE || old_name->type == YP_NODE_GLOBAL_VARIABLE_READ_NODE) { - if (old_name->type == YP_NODE_NUMBERED_REFERENCE_READ_NODE) { + if (YP_NODE_TYPE_P(old_name, YP_NODE_BACK_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(old_name, YP_NODE_NUMBERED_REFERENCE_READ_NODE) || YP_NODE_TYPE_P(old_name, YP_NODE_GLOBAL_VARIABLE_READ_NODE)) { + if (YP_NODE_TYPE_P(old_name, YP_NODE_NUMBERED_REFERENCE_READ_NODE)) { yp_diagnostic_list_append(&parser->error_list, old_name->location.start, old_name->location.end, "Can't make alias for number variables."); } } else { @@ -10673,12 +10805,12 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_splat_node_t *splat_node = yp_splat_node_create(parser, &operator, expression); yp_when_node_conditions_append(when_node, (yp_node_t *) splat_node); - if (expression->type == YP_NODE_MISSING_NODE) break; + if (YP_NODE_TYPE_P(expression, YP_NODE_MISSING_NODE)) break; } else { yp_node_t *condition = parse_expression(parser, YP_BINDING_POWER_DEFINED, "Expected a value after when keyword."); yp_when_node_conditions_append(when_node, condition); - if (condition->type == YP_NODE_MISSING_NODE) break; + if (YP_NODE_TYPE_P(condition, YP_NODE_MISSING_NODE)) break; } } while (accept(parser, YP_TOKEN_COMMA)); @@ -10826,7 +10958,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { parser_lex(parser); yp_token_t keyword = parser->previous; - yp_arguments_node_t *arguments = NULL; + yp_arguments_t arguments = YP_EMPTY_ARGUMENTS; if ( token_begins_expression_p(parser->current.type) || @@ -10835,16 +10967,16 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_binding_power_t binding_power = yp_binding_powers[parser->current.type].left; if (binding_power == YP_BINDING_POWER_UNSET || binding_power >= YP_BINDING_POWER_RANGE) { - arguments = yp_arguments_node_create(parser); - parse_arguments(parser, arguments, false, YP_TOKEN_EOF); + arguments.arguments = yp_arguments_node_create(parser); + parse_arguments(parser, &arguments, false, YP_TOKEN_EOF); } } switch (keyword.type) { case YP_TOKEN_KEYWORD_BREAK: - return (yp_node_t *) yp_break_node_create(parser, &keyword, arguments); + return (yp_node_t *) yp_break_node_create(parser, &keyword, arguments.arguments); case YP_TOKEN_KEYWORD_NEXT: - return (yp_node_t *) yp_next_node_create(parser, &keyword, arguments); + return (yp_node_t *) yp_next_node_create(parser, &keyword, arguments.arguments); case YP_TOKEN_KEYWORD_RETURN: { if ( (parser->current_context->context == YP_CONTEXT_CLASS) || @@ -10852,7 +10984,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { ) { yp_diagnostic_list_append(&parser->error_list, parser->current.start, parser->current.end, "Invalid return in class/module body"); } - return (yp_node_t *) yp_return_node_create(parser, &keyword, arguments); + return (yp_node_t *) yp_return_node_create(parser, &keyword, arguments.arguments); } default: assert(false && "unreachable"); @@ -10899,7 +11031,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } if (match_any_type_p(parser, 2, YP_TOKEN_KEYWORD_RESCUE, YP_TOKEN_KEYWORD_ENSURE)) { - assert(statements == NULL || statements->type == YP_NODE_STATEMENTS_NODE); + assert(statements == NULL || YP_NODE_TYPE_P(statements, YP_NODE_STATEMENTS_NODE)); statements = (yp_node_t *) parse_rescues_as_begin(parser, (yp_statements_node_t *) statements); } @@ -10939,7 +11071,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } if (match_any_type_p(parser, 2, YP_TOKEN_KEYWORD_RESCUE, YP_TOKEN_KEYWORD_ENSURE)) { - assert(statements == NULL || statements->type == YP_NODE_STATEMENTS_NODE); + assert(statements == NULL || YP_NODE_TYPE_P(statements, YP_NODE_STATEMENTS_NODE)); statements = (yp_node_t *) parse_rescues_as_begin(parser, (yp_statements_node_t *) statements); } @@ -10976,7 +11108,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { parser_lex(parser); if (match_any_type_p(parser, 2, YP_TOKEN_DOT, YP_TOKEN_COLON_COLON)) { - receiver = parse_vcall(parser); + receiver = parse_variable_call(parser); lex_state_set(parser, YP_LEX_STATE_FNAME); parser_lex(parser); @@ -11169,7 +11301,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } if (match_any_type_p(parser, 2, YP_TOKEN_KEYWORD_RESCUE, YP_TOKEN_KEYWORD_ENSURE)) { - assert(statements == NULL || statements->type == YP_NODE_STATEMENTS_NODE); + assert(statements == NULL || YP_NODE_TYPE_P(statements, YP_NODE_STATEMENTS_NODE)); statements = (yp_node_t *) parse_rescues_as_begin(parser, (yp_statements_node_t *) statements); } @@ -11281,22 +11413,23 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_undef_node_t *undef = yp_undef_node_create(parser, &parser->previous); yp_node_t *name = parse_undef_argument(parser); - if (name->type != YP_NODE_MISSING_NODE) { + if (YP_NODE_TYPE_P(name, YP_NODE_MISSING_NODE)) { + yp_node_destroy(parser, name); + } else { yp_undef_node_append(undef, name); while (match_type_p(parser, YP_TOKEN_COMMA)) { lex_state_set(parser, YP_LEX_STATE_FNAME | YP_LEX_STATE_FITEM); parser_lex(parser); name = parse_undef_argument(parser); - if (name->type == YP_NODE_MISSING_NODE) { + + if (YP_NODE_TYPE_P(name, YP_NODE_MISSING_NODE)) { yp_node_destroy(parser, name); break; } yp_undef_node_append(undef, name); } - } else { - yp_node_destroy(parser, name); } return (yp_node_t *) undef; @@ -11343,7 +11476,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { // If we can recover from a syntax error that occurred while parsing the // name of the module, then we'll handle that here. - if (name->type == YP_NODE_MISSING_NODE) { + if (YP_NODE_TYPE_P(name, YP_NODE_MISSING_NODE)) { yp_token_t end_keyword = (yp_token_t) { .type = YP_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end }; return (yp_node_t *) yp_module_node_create(parser, NULL, &module_keyword, name, NULL, &end_keyword); } @@ -11368,7 +11501,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } if (match_any_type_p(parser, 2, YP_TOKEN_KEYWORD_RESCUE, YP_TOKEN_KEYWORD_ENSURE)) { - assert(statements == NULL || statements->type == YP_NODE_STATEMENTS_NODE); + assert(statements == NULL || YP_NODE_TYPE_P(statements, YP_NODE_STATEMENTS_NODE)); statements = (yp_node_t *) parse_rescues_as_begin(parser, (yp_statements_node_t *) statements); } @@ -11417,7 +11550,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close `until` statement."); } - yp_until_node_t *until_node = yp_until_node_create(parser, &keyword, predicate, statements); + yp_until_node_t *until_node = yp_until_node_create(parser, &keyword, predicate, statements, 0); if (parser->previous.type == YP_TOKEN_KEYWORD_END) { until_node->base.location.end = parser->previous.end; } @@ -11443,7 +11576,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { expect(parser, YP_TOKEN_KEYWORD_END, "Expected `end` to close `while` statement."); } - yp_while_node_t *while_node = yp_while_node_create(parser, &keyword, predicate, statements); + yp_while_node_t *while_node = yp_while_node_create(parser, &keyword, predicate, statements, 0); if (parser->previous.type == YP_TOKEN_KEYWORD_END) { while_node->base.location.end = parser->previous.end; } @@ -11510,7 +11643,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { // to create a new string node and set that to the current. parser_lex(parser); current = (yp_node_t *) yp_symbol_node_create_and_unescape(parser, &opening, &parser->previous, &closing, YP_UNESCAPE_ALL); - } else if (current->type == YP_NODE_INTERPOLATED_SYMBOL_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_INTERPOLATED_SYMBOL_NODE)) { // 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. @@ -11531,7 +11664,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_token_t opening = not_provided(parser); yp_token_t closing = not_provided(parser); current = (yp_node_t *) yp_interpolated_symbol_node_create(parser, &opening, NULL, &closing); - } else if (current->type == YP_NODE_SYMBOL_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_SYMBOL_NODE)) { // If we hit an embedded variable and the current node is a string // node, then we'll convert the current into an interpolated // string and add the string node to the list of parts. @@ -11565,7 +11698,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_token_t opening = not_provided(parser); yp_token_t closing = not_provided(parser); current = (yp_node_t *) yp_interpolated_symbol_node_create(parser, &opening, NULL, &closing); - } else if (current->type == YP_NODE_SYMBOL_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_SYMBOL_NODE)) { // If we hit an embedded expression and the current node is a // string node, then we'll convert the current into an // interpolated string and add the string node to the list of @@ -11579,7 +11712,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { interpolated->base.location.start = current->location.start; start_location_set = true; current = (yp_node_t *) interpolated; - } else if (current->type == YP_NODE_INTERPOLATED_SYMBOL_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_INTERPOLATED_SYMBOL_NODE)) { // If we hit an embedded expression and the current node is an // interpolated string, then we'll just continue on. } else { @@ -11667,7 +11800,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { // the first string content we've seen. In that case we're going // to create a new string node and set that to the current. current = parse_string_part(parser); - } else if (current->type == YP_NODE_INTERPOLATED_STRING_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_INTERPOLATED_STRING_NODE)) { // 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. @@ -11687,7 +11820,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_token_t opening = not_provided(parser); yp_token_t closing = not_provided(parser); current = (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, NULL, &closing); - } else if (current->type == YP_NODE_STRING_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_STRING_NODE)) { // If we hit an embedded variable and the current node is a string // node, then we'll convert the current into an interpolated // string and add the string node to the list of parts. @@ -11713,7 +11846,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_token_t opening = not_provided(parser); yp_token_t closing = not_provided(parser); current = (yp_node_t *) yp_interpolated_string_node_create(parser, &opening, NULL, &closing); - } else if (current->type == YP_NODE_STRING_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_STRING_NODE)) { // If we hit an embedded expression and the current node is a // string node, then we'll convert the current into an // interpolated string and add the string node to the list of @@ -11723,7 +11856,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { yp_interpolated_string_node_t *interpolated = yp_interpolated_string_node_create(parser, &opening, NULL, &closing); yp_interpolated_string_node_append(interpolated, current); current = (yp_node_t *) interpolated; - } else if (current->type == YP_NODE_INTERPOLATED_STRING_NODE) { + } else if (YP_NODE_TYPE_P(current, YP_NODE_INTERPOLATED_STRING_NODE)) { // If we hit an embedded expression and the current node is an // interpolated string, then we'll just continue on. } else { @@ -11917,8 +12050,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { return (yp_node_t *) node; } - case YP_TOKEN_UMINUS: - case YP_TOKEN_UMINUS_NUM: { + case YP_TOKEN_UMINUS: { parser_lex(parser); yp_token_t operator = parser->previous; @@ -11927,6 +12059,26 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { return (yp_node_t *) node; } + case YP_TOKEN_UMINUS_NUM: { + parser_lex(parser); + + yp_token_t operator = parser->previous; + yp_node_t *node = parse_expression(parser, yp_binding_powers[parser->previous.type].right, "Expected a receiver after unary -."); + + switch (YP_NODE_TYPE(node)) { + case YP_NODE_INTEGER_NODE: + case YP_NODE_FLOAT_NODE: + case YP_NODE_RATIONAL_NODE: + case YP_NODE_IMAGINARY_NODE: + parse_negative_numeric(node); + break; + default: + node = (yp_node_t *) yp_call_node_unary_create(parser, &operator, node, "-@"); + break; + } + + return node; + } case YP_TOKEN_MINUS_GREATER: { int previous_lambda_enclosure_nesting = parser->lambda_enclosure_nesting; parser->lambda_enclosure_nesting = parser->enclosure_nesting; @@ -11982,7 +12134,7 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { } if (match_any_type_p(parser, 2, YP_TOKEN_KEYWORD_RESCUE, YP_TOKEN_KEYWORD_ENSURE)) { - assert(body == NULL || body->type == YP_NODE_STATEMENTS_NODE); + assert(body == NULL || YP_NODE_TYPE_P(body, YP_NODE_STATEMENTS_NODE)); body = (yp_node_t *) parse_rescues_as_begin(parser, (yp_statements_node_t *) body); } @@ -12173,18 +12325,18 @@ static inline yp_node_t * parse_assignment_value(yp_parser_t *parser, yp_binding_power_t previous_binding_power, yp_binding_power_t binding_power, const char *message) { yp_node_t *value = parse_starred_expression(parser, binding_power, message); - if (previous_binding_power == YP_BINDING_POWER_STATEMENT && accept(parser, YP_TOKEN_COMMA)) { + if (previous_binding_power == YP_BINDING_POWER_STATEMENT && (YP_NODE_TYPE_P(value, YP_NODE_SPLAT_NODE) || match_type_p(parser, YP_TOKEN_COMMA))) { yp_token_t opening = not_provided(parser); yp_array_node_t *array = yp_array_node_create(parser, &opening); yp_array_node_elements_append(array, value); value = (yp_node_t *) array; - do { + while (accept(parser, YP_TOKEN_COMMA)) { yp_node_t *element = parse_starred_expression(parser, binding_power, "Expected an element for the array."); yp_array_node_elements_append(array, element); - if (element->type == YP_NODE_MISSING_NODE) break; - } while (accept(parser, YP_TOKEN_COMMA)); + if (YP_NODE_TYPE_P(element, YP_NODE_MISSING_NODE)) break; + } } return value; @@ -12196,14 +12348,14 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t switch (token.type) { case YP_TOKEN_EQUAL: { - switch (node->type) { + switch (YP_NODE_TYPE(node)) { case YP_NODE_CALL_NODE: { - // If we have no arguments to the call node and we need this to be a - // target then this is either a method call or a local variable write. - // This _must_ happen before the value is parsed because it could be - // referenced in the value. + // If we have no arguments to the call node and we need this + // to be a target then this is either a method call or a + // local variable write. This _must_ happen before the value + // is parsed because it could be referenced in the value. yp_call_node_t *call_node = (yp_call_node_t *) node; - if (yp_call_node_vcall_p(call_node)) { + if (yp_call_node_variable_call_p(call_node)) { yp_parser_local_add_location(parser, call_node->message_loc.start, call_node->message_loc.end); } } @@ -12216,13 +12368,13 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t case YP_NODE_SPLAT_NODE: { yp_splat_node_t *splat_node = (yp_splat_node_t *) node; - switch (splat_node->expression->type) { - case YP_CASE_WRITABLE: { + switch (YP_NODE_TYPE(splat_node->expression)) { + case YP_CASE_WRITABLE: parser_lex(parser); yp_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, "Expected a value after =."); return parse_target(parser, (yp_node_t *) splat_node, &token, value); - } - default: {} + default: + break; } } /* fallthrough */ @@ -12237,7 +12389,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t } } case YP_TOKEN_AMPERSAND_AMPERSAND_EQUAL: { - switch (node->type) { + switch (YP_NODE_TYPE(node)) { case YP_NODE_BACK_REFERENCE_READ_NODE: case YP_NODE_NUMBERED_REFERENCE_READ_NODE: yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable"); @@ -12257,7 +12409,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t // If we have a vcall (a method with no arguments and no // receiver that could have been a local variable) then we // will transform it into a local variable write. - if (yp_call_node_vcall_p(call_node)) { + if (yp_call_node_variable_call_p(call_node)) { yp_location_t message_loc = call_node->message_loc; yp_parser_local_add_location(parser, message_loc.start, message_loc.end); @@ -12342,7 +12494,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t } } case YP_TOKEN_PIPE_PIPE_EQUAL: { - switch (node->type) { + switch (YP_NODE_TYPE(node)) { case YP_NODE_BACK_REFERENCE_READ_NODE: case YP_NODE_NUMBERED_REFERENCE_READ_NODE: yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable"); @@ -12362,7 +12514,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t // If we have a vcall (a method with no arguments and no // receiver that could have been a local variable) then we // will transform it into a local variable write. - if (yp_call_node_vcall_p(call_node)) { + if (yp_call_node_variable_call_p(call_node)) { yp_location_t message_loc = call_node->message_loc; yp_parser_local_add_location(parser, message_loc.start, message_loc.end); @@ -12457,7 +12609,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t case YP_TOKEN_SLASH_EQUAL: case YP_TOKEN_STAR_EQUAL: case YP_TOKEN_STAR_STAR_EQUAL: { - switch (node->type) { + switch (YP_NODE_TYPE(node)) { case YP_NODE_BACK_REFERENCE_READ_NODE: case YP_NODE_NUMBERED_REFERENCE_READ_NODE: yp_diagnostic_list_append(&parser->error_list, node->location.start, node->location.end, "Can't set variable"); @@ -12477,7 +12629,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t // If we have a vcall (a method with no arguments and no // receiver that could have been a local variable) then we // will transform it into a local variable write. - if (yp_call_node_vcall_p(call_node)) { + if (yp_call_node_variable_call_p(call_node)) { yp_location_t message_loc = call_node->message_loc; yp_parser_local_add_location(parser, message_loc.start, message_loc.end); @@ -12586,7 +12738,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t // If the receiver of this =~ is a regular expression node, then we need // to introduce local variables for it based on its named capture groups. - if (node->type == YP_NODE_REGULAR_EXPRESSION_NODE) { + if (YP_NODE_TYPE_P(node, YP_NODE_REGULAR_EXPRESSION_NODE)) { yp_string_list_t named_captures; yp_string_list_init(&named_captures); @@ -12606,6 +12758,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t return (yp_node_t *) yp_call_node_binary_create(parser, node, &token, argument); } + case YP_TOKEN_UAMPERSAND: case YP_TOKEN_USTAR: case YP_TOKEN_USTAR_STAR: // The only times this will occur are when we are in an error state, @@ -12709,7 +12862,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t yp_statements_node_body_append(statements, node); yp_node_t *predicate = parse_expression(parser, binding_power, "Expected a predicate after 'until'"); - return (yp_node_t *) yp_until_node_create(parser, &token, predicate, statements); + return (yp_node_t *) yp_until_node_create(parser, &token, predicate, statements, YP_NODE_TYPE_P(node, YP_NODE_BEGIN_NODE) ? YP_LOOP_FLAGS_BEGIN_MODIFIER : 0); } case YP_TOKEN_KEYWORD_WHILE_MODIFIER: { parser_lex(parser); @@ -12717,7 +12870,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t yp_statements_node_body_append(statements, node); yp_node_t *predicate = parse_expression(parser, binding_power, "Expected a predicate after 'while'"); - return (yp_node_t *) yp_while_node_create(parser, &token, predicate, statements); + return (yp_node_t *) yp_while_node_create(parser, &token, predicate, statements, YP_NODE_TYPE_P(node, YP_NODE_BEGIN_NODE) ? YP_LOOP_FLAGS_BEGIN_MODIFIER : 0); } case YP_TOKEN_QUESTION_MARK: { parser_lex(parser); @@ -12785,12 +12938,13 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t case YP_CASE_KEYWORD: case YP_TOKEN_IDENTIFIER: { parser_lex(parser); + yp_token_t message = parser->previous; // If we have an identifier following a '::' operator, then it is for // sure a method call. yp_arguments_t arguments = YP_EMPTY_ARGUMENTS; parse_arguments_list(parser, &arguments, true); - yp_call_node_t *call = yp_call_node_call_create(parser, node, &delimiter, &parser->previous, &arguments); + yp_call_node_t *call = yp_call_node_call_create(parser, node, &delimiter, &message, &arguments); // If this is followed by a comma then it is a multiple assignment. if (previous_binding_power == YP_BINDING_POWER_STATEMENT && match_type_p(parser, YP_TOKEN_COMMA)) { @@ -12831,7 +12985,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t yp_accepts_block_stack_push(parser, true); arguments.arguments = yp_arguments_node_create(parser); - parse_arguments(parser, arguments.arguments, false, YP_TOKEN_BRACKET_RIGHT); + parse_arguments(parser, &arguments, false, YP_TOKEN_BRACKET_RIGHT); yp_accepts_block_stack_pop(parser); expect(parser, YP_TOKEN_BRACKET_RIGHT, "Expected ']' to close the bracket expression."); @@ -12855,6 +13009,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t arguments.block = parse_block(parser); } + yp_arguments_validate(parser, &arguments); return (yp_node_t *) yp_call_node_aref_create(parser, node, &arguments); } case YP_TOKEN_KEYWORD_IN: { @@ -12907,7 +13062,7 @@ parse_expression(yp_parser_t *parser, yp_binding_power_t binding_power, const ch // If we found a syntax error, then the type of node returned by // parse_expression_prefix is going to be a missing node. In that case we need // to add the error message to the parser's error list. - if (node->type == YP_NODE_MISSING_NODE) { + if (YP_NODE_TYPE_P(node, YP_NODE_MISSING_NODE)) { yp_diagnostic_list_append(&parser->error_list, recovery.end, recovery.end, message); return node; } @@ -12948,8 +13103,11 @@ parse_program(yp_parser_t *parser) { return (yp_node_t *) yp_program_node_create(parser, &locals, statements); } +// Read a 32-bit unsigned integer from a pointer. This function is used to read +// the metadata that is passed into the parser from the Ruby implementation. It +// handles aligned and unaligned reads. static uint32_t -yp_read_u32(const char *ptr) { +yp_metadata_read_u32(const char *ptr) { if (((uintptr_t) ptr) % sizeof(uint32_t) == 0) { return *((uint32_t *) ptr); } else { @@ -12959,45 +13117,57 @@ yp_read_u32(const char *ptr) { } } -// Process any additional metadata being passed into a parse. Since the source -// of these calls will be from Ruby implementation internals we assume it is from -// a trusted source. +// Process any additional metadata being passed into a call to the parser via +// the yp_parse_serialize function. Since the source of these calls will be from +// Ruby implementation internals we assume it is from a trusted source. // // Currently, this is only passing in variable scoping surrounding an eval, but // eventually it will be extended to hold any additional metadata. This data // is serialized to reduce the calling complexity for a foreign function call // vs a foreign runtime making a bindable in-memory version of a C structure. // -// *Format* -// -// No metadata should just be NULL. For variable scopes it should be: +// metadata is assumed to be a valid pointer pointing to well-formed data. The +// format is described below: // // ```text -// [number_of_variable_scopes: uint32_t, -// [number_of_variables: uint32_t, -// [data_length: uint32_t, data: char*]* +// [ +// filepath_size: uint32_t, +// filepath: char*, +// scopes_count: uint32_t, +// [ +// locals_count: uint32_t, +// [local_size: uint32_t, local: char*]* // ]* // ] // ``` static void yp_parser_metadata(yp_parser_t *parser, const char *metadata) { - const char *p = metadata; - uint32_t number_of_scopes = yp_read_u32(p); - p += 4; + uint32_t filepath_size = yp_metadata_read_u32(metadata); + metadata += 4; - for (size_t scope_index = 0; scope_index < number_of_scopes; scope_index++) { - uint32_t number_of_variables = yp_read_u32(p); - p += 4; + if (filepath_size) { + yp_string_t filepath_string; + yp_string_constant_init(&filepath_string, metadata, filepath_size); - yp_parser_scope_push(parser, scope_index == 0); + parser->filepath_string = filepath_string; + metadata += filepath_size; + } - for (size_t variable_index = 0; variable_index < number_of_variables; variable_index++) { - uint32_t length = yp_read_u32(p); - p += 4; + uint32_t scopes_count = yp_metadata_read_u32(metadata); + metadata += 4; + + for (size_t scope_index = 0; scope_index < scopes_count; scope_index++) { + uint32_t locals_count = yp_metadata_read_u32(metadata); + metadata += 4; + + yp_parser_scope_push(parser, scope_index == 0); - yp_parser_local_add_location(parser, p, p + length); + for (size_t local_index = 0; local_index < locals_count; local_index++) { + uint32_t local_size = yp_metadata_read_u32(metadata); + metadata += 4; - p += length; + yp_parser_local_add_location(parser, metadata, metadata + local_size); + metadata += local_size; } } } diff --git a/yarp/yarp.h b/yarp/yarp.h index 1c6652a3021ebc..787029fcc33ed0 100644 --- a/yarp/yarp.h +++ b/yarp/yarp.h @@ -59,10 +59,12 @@ YP_EXPORTED_FUNCTION void yp_prettyprint(yp_parser_t *parser, yp_node_t *node, y // Serialize the AST represented by the given node to the given buffer. YP_EXPORTED_FUNCTION void yp_serialize(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buffer); -// Parse and serialize the AST represented by the given source to the given -// buffer. +// Parse the given source to the AST and serialize the AST to the given buffer. YP_EXPORTED_FUNCTION void yp_parse_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *metadata); +// Lex the given source and serialize to the given buffer. +YP_EXPORTED_FUNCTION void yp_lex_serialize(const char *source, size_t size, const char *filepath, yp_buffer_t *buffer); + // Returns a string representation of the given token type. YP_EXPORTED_FUNCTION const char * yp_token_type_to_str(yp_token_type_t token_type); From f20dfd0803fb21a9332092922378a0de022eaa67 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 15 Aug 2023 10:02:43 -0700 Subject: [PATCH 137/158] Fix the YARP init path --- yarp/yarp_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarp/yarp_init.c b/yarp/yarp_init.c index 48efc0e779b711..4684e99db65744 100644 --- a/yarp/yarp_init.c +++ b/yarp/yarp_init.c @@ -5,5 +5,5 @@ void ruby_init_ext(const char *name, void (*init)(void)); void Init_YARP(void) { - ruby_init_ext("yarp.so", Init_yarp); + ruby_init_ext("yarp/yarp.so", Init_yarp); } From 87f74a349e5ed337b708e3626dc946252dfc2c86 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 15 Aug 2023 10:01:31 -0700 Subject: [PATCH 138/158] Update dependencies --- common.mk | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/common.mk b/common.mk index 6aea69e9e09261..b9c3b664b92f2e 100644 --- a/common.mk +++ b/common.mk @@ -85,32 +85,14 @@ MAKE_ENC = -f $(ENC_MK) V="$(V)" UNICODE_HDR_DIR="$(UNICODE_HDR_DIR)" \ YARP_FILES = yarp/api_node.$(OBJEXT) \ yarp/api_pack.$(OBJEXT) \ yarp/diagnostic.$(OBJEXT) \ - yarp/enc/yp_ascii.$(OBJEXT) \ yarp/enc/yp_big5.$(OBJEXT) \ yarp/enc/yp_euc_jp.$(OBJEXT) \ yarp/enc/yp_gbk.$(OBJEXT) \ - yarp/enc/yp_iso_8859_1.$(OBJEXT) \ - yarp/enc/yp_iso_8859_10.$(OBJEXT) \ - yarp/enc/yp_iso_8859_11.$(OBJEXT) \ - yarp/enc/yp_iso_8859_13.$(OBJEXT) \ - yarp/enc/yp_iso_8859_14.$(OBJEXT) \ - yarp/enc/yp_iso_8859_15.$(OBJEXT) \ - yarp/enc/yp_iso_8859_16.$(OBJEXT) \ - yarp/enc/yp_iso_8859_2.$(OBJEXT) \ - yarp/enc/yp_iso_8859_3.$(OBJEXT) \ - yarp/enc/yp_iso_8859_4.$(OBJEXT) \ - yarp/enc/yp_iso_8859_5.$(OBJEXT) \ - yarp/enc/yp_iso_8859_6.$(OBJEXT) \ - yarp/enc/yp_iso_8859_7.$(OBJEXT) \ - yarp/enc/yp_iso_8859_8.$(OBJEXT) \ - yarp/enc/yp_iso_8859_9.$(OBJEXT) \ - yarp/enc/yp_koi8_r.$(OBJEXT) \ - yarp/enc/yp_shared.$(OBJEXT) \ yarp/enc/yp_shift_jis.$(OBJEXT) \ + yarp/enc/yp_tables.$(OBJEXT) \ yarp/enc/yp_unicode.$(OBJEXT) \ - yarp/enc/yp_windows_1251.$(OBJEXT) \ - yarp/enc/yp_windows_1252.$(OBJEXT) \ yarp/enc/yp_windows_31j.$(OBJEXT) \ + yarp/extension.$(OBJEXT) \ yarp/node.$(OBJEXT) \ yarp/pack.$(OBJEXT) \ yarp/prettyprint.$(OBJEXT) \ @@ -130,8 +112,7 @@ YARP_FILES = yarp/api_node.$(OBJEXT) \ yarp/util/yp_strncasecmp.$(OBJEXT) \ yarp/util/yp_strpbrk.$(OBJEXT) \ yarp/yarp.$(OBJEXT) \ - yarp/yarp_init.$(OBJEXT) \ - yarp/extension.$(OBJEXT) + yarp/yarp_init.$(OBJEXT) COMMONOBJS = array.$(OBJEXT) \ ast.$(OBJEXT) \ @@ -19330,6 +19311,11 @@ yarp/enc/yp_shift_jis.$(OBJEXT): $(top_srcdir)/yarp/defines.h yarp/enc/yp_shift_jis.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h yarp/enc/yp_shift_jis.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_shift_jis.c yarp/enc/yp_shift_jis.$(OBJEXT): {$(VPATH)}config.h +yarp/enc/yp_tables.$(OBJEXT): $(top_srcdir)/yarp/config.h +yarp/enc/yp_tables.$(OBJEXT): $(top_srcdir)/yarp/defines.h +yarp/enc/yp_tables.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h +yarp/enc/yp_tables.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_tables.c +yarp/enc/yp_tables.$(OBJEXT): {$(VPATH)}config.h yarp/enc/yp_unicode.$(OBJEXT): $(top_srcdir)/yarp/config.h yarp/enc/yp_unicode.$(OBJEXT): $(top_srcdir)/yarp/defines.h yarp/enc/yp_unicode.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h @@ -19590,6 +19576,7 @@ yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/regexp.c yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/regexp.h yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h +yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h @@ -19598,15 +19585,25 @@ yarp/regexp.$(OBJEXT): {$(VPATH)}config.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/ast.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/config.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/defines.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/node.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/pack.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/parser.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/regexp.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/serialize.c +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/unescape.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h +yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/yarp.h yarp/serialize.$(OBJEXT): {$(VPATH)}config.h yarp/token_type.$(OBJEXT): $(top_srcdir)/yarp/ast.h yarp/token_type.$(OBJEXT): $(top_srcdir)/yarp/config.h @@ -19620,9 +19617,13 @@ yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/config.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/defines.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h +yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/node.h +yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/pack.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/parser.h +yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/regexp.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/unescape.c yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/unescape.h +yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h @@ -19630,6 +19631,9 @@ yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h +yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h +yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h +yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/yarp.h yarp/unescape.$(OBJEXT): {$(VPATH)}config.h yarp/util/yp_buffer.$(OBJEXT): $(top_srcdir)/yarp/config.h yarp/util/yp_buffer.$(OBJEXT): $(top_srcdir)/yarp/defines.h From c989c1b068e944908d185bfab67b64bc52a072d0 Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Tue, 15 Aug 2023 14:34:24 -0700 Subject: [PATCH 139/158] [ruby/yarp] Omit locals test if running on a 32 bit machine https://github.com/ruby/yarp/commit/809d046f36 --- test/yarp/locals_test.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/yarp/locals_test.rb b/test/yarp/locals_test.rb index 18d8edacdaa309..d6b3120f6288a1 100644 --- a/test/yarp/locals_test.rb +++ b/test/yarp/locals_test.rb @@ -9,6 +9,10 @@ # to test on the most recent versions. return if !defined?(RubyVM::InstructionSequence) || RUBY_VERSION < "3.2" +# Omit tests if running on a 32-bit machine because there is a bug with how +# Ruby is handling large ISeqs on 32-bit machines +return if RUBY_PLATFORM =~ /i686/ + require "yarp_test_helper" class LocalsTest < Test::Unit::TestCase From 45740e7a248b4b995644646e38d94b8be44fc60c Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Wed, 16 Aug 2023 15:42:56 -0700 Subject: [PATCH 140/158] [ruby/yarp] Use _snprintf when using Windows versions prior to 2015 (< 1900) Ruby CI has informed us that snprintf is not available on Windows versions, but _sprintf is supported. This commit allows us to use _sprintf where applicable https://github.com/ruby/yarp/commit/818cc96afe --- yarp/defines.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yarp/defines.h b/yarp/defines.h index 32ed3a557a9f94..c08d578422dd5b 100644 --- a/yarp/defines.h +++ b/yarp/defines.h @@ -34,6 +34,11 @@ # define inline __inline #endif +// Windows versions before 2015 use _snprintf +#if defined(_MSC_VER) && (_MSC_VER < 1900) +# define snprintf _snprintf +#endif + int yp_strncasecmp(const char *string1, const char *string2, size_t length); #endif From f1778870bd0690a626ee09dbc068d15048e8e63b Mon Sep 17 00:00:00 2001 From: git Date: Thu, 17 Aug 2023 00:48:19 +0000 Subject: [PATCH 141/158] Update default gems list at 45740e7a248b4b995644646e38d94b [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index cdd3e38a69b7eb..dd40577821fa26 100644 --- a/NEWS.md +++ b/NEWS.md @@ -82,7 +82,7 @@ The following default gems are updated. * time 0.2.2 * timeout 0.4.0 * uri 0.12.2 -* yarp 0.4.0 +* yarp 0.7.0 The following bundled gems are updated. From 7183cf53f868c6a1abdc2ff4cb848c28c4858f05 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 15 Aug 2023 16:47:48 -0700 Subject: [PATCH 142/158] Revert an unintended revert --- tool/sync_default_gems.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 8f2f3b5df0e12a..bdc7bc698158cf 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -371,7 +371,7 @@ def sync_default_gems(gem) `git checkout ext/digest/depend ext/digest/*/depend` when "set" sync_lib gem, upstream - cp_r("#{upstream}/test", ".") + cp_r(Dir.glob("#{upstream}/test/*"), "test/set") when "optparse" sync_lib gem, upstream rm_rf(%w[doc/optparse]) From cdb757f817b0721d79d43ae8de6f8198d6033177 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 16 Aug 2023 17:55:32 -0700 Subject: [PATCH 143/158] Avoid synchronizing GitHub Actions from YARP --- tool/sync_default_gems.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index bdc7bc698158cf..28a1f963e8d98f 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -446,6 +446,7 @@ def sync_default_gems(gem) |[^\/]+\.yml |\.gitignore |\.git.* + |\.github/.* |[A-Z]\w+file |COPYING |CONTRIBUTING\.md From 1c53e64c512668685bb7abaf1232518af3969496 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 16 Aug 2023 17:55:56 -0700 Subject: [PATCH 144/158] Fix a regexp error --- tool/sync_default_gems.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 28a1f963e8d98f..17865b8afb3e5b 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -446,7 +446,7 @@ def sync_default_gems(gem) |[^\/]+\.yml |\.gitignore |\.git.* - |\.github/.* + |\.github\/.* |[A-Z]\w+file |COPYING |CONTRIBUTING\.md From 48b241e53fdb68c0ad115bcd23a43b310cc18db1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 16 Aug 2023 21:12:44 -0400 Subject: [PATCH 145/158] [ruby/yarp] Fix errors on locals test caused by LANG=C https://github.com/ruby/yarp/commit/8fae286bc9 --- test/yarp/locals_test.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/yarp/locals_test.rb b/test/yarp/locals_test.rb index d6b3120f6288a1..4d9cea94a80a22 100644 --- a/test/yarp/locals_test.rb +++ b/test/yarp/locals_test.rb @@ -77,6 +77,15 @@ class LocalsTest < Test::Unit::TestCase define_method("test_#{relative}") { assert_locals(filepath) } end + def setup + @previous_default_external = Encoding.default_external + ignore_warnings { Encoding.default_external = Encoding::UTF_8 } + end + + def teardown + ignore_warnings { Encoding.default_external = @previous_default_external } + end + private def assert_locals(filepath) @@ -87,4 +96,12 @@ def assert_locals(filepath) assert_equal(expected, actual) end + + def ignore_warnings + previous_verbosity = $VERBOSE + $VERBOSE = nil + yield + ensure + $VERBOSE = previous_verbosity + end end From 5bb946228550c7f171c27725860b153a675404f3 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Aug 2023 21:39:49 +0900 Subject: [PATCH 146/158] [Bug #19831] Remove duplicate library options `$(MAINLIBS)` should be included in `$(LIBRUBYARG)` in cases it is needed. --- template/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/Makefile.in b/template/Makefile.in index e95b0dd32a83cc..893581c4571abd 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -292,7 +292,7 @@ miniruby$(EXEEXT): $(PROGRAM): @$(RM) $@ $(ECHO) linking $@ - $(Q) $(PURIFY) $(CC) $(EXE_LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(EXTLIBS) $(OUTFLAG)$@ + $(Q) $(PURIFY) $(CC) $(EXE_LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(EXTLIBS) $(OUTFLAG)$@ $(Q) $(POSTLINK) $(PROGRAM): @XRUBY_LIBPATHENV_WRAPPER@ From e210b899dc803607bef1b395ace02dc9f96554ea Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 16 Aug 2023 20:28:33 -0700 Subject: [PATCH 147/158] Move the PC regardless of the leaf flag (#8232) Co-authored-by: Alan Wu --- compile.c | 6 ----- gc.c | 35 ---------------------------- internal/compile.h | 1 - test/objspace/test_objspace.rb | 7 ++++++ tool/ruby_vm/views/_insn_entry.erb | 5 ++-- tool/ruby_vm/views/_leaf_helpers.erb | 25 -------------------- vm_insnhelper.h | 6 ++--- 7 files changed, 11 insertions(+), 74 deletions(-) diff --git a/compile.c b/compile.c index de34b0f0431260..7ae6efb668a9e6 100644 --- a/compile.c +++ b/compile.c @@ -10217,12 +10217,6 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, fflush(stdout); } -bool -rb_insns_leaf_p(int i) -{ - return insn_leaf_p(i); -} - int rb_insn_len(VALUE insn) { diff --git a/gc.c b/gc.c index 0d650dbe68f79b..cc318b15e06364 100644 --- a/gc.c +++ b/gc.c @@ -2423,42 +2423,7 @@ static void gc_event_hook_body(rb_execution_context_t *ec, rb_objspace_t *objspace, const rb_event_flag_t event, VALUE data) { if (UNLIKELY(!ec->cfp)) return; - const VALUE *pc = ec->cfp->pc; - if (pc && VM_FRAME_RUBYFRAME_P(ec->cfp)) { - int prev_opcode = rb_vm_insn_addr2opcode((void *)*ec->cfp->iseq->body->iseq_encoded); - for (const VALUE *insn = ec->cfp->iseq->body->iseq_encoded; insn < pc; insn += rb_insn_len(prev_opcode)) { - prev_opcode = rb_vm_insn_addr2opcode((void *)*insn); - } - - /* If the previous instruction is a leaf instruction, then the PC is - * the currently executing instruction. We should increment the PC - * because the source line is calculated with PC-1 in calc_pos. - * - * If the previous instruction is not a leaf instruction and the - * current instruction is not a leaf instruction, then the PC was - * incremented before the instruction was ran (meaning the currently - * executing instruction is actually the previous instruction), so we - * should not increment the PC otherwise we will calculate the source - * line for the next instruction. - * - * However, this implementation still has a bug. Consider the - * following situation: - * - * non-leaf - * leaf <- - * - * Where the PC currently points to a leaf instruction. We don't know - * which instruction we really are at since we could be at the non-leaf - * instruction (since it incremented the PC before executing the - * instruction). We could also be at the leaf instruction since the PC - * doesn't get incremented until the instruction finishes. - */ - if (rb_insns_leaf_p(prev_opcode)) { - ec->cfp->pc++; - } - } EXEC_EVENT_HOOK(ec, event, ec->cfp->self, 0, 0, 0, data); - ec->cfp->pc = pc; } #define gc_event_hook_available_p(objspace) ((objspace)->flags.has_hook) diff --git a/internal/compile.h b/internal/compile.h index eebb7605cd7fa5..2ece5396f655d2 100644 --- a/internal/compile.h +++ b/internal/compile.h @@ -17,7 +17,6 @@ struct rb_iseq_struct; /* in vm_core.h */ /* compile.c */ int rb_dvar_defined(ID, const struct rb_iseq_struct *); int rb_local_defined(ID, const struct rb_iseq_struct *); -bool rb_insns_leaf_p(int i); int rb_insn_len(VALUE insn); const char *rb_insns_name(int i); VALUE rb_insns_name_array(void); diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb index 7edf6be9307318..43ccac79206a89 100644 --- a/test/objspace/test_objspace.rb +++ b/test/objspace/test_objspace.rb @@ -225,6 +225,13 @@ def test_trace_object_allocations assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(o4)) assert_equal(line4, ObjectSpace.allocation_sourceline(o4)) + # The line number should be based on newarray instead of getinstancevariable. + line5 = __LINE__; o5 = [ # newarray (leaf) + @ivar, # getinstancevariable (not leaf) + ] + assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(o5)) + assert_equal(line5, ObjectSpace.allocation_sourceline(o5)) + # [Bug #19482] EnvUtil.under_gc_stress do 100.times do diff --git a/tool/ruby_vm/views/_insn_entry.erb b/tool/ruby_vm/views/_insn_entry.erb index 32070c5f3475b6..6ec33461c48763 100644 --- a/tool/ruby_vm/views/_insn_entry.erb +++ b/tool/ruby_vm/views/_insn_entry.erb @@ -24,7 +24,7 @@ INSN_ENTRY(<%= insn.name %>) <%= ope[:decl] %> = (<%= ope[:type] %>)GET_OPERAND(<%= i + 1 %>); % end # define INSN_ATTR(x) <%= insn.call_attribute(' ## x ## ') %> - const bool leaf = INSN_ATTR(leaf); + const bool MAYBE_UNUSED(leaf) = INSN_ATTR(leaf); % insn.pops.reverse_each.with_index.reverse_each do |pop, i| <%= pop[:decl] %> = <%= insn.cast_from_VALUE pop, "TOPN(#{i})"%>; % end @@ -35,7 +35,7 @@ INSN_ENTRY(<%= insn.name %>) % end /* ### Instruction preambles. ### */ - if (! leaf) ADD_PC(INSN_ATTR(width)); + ADD_PC(INSN_ATTR(width)); % if insn.handles_sp? POPN(INSN_ATTR(popn)); % end @@ -68,7 +68,6 @@ INSN_ENTRY(<%= insn.name %>) VM_ASSERT(!RB_TYPE_P(TOPN(<%= i %>), T_MOVED)); % end % end - if (leaf) ADD_PC(INSN_ATTR(width)); # undef INSN_ATTR /* ### Leave the instruction. ### */ diff --git a/tool/ruby_vm/views/_leaf_helpers.erb b/tool/ruby_vm/views/_leaf_helpers.erb index ac35df64f40649..f740107a0ad873 100644 --- a/tool/ruby_vm/views/_leaf_helpers.erb +++ b/tool/ruby_vm/views/_leaf_helpers.erb @@ -10,31 +10,6 @@ #include "iseq.h" -extern const bool rb_vm_insn_leaf_p[]; - -#ifdef RUBY_VM_INSNS_INFO -const bool rb_vm_insn_leaf_p[] = { -% RubyVM::Instructions.each_slice(20) do |insns| - <%= insns.map do |insn| - if insn.is_a?(RubyVM::BareInstructions) - insn.always_leaf? ? '1' : '0' - else - '0' - end - end.join(', ') - %>, -% end -}; -#endif - -CONSTFUNC(MAYBE_UNUSED(static bool insn_leaf_p(VALUE insn))); - -bool -insn_leaf_p(VALUE insn) -{ - return rb_vm_insn_leaf_p[insn]; -} - // This is used to tell RJIT that this insn would be leaf if CHECK_INTS didn't exist. // It should be used only when RUBY_VM_CHECK_INTS is directly written in insns.def. static bool leafness_of_check_ints = false; diff --git a/vm_insnhelper.h b/vm_insnhelper.h index 66895cd142d514..90372853dd92fb 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -181,10 +181,8 @@ CC_SET_FASTPATH(const struct rb_callcache *cc, vm_call_handler func, bool enable /**********************************************************/ #define CALL_SIMPLE_METHOD() do { \ - rb_snum_t x = leaf ? INSN_ATTR(width) : 0; \ - rb_snum_t y = attr_width_opt_send_without_block(0); \ - rb_snum_t z = x - y; \ - ADD_PC(z); \ + rb_snum_t insn_width = attr_width_opt_send_without_block(0); \ + ADD_PC(-insn_width); \ DISPATCH_ORIGINAL_INSN(opt_send_without_block); \ } while (0) From d26b015e83e499e3bad61d6f2ef88eeca55fdedc Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 17 Aug 2023 12:18:01 +0900 Subject: [PATCH 148/158] [Bug #19831] Remove duplicate library options `$(LIBRUBYARG_SHARED)` is included in `$(LIBS)` in extension libraries. --- configure.ac | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index caacfebbedce3d..f71c2c260904a2 100644 --- a/configure.ac +++ b/configure.ac @@ -3061,8 +3061,7 @@ AC_SUBST(EXTOBJS) : ${LIBPATHENV=DYLD_FALLBACK_LIBRARY_PATH} : ${PRELOADENV=DYLD_INSERT_LIBRARIES} AS_IF([test x"$enable_shared" = xyes], [ - # Resolve symbols from libruby.dylib when --enable-shared - EXTDLDFLAGS='$(LIBRUBYARG_SHARED)' + # Resolve symbols from libruby.dylib in $(LIBS) when --enable-shared ], [test "x$EXTSTATIC" = x], [ # When building exts as bundles, a mach-o bundle needs to know its loader # program to bind symbols from the ruby executable From 8c447cffe441e68d73d6d6b1235b574439c34546 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Wed, 16 Aug 2023 21:31:54 +0900 Subject: [PATCH 149/158] Lrama v0.5.4 --- tool/lrama/lib/lrama.rb | 2 + tool/lrama/lib/lrama/command.rb | 6 +- tool/lrama/lib/lrama/counterexamples.rb | 285 ++++++++++++++++++ .../lib/lrama/counterexamples/derivation.rb | 63 ++++ .../lib/lrama/counterexamples/example.rb | 124 ++++++++ tool/lrama/lib/lrama/counterexamples/path.rb | 69 +++++ .../lib/lrama/counterexamples/state_item.rb | 6 + .../lrama/lib/lrama/counterexamples/triple.rb | 21 ++ tool/lrama/lib/lrama/digraph.rb | 5 +- tool/lrama/lib/lrama/grammar.rb | 45 ++- tool/lrama/lib/lrama/grammar/auxiliary.rb | 7 + tool/lrama/lib/lrama/grammar/rule.rb | 6 + tool/lrama/lib/lrama/grammar/symbol.rb | 15 +- tool/lrama/lib/lrama/lexer/token.rb | 5 +- tool/lrama/lib/lrama/lexer/token/type.rb | 8 + tool/lrama/lib/lrama/output.rb | 2 +- tool/lrama/lib/lrama/parser.rb | 1 + tool/lrama/lib/lrama/parser/token_scanner.rb | 9 +- tool/lrama/lib/lrama/state.rb | 14 +- .../lib/lrama/state/reduce_reduce_conflict.rb | 9 + .../lib/lrama/state/shift_reduce_conflict.rb | 9 + tool/lrama/lib/lrama/states.rb | 53 ++-- tool/lrama/lib/lrama/states/item.rb | 40 ++- tool/lrama/lib/lrama/states_reporter.rb | 31 +- tool/lrama/lib/lrama/type.rb | 4 + tool/lrama/lib/lrama/version.rb | 2 +- tool/lrama/template/bison/yacc.c | 198 ++++++------ 27 files changed, 871 insertions(+), 168 deletions(-) create mode 100644 tool/lrama/lib/lrama/counterexamples.rb create mode 100644 tool/lrama/lib/lrama/counterexamples/derivation.rb create mode 100644 tool/lrama/lib/lrama/counterexamples/example.rb create mode 100644 tool/lrama/lib/lrama/counterexamples/path.rb create mode 100644 tool/lrama/lib/lrama/counterexamples/state_item.rb create mode 100644 tool/lrama/lib/lrama/counterexamples/triple.rb create mode 100644 tool/lrama/lib/lrama/grammar/auxiliary.rb create mode 100644 tool/lrama/lib/lrama/lexer/token/type.rb create mode 100644 tool/lrama/lib/lrama/state/reduce_reduce_conflict.rb create mode 100644 tool/lrama/lib/lrama/state/shift_reduce_conflict.rb create mode 100644 tool/lrama/lib/lrama/type.rb diff --git a/tool/lrama/lib/lrama.rb b/tool/lrama/lib/lrama.rb index 19f579c3306bf6..12e635d8b6ae73 100644 --- a/tool/lrama/lib/lrama.rb +++ b/tool/lrama/lib/lrama.rb @@ -1,6 +1,7 @@ require "lrama/bitmap" require "lrama/command" require "lrama/context" +require "lrama/counterexamples" require "lrama/digraph" require "lrama/grammar" require "lrama/lexer" @@ -10,5 +11,6 @@ require "lrama/state" require "lrama/states" require "lrama/states_reporter" +require "lrama/type" require "lrama/version" require "lrama/warning" diff --git a/tool/lrama/lib/lrama/command.rb b/tool/lrama/lib/lrama/command.rb index 2d37639d69dac8..9fceb55fe05568 100644 --- a/tool/lrama/lib/lrama/command.rb +++ b/tool/lrama/lib/lrama/command.rb @@ -67,7 +67,7 @@ def validate_report(report) bison_list = %w[states itemsets lookaheads solved counterexamples cex all none] others = %w[verbose] list = bison_list + others - not_supported = %w[counterexamples cex none] + not_supported = %w[cex none] h = { grammar: true } report.each do |r| @@ -121,13 +121,13 @@ def parse_option # Output Files: opt.on('-h', '--header=[FILE]') {|v| @header = true; @header_file = v } opt.on('-d') { @header = true } - opt.on('-r', '--report=THINGS') {|v| @report = v.split(',') } + opt.on('-r', '--report=THINGS', Array) {|v| @report = v } opt.on('--report-file=FILE') {|v| @report_file = v } opt.on('-v') { } # Do nothing opt.on('-o', '--output=FILE') {|v| @outfile = v } # Hidden - opt.on('--trace=THINGS') {|v| @trace = v.split(',') } + opt.on('--trace=THINGS', Array) {|v| @trace = v } # Error Recovery opt.on('-e') {|v| @error_recovery = true } diff --git a/tool/lrama/lib/lrama/counterexamples.rb b/tool/lrama/lib/lrama/counterexamples.rb new file mode 100644 index 00000000000000..a5d62a0c7c3321 --- /dev/null +++ b/tool/lrama/lib/lrama/counterexamples.rb @@ -0,0 +1,285 @@ +require "set" + +require "lrama/counterexamples/derivation" +require "lrama/counterexamples/example" +require "lrama/counterexamples/path" +require "lrama/counterexamples/state_item" +require "lrama/counterexamples/triple" + +module Lrama + # See: https://www.cs.cornell.edu/andru/papers/cupex/cupex.pdf + # 4. Constructing Nonunifying Counterexamples + class Counterexamples + attr_reader :transitions, :productions + + def initialize(states) + @states = states + setup_transitions + setup_productions + end + + def to_s + "#" + end + alias :inspect :to_s + + def compute(conflict_state) + conflict_state.conflicts.flat_map do |conflict| + case conflict.type + when :shift_reduce + shift_reduce_example(conflict_state, conflict) + when :reduce_reduce + reduce_reduce_examples(conflict_state, conflict) + end + end.compact + end + + private + + def setup_transitions + # Hash [StateItem, Symbol] => StateItem + @transitions = {} + # Hash [StateItem, Symbol] => Set(StateItem) + @reverse_transitions = {} + + @states.states.each do |src_state| + trans = {} + + src_state.transitions.each do |shift, next_state| + trans[shift.next_sym] = next_state + end + + src_state.items.each do |src_item| + next if src_item.end_of_rule? + sym = src_item.next_sym + dest_state = trans[sym] + + dest_state.kernels.each do |dest_item| + next unless (src_item.rule == dest_item.rule) && (src_item.position + 1 == dest_item.position) + src_state_item = StateItem.new(src_state, src_item) + dest_state_item = StateItem.new(dest_state, dest_item) + + @transitions[[src_state_item, sym]] = dest_state_item + + key = [dest_state_item, sym] + @reverse_transitions[key] ||= Set.new + @reverse_transitions[key] << src_state_item + end + end + end + end + + def setup_productions + # Hash [StateItem] => Set(Item) + @productions = {} + # Hash [State, Symbol] => Set(Item). Symbol is nterm + @reverse_productions = {} + + @states.states.each do |state| + # LHS => Set(Item) + h = {} + + state.closure.each do |item| + sym = item.lhs + + h[sym] ||= Set.new + h[sym] << item + end + + state.items.each do |item| + next if item.end_of_rule? + next if item.next_sym.term? + + sym = item.next_sym + state_item = StateItem.new(state, item) + key = [state, sym] + + @productions[state_item] = h[sym] + + @reverse_productions[key] ||= Set.new + @reverse_productions[key] << item + end + end + end + + def shift_reduce_example(conflict_state, conflict) + conflict_symbol = conflict.symbols.first + shift_conflict_item = conflict_state.items.find { |item| item.next_sym == conflict_symbol } + path2 = shortest_path(conflict_state, conflict.reduce.item, conflict_symbol) + path1 = find_shift_conflict_shortest_path(path2, conflict_state, shift_conflict_item) + + Example.new(path1, path2, conflict, conflict_symbol, self) + end + + def reduce_reduce_examples(conflict_state, conflict) + conflict_symbol = conflict.symbols.first + path1 = shortest_path(conflict_state, conflict.reduce1.item, conflict_symbol) + path2 = shortest_path(conflict_state, conflict.reduce2.item, conflict_symbol) + + Example.new(path1, path2, conflict, conflict_symbol, self) + end + + def find_shift_conflict_shortest_path(reduce_path, conflict_state, conflict_item) + state_items = find_shift_conflict_shortest_state_items(reduce_path, conflict_state, conflict_item) + build_paths_from_state_items(state_items) + end + + def find_shift_conflict_shortest_state_items(reduce_path, conflict_state, conflict_item) + target_state_item = StateItem.new(conflict_state, conflict_item) + result = [target_state_item] + reversed_reduce_path = reduce_path.to_a.reverse + # Index for state_item + i = 0 + + while (path = reversed_reduce_path[i]) + # Index for prev_state_item + j = i + 1 + _j = j + + while (prev_path = reversed_reduce_path[j]) + if prev_path.production? + j += 1 + else + break + end + end + + state_item = path.to + prev_state_item = prev_path&.to + + if target_state_item == state_item || target_state_item.item.start_item? + result.concat(reversed_reduce_path[_j..-1].map(&:to)) + break + end + + if target_state_item.item.beginning_of_rule? + queue = [] + queue << [target_state_item] + + # Find reverse production + while (sis = queue.shift) + si = sis.last + + # Reach to start state + if si.item.start_item? + sis.shift + result.concat(sis) + target_state_item = si + break + end + + if !si.item.beginning_of_rule? + key = [si, si.item.previous_sym] + @reverse_transitions[key].each do |prev_target_state_item| + next if prev_target_state_item.state != prev_state_item.state + sis.shift + result.concat(sis) + result << prev_target_state_item + target_state_item = prev_target_state_item + i = j + queue.clear + break + end + else + key = [si.state, si.item.lhs] + @reverse_productions[key].each do |item| + state_item = StateItem.new(si.state, item) + queue << (sis + [state_item]) + end + end + end + else + # Find reverse transition + key = [target_state_item, target_state_item.item.previous_sym] + @reverse_transitions[key].each do |prev_target_state_item| + next if prev_target_state_item.state != prev_state_item.state + result << prev_target_state_item + target_state_item = prev_target_state_item + i = j + break + end + end + end + + result.reverse + end + + def build_paths_from_state_items(state_items) + paths = state_items.zip([nil] + state_items).map do |si, prev_si| + case + when prev_si.nil? + StartPath.new(si) + when si.item.beginning_of_rule? + ProductionPath.new(prev_si, si) + else + TransitionPath.new(prev_si, si) + end + end + + paths + end + + def shortest_path(conflict_state, conflict_reduce_item, conflict_term) + # queue: is an array of [Triple, [Path]] + queue = [] + visited = {} + start_state = @states.states.first + raise "BUG: Start state should be just one kernel." if start_state.kernels.count != 1 + + start = Triple.new(start_state, start_state.kernels.first, Set.new([@states.eof_symbol])) + + queue << [start, [StartPath.new(start.state_item)]] + + while true + triple, paths = queue.shift + + next if visited[triple] + visited[triple] = true + + # Found + if triple.state == conflict_state && triple.item == conflict_reduce_item && triple.l.include?(conflict_term) + return paths + end + + # transition + triple.state.transitions.each do |shift, next_state| + next unless triple.item.next_sym && triple.item.next_sym == shift.next_sym + next_state.kernels.each do |kernel| + next if kernel.rule != triple.item.rule + t = Triple.new(next_state, kernel, triple.l) + queue << [t, paths + [TransitionPath.new(triple.state_item, t.state_item)]] + end + end + + # production step + triple.state.closure.each do |item| + next unless triple.item.next_sym && triple.item.next_sym == item.lhs + l = follow_l(triple.item, triple.l) + t = Triple.new(triple.state, item, l) + queue << [t, paths + [ProductionPath.new(triple.state_item, t.state_item)]] + end + + break if queue.empty? + end + + return nil + end + + def follow_l(item, current_l) + # 1. follow_L (A -> X1 ... Xn-1 • Xn) = L + # 2. follow_L (A -> X1 ... Xk • Xk+1 Xk+2 ... Xn) = {Xk+2} if Xk+2 is a terminal + # 3. follow_L (A -> X1 ... Xk • Xk+1 Xk+2 ... Xn) = FIRST(Xk+2) if Xk+2 is a nonnullable nonterminal + # 4. follow_L (A -> X1 ... Xk • Xk+1 Xk+2 ... Xn) = FIRST(Xk+2) + follow_L (A -> X1 ... Xk+1 • Xk+2 ... Xn) if Xk+2 is a nullable nonterminal + case + when item.number_of_rest_symbols == 1 + current_l + when item.next_next_sym.term? + Set.new([item.next_next_sym]) + when !item.next_next_sym.nullable + item.next_next_sym.first_set + else + item.next_next_sym.first_set + follow_l(item.new_by_next_position, current_l) + end + end + end +end diff --git a/tool/lrama/lib/lrama/counterexamples/derivation.rb b/tool/lrama/lib/lrama/counterexamples/derivation.rb new file mode 100644 index 00000000000000..691e9353563aa4 --- /dev/null +++ b/tool/lrama/lib/lrama/counterexamples/derivation.rb @@ -0,0 +1,63 @@ +module Lrama + class Counterexamples + class Derivation + attr_reader :item, :left, :right + attr_writer :right + + def initialize(item, left, right = nil) + @item = item + @left = left + @right = right + end + + def to_s + "#" + end + alias :inspect :to_s + + def render_strings_for_report + result = [] + _render_for_report(self, 0, result, 0) + result.map(&:rstrip) + end + + def render_for_report + render_strings_for_report.join("\n") + end + + private + + def _render_for_report(derivation, offset, strings, index) + item = derivation.item + if strings[index] + strings[index] << " " * (offset - strings[index].length) + else + strings[index] = " " * offset + end + str = strings[index] + str << "#{item.rule_id}: #{item.symbols_before_dot.map(&:display_name).join(" ")} " + + if derivation.left + len = str.length + str << "#{item.next_sym.display_name}" + length = _render_for_report(derivation.left, len, strings, index + 1) + # I want String#ljust! + str << " " * (length - str.length) + else + str << " • #{item.symbols_after_dot.map(&:display_name).join(" ")} " + return str.length + end + + if derivation.right&.left + length = _render_for_report(derivation.right.left, str.length, strings, index + 1) + str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} " + str << " " * (length - str.length) if length > str.length + elsif item.next_next_sym + str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} " + end + + return str.length + end + end + end +end diff --git a/tool/lrama/lib/lrama/counterexamples/example.rb b/tool/lrama/lib/lrama/counterexamples/example.rb new file mode 100644 index 00000000000000..8f02d71fa45e0c --- /dev/null +++ b/tool/lrama/lib/lrama/counterexamples/example.rb @@ -0,0 +1,124 @@ +module Lrama + class Counterexamples + class Example + attr_reader :path1, :path2, :conflict, :conflict_symbol + + # path1 is shift conflict when S/R conflict + # path2 is always reduce conflict + def initialize(path1, path2, conflict, conflict_symbol, counterexamples) + @path1 = path1 + @path2 = path2 + @conflict = conflict + @conflict_symbol = conflict_symbol + @counterexamples = counterexamples + end + + def type + @conflict.type + end + + def path1_item + @path1.last.to.item + end + + def path2_item + @path2.last.to.item + end + + def derivations1 + @derivations1 ||= _derivations(path1) + end + + def derivations2 + @derivations2 ||= _derivations(path2) + end + + private + + def _derivations(paths) + derivation = nil + current = :production + lookahead_sym = paths.last.to.item.end_of_rule? ? @conflict_symbol : nil + + paths.reverse.each do |path| + item = path.to.item + + case current + when :production + case path + when StartPath + derivation = Derivation.new(item, derivation) + current = :start + when TransitionPath + derivation = Derivation.new(item, derivation) + current = :transition + when ProductionPath + derivation = Derivation.new(item, derivation) + current = :production + end + + if lookahead_sym && item.next_next_sym && item.next_next_sym.first_set.include?(lookahead_sym) + state_item = @counterexamples.transitions[[path.to, item.next_sym]] + derivation2 = find_derivation_for_symbol(state_item, lookahead_sym) + derivation.right = derivation2 + lookahead_sym = nil + end + + when :transition + case path + when StartPath + derivation = Derivation.new(item, derivation) + current = :start + when TransitionPath + # ignore + current = :transition + when ProductionPath + # ignore + current = :production + end + else + raise "BUG: Unknown #{current}" + end + + break if current == :start + end + + derivation + end + + def find_derivation_for_symbol(state_item, sym) + queue = [] + queue << [state_item] + + while (sis = queue.shift) + si = sis.last + next_sym = si.item.next_sym + + if next_sym == sym + derivation = nil + + sis.reverse.each do |si| + derivation = Derivation.new(si.item, derivation) + end + + return derivation + end + + if next_sym.nterm? && next_sym.first_set.include?(sym) + @counterexamples.productions[si].each do |next_item| + next if next_item.empty_rule? + next_si = StateItem.new(si.state, next_item) + next if sis.include?(next_si) + queue << (sis + [next_si]) + end + + if next_sym.nullable + next_si = @counterexamples.transitions[[si, next_sym]] + queue << (sis + [next_si]) + end + end + end + end + end + end +end diff --git a/tool/lrama/lib/lrama/counterexamples/path.rb b/tool/lrama/lib/lrama/counterexamples/path.rb new file mode 100644 index 00000000000000..a4caecd765b14c --- /dev/null +++ b/tool/lrama/lib/lrama/counterexamples/path.rb @@ -0,0 +1,69 @@ +module Lrama + class Counterexamples + class Path + def initialize(from_state_item, to_state_item) + @from_state_item = from_state_item + @to_state_item = to_state_item + end + + def from + @from_state_item + end + + def to + @to_state_item + end + + def to_s + "#" + end + alias :inspect :to_s + end + + class StartPath < Path + def initialize(to_state_item) + super nil, to_state_item + end + + def type + :start + end + + def transition? + false + end + + def production? + false + end + end + + class TransitionPath < Path + def type + :transition + end + + def transition? + true + end + + def production? + false + end + end + + class ProductionPath < Path + def type + :production + end + + def transition? + false + end + + def production? + true + end + end + end +end diff --git a/tool/lrama/lib/lrama/counterexamples/state_item.rb b/tool/lrama/lib/lrama/counterexamples/state_item.rb new file mode 100644 index 00000000000000..930ff4a5f86493 --- /dev/null +++ b/tool/lrama/lib/lrama/counterexamples/state_item.rb @@ -0,0 +1,6 @@ +module Lrama + class Counterexamples + class StateItem < Struct.new(:state, :item) + end + end +end diff --git a/tool/lrama/lib/lrama/counterexamples/triple.rb b/tool/lrama/lib/lrama/counterexamples/triple.rb new file mode 100644 index 00000000000000..e802beccf4cffc --- /dev/null +++ b/tool/lrama/lib/lrama/counterexamples/triple.rb @@ -0,0 +1,21 @@ +module Lrama + class Counterexamples + # s: state + # itm: item within s + # l: precise lookahead set + class Triple < Struct.new(:s, :itm, :l) + alias :state :s + alias :item :itm + alias :precise_lookahead_set :l + + def state_item + StateItem.new(state, item) + end + + def inspect + "#{state.inspect}. #{item.display_name}. #{l.map(&:id).map(&:s_value)}" + end + alias :to_s :inspect + end + end +end diff --git a/tool/lrama/lib/lrama/digraph.rb b/tool/lrama/lib/lrama/digraph.rb index 28f26781b151b7..c48b3f40413a2c 100644 --- a/tool/lrama/lib/lrama/digraph.rb +++ b/tool/lrama/lib/lrama/digraph.rb @@ -33,7 +33,7 @@ def traverse(x) @h[x] = d @result[x] = @base_function[x] # F x = F' x - @relation[x] && @relation[x].each do |y| + @relation[x]&.each do |y| traverse(y) if @h[y] == 0 @h[x] = [@h[x], @h[y]].min @result[x] |= @result[y] # F x = F x + F y @@ -43,9 +43,8 @@ def traverse(x) while true do z = @stack.pop @h[z] = Float::INFINITY - @result[z] = @result[x] # F (Top of S) = F x - break if z == x + @result[z] = @result[x] # F (Top of S) = F x end end end diff --git a/tool/lrama/lib/lrama/grammar.rb b/tool/lrama/lib/lrama/grammar.rb index a4f98ecc834371..25f1a49170cd9c 100644 --- a/tool/lrama/lib/lrama/grammar.rb +++ b/tool/lrama/lib/lrama/grammar.rb @@ -1,3 +1,4 @@ +require "lrama/grammar/auxiliary" require "lrama/grammar/code" require "lrama/grammar/error_token" require "lrama/grammar/precedence" @@ -7,16 +8,13 @@ require "lrama/grammar/symbol" require "lrama/grammar/union" require "lrama/lexer" +require "lrama/type" module Lrama - Type = Struct.new(:id, :tag, keyword_init: true) Token = Lrama::Lexer::Token # Grammar is the result of parsing an input grammar file class Grammar - # Grammar file information not used by States but by Output - Aux = Struct.new(:prologue_first_lineno, :prologue, :epilogue_first_lineno, :epilogue, keyword_init: true) - attr_reader :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol, :aux attr_accessor :union, :expect, :printers, :error_tokens, @@ -38,7 +36,7 @@ def initialize @error_symbol = nil @undef_symbol = nil @accept_symbol = nil - @aux = Aux.new + @aux = Auxiliary.new append_special_symbols end @@ -48,7 +46,7 @@ def add_printer(ident_or_tags:, code:, lineno:) end def add_error_token(ident_or_tags:, code:, lineno:) - @error_tokens << ErrorToken.new(ident_or_tags, code, lineno) + @error_tokens << ErrorToken.new(ident_or_tags: ident_or_tags, code: code, lineno: lineno) end def add_term(id:, alias_name: nil, tag: nil, token_id: nil, replace: false) @@ -215,6 +213,41 @@ def compute_nullable end end + def compute_first_set + terms.each do |term| + term.first_set = Set.new([term]).freeze + term.first_set_bitmap = Lrama::Bitmap.from_array([term.number]) + end + + nterms.each do |nterm| + nterm.first_set = Set.new([]).freeze + nterm.first_set_bitmap = Lrama::Bitmap.from_array([]) + end + + while true do + changed = false + + @rules.each do |rule| + rule.rhs.each do |r| + if rule.lhs.first_set_bitmap | r.first_set_bitmap != rule.lhs.first_set_bitmap + changed = true + rule.lhs.first_set_bitmap = rule.lhs.first_set_bitmap | r.first_set_bitmap + end + + break unless r.nullable + end + end + + break unless changed + end + + nterms.each do |nterm| + nterm.first_set = Lrama::Bitmap.to_array(nterm.first_set_bitmap).map do |number| + find_symbol_by_number!(number) + end.to_set + end + end + def find_symbol_by_s_value(s_value) @symbols.find do |sym| sym.id.s_value == s_value diff --git a/tool/lrama/lib/lrama/grammar/auxiliary.rb b/tool/lrama/lib/lrama/grammar/auxiliary.rb new file mode 100644 index 00000000000000..933574b0f63733 --- /dev/null +++ b/tool/lrama/lib/lrama/grammar/auxiliary.rb @@ -0,0 +1,7 @@ +module Lrama + class Grammar + # Grammar file information not used by States but by Output + class Auxiliary < Struct.new(:prologue_first_lineno, :prologue, :epilogue_first_lineno, :epilogue, keyword_init: true) + end + end +end diff --git a/tool/lrama/lib/lrama/grammar/rule.rb b/tool/lrama/lib/lrama/grammar/rule.rb index 7ed5b3312c4149..c559388b6273ce 100644 --- a/tool/lrama/lib/lrama/grammar/rule.rb +++ b/tool/lrama/lib/lrama/grammar/rule.rb @@ -17,6 +17,12 @@ def as_comment "#{l}: #{r}" end + # opt_nl: ε <-- empty_rule + # | '\n' <-- not empty_rule + def empty_rule? + rhs.empty? + end + def precedence precedence_sym&.precedence end diff --git a/tool/lrama/lib/lrama/grammar/symbol.rb b/tool/lrama/lib/lrama/grammar/symbol.rb index 28916eb54f9fdb..9df1c2f636daf1 100644 --- a/tool/lrama/lib/lrama/grammar/symbol.rb +++ b/tool/lrama/lib/lrama/grammar/symbol.rb @@ -7,6 +7,7 @@ module Lrama class Grammar class Symbol < Struct.new(:id, :alias_name, :number, :tag, :term, :token_id, :nullable, :precedence, :printer, :error_token, keyword_init: true) + attr_accessor :first_set, :first_set_bitmap attr_writer :eof_symbol, :error_symbol, :undef_symbol, :accept_symbol def term? @@ -34,11 +35,7 @@ def accept_symbol? end def display_name - if alias_name - alias_name - else - id.s_value - end + alias_name || id.s_value end # name for yysymbol_kind_t @@ -51,11 +48,7 @@ def enum_name when eof_symbol? name = "YYEOF" when term? && id.type == Token::Char - if alias_name - name = number.to_s + alias_name - else - name = number.to_s + id.s_value - end + name = number.to_s + display_name when term? && id.type == Token::Ident name = id.s_value when nterm? && (id.s_value.include?("$") || id.s_value.include?("@")) @@ -66,7 +59,7 @@ def enum_name raise "Unexpected #{self}" end - "YYSYMBOL_" + name.gsub(/[^a-zA-Z_0-9]+/, "_") + "YYSYMBOL_" + name.gsub(/\W+/, "_") end # comment for yysymbol_kind_t diff --git a/tool/lrama/lib/lrama/lexer/token.rb b/tool/lrama/lib/lrama/lexer/token.rb index 29ce48b2fa0f44..aa49bfe47d7471 100644 --- a/tool/lrama/lib/lrama/lexer/token.rb +++ b/tool/lrama/lib/lrama/lexer/token.rb @@ -1,7 +1,8 @@ +require 'lrama/lexer/token/type' + module Lrama class Lexer - class Token < Struct.new(:type, :s_value, :alias, keyword_init: true) - Type = Struct.new(:id, :name, keyword_init: true) + class Token attr_accessor :line, :column, :referred # For User_code diff --git a/tool/lrama/lib/lrama/lexer/token/type.rb b/tool/lrama/lib/lrama/lexer/token/type.rb new file mode 100644 index 00000000000000..d58a56f40bcfbc --- /dev/null +++ b/tool/lrama/lib/lrama/lexer/token/type.rb @@ -0,0 +1,8 @@ +module Lrama + class Lexer + class Token < Struct.new(:type, :s_value, :alias, keyword_init: true) + class Type < Struct.new(:id, :name, keyword_init: true) + end + end + end +end diff --git a/tool/lrama/lib/lrama/output.rb b/tool/lrama/lib/lrama/output.rb index dd71814a1111c4..757d16e25ae3ff 100644 --- a/tool/lrama/lib/lrama/output.rb +++ b/tool/lrama/lib/lrama/output.rb @@ -252,7 +252,7 @@ def user_args end def extract_param_name(param) - /\A(.)+([a-zA-Z0-9_]+)\z/.match(param)[2] + /\A(\W*)([a-zA-Z0-9_]+)\z/.match(param.split.last)[2] end def parse_param_name diff --git a/tool/lrama/lib/lrama/parser.rb b/tool/lrama/lib/lrama/parser.rb index 4faa402d1b3c95..a12c8bbb34e33f 100644 --- a/tool/lrama/lib/lrama/parser.rb +++ b/tool/lrama/lib/lrama/parser.rb @@ -22,6 +22,7 @@ def parse process_epilogue(grammar, lexer) grammar.prepare grammar.compute_nullable + grammar.compute_first_set grammar.validate! grammar diff --git a/tool/lrama/lib/lrama/parser/token_scanner.rb b/tool/lrama/lib/lrama/parser/token_scanner.rb index 1ff67b30a3e385..992b5742d3b857 100644 --- a/tool/lrama/lib/lrama/parser/token_scanner.rb +++ b/tool/lrama/lib/lrama/parser/token_scanner.rb @@ -11,7 +11,7 @@ def current_token end def current_type - current_token && current_token.type + current_token&.type end def previous_token @@ -26,9 +26,7 @@ def next def consume(*token_types) if token_types.include?(current_type) - token = current_token - self.next - return token + return self.next end return nil @@ -42,8 +40,7 @@ def consume_multi(*token_types) a = [] while token_types.include?(current_type) - a << current_token - self.next + a << self.next end raise "No token is consumed. #{token_types}" if a.empty? diff --git a/tool/lrama/lib/lrama/state.rb b/tool/lrama/lib/lrama/state.rb index b868035e1a7c58..6632bafeccb43e 100644 --- a/tool/lrama/lib/lrama/state.rb +++ b/tool/lrama/lib/lrama/state.rb @@ -1,11 +1,11 @@ require "lrama/state/reduce" -require "lrama/state/shift" +require "lrama/state/reduce_reduce_conflict" require "lrama/state/resolved_conflict" +require "lrama/state/shift" +require "lrama/state/shift_reduce_conflict" module Lrama class State - Conflict = Struct.new(:symbols, :reduce, :type, keyword_init: true) - attr_reader :id, :accessing_symbol, :kernels, :conflicts, :resolved_conflicts, :default_reduction_rule, :closure, :items attr_accessor :shifts, :reduces @@ -101,6 +101,10 @@ def term_transitions @term_transitions end + def transitions + term_transitions + nterm_transitions + end + def selected_term_transitions term_transitions.select do |shift, next_state| !shift.not_selected @@ -144,6 +148,10 @@ def default_reduction_rule=(default_reduction_rule) end end + def has_conflicts? + !@conflicts.empty? + end + def sr_conflicts @conflicts.select do |conflict| conflict.type == :shift_reduce diff --git a/tool/lrama/lib/lrama/state/reduce_reduce_conflict.rb b/tool/lrama/lib/lrama/state/reduce_reduce_conflict.rb new file mode 100644 index 00000000000000..0a0e4dc20ae7f3 --- /dev/null +++ b/tool/lrama/lib/lrama/state/reduce_reduce_conflict.rb @@ -0,0 +1,9 @@ +module Lrama + class State + class ReduceReduceConflict < Struct.new(:symbols, :reduce1, :reduce2, keyword_init: true) + def type + :reduce_reduce + end + end + end +end diff --git a/tool/lrama/lib/lrama/state/shift_reduce_conflict.rb b/tool/lrama/lib/lrama/state/shift_reduce_conflict.rb new file mode 100644 index 00000000000000..f80bd5f352453f --- /dev/null +++ b/tool/lrama/lib/lrama/state/shift_reduce_conflict.rb @@ -0,0 +1,9 @@ +module Lrama + class State + class ShiftReduceConflict < Struct.new(:symbols, :shift, :reduce, keyword_init: true) + def type + :shift_reduce + end + end + end +end diff --git a/tool/lrama/lib/lrama/states.rb b/tool/lrama/lib/lrama/states.rb index cf26416a3780b1..d27c5411ea9828 100644 --- a/tool/lrama/lib/lrama/states.rb +++ b/tool/lrama/lib/lrama/states.rb @@ -102,43 +102,27 @@ def states_count end def direct_read_sets - h = {} - - @direct_read_sets.each do |k, v| - h[k] = bitmap_to_terms(v) + @direct_read_sets.transform_values do |v| + bitmap_to_terms(v) end - - return h end def read_sets - h = {} - - @read_sets.each do |k, v| - h[k] = bitmap_to_terms(v) + @read_sets.transform_values do |v| + bitmap_to_terms(v) end - - return h end def follow_sets - h = {} - - @follow_sets.each do |k, v| - h[k] = bitmap_to_terms(v) + @follow_sets.transform_values do |v| + bitmap_to_terms(v) end - - return h end def la - h = {} - - @la.each do |k, v| - h[k] = bitmap_to_terms(v) + @la.transform_values do |v| + bitmap_to_terms(v) end - - return h end private @@ -452,7 +436,7 @@ def compute_shift_reduce_conflicts # Can resolve only when both have prec unless shift_prec && reduce_prec - state.conflicts << State::Conflict.new(symbols: [sym], reduce: reduce, type: :shift_reduce) + state.conflicts << State::ShiftReduceConflict.new(symbols: [sym], shift: shift, reduce: reduce) next end @@ -501,16 +485,21 @@ def compute_shift_reduce_conflicts def compute_reduce_reduce_conflicts states.each do |state| - a = [] + count = state.reduces.count - state.reduces.each do |reduce| - next if reduce.look_ahead.nil? + for i in 0...count do + reduce1 = state.reduces[i] + next if reduce1.look_ahead.nil? - intersection = a & reduce.look_ahead - a += reduce.look_ahead + for j in (i+1)...count do + reduce2 = state.reduces[j] + next if reduce2.look_ahead.nil? - if !intersection.empty? - state.conflicts << State::Conflict.new(symbols: intersection.dup, reduce: reduce, type: :reduce_reduce) + intersection = reduce1.look_ahead & reduce2.look_ahead + + if !intersection.empty? + state.conflicts << State::ReduceReduceConflict.new(symbols: intersection, reduce1: reduce1, reduce2: reduce2) + end end end end diff --git a/tool/lrama/lib/lrama/states/item.rb b/tool/lrama/lib/lrama/states/item.rb index 5c3696cc7b0d04..823ccc72e1b4cf 100644 --- a/tool/lrama/lib/lrama/states/item.rb +++ b/tool/lrama/lib/lrama/states/item.rb @@ -12,20 +12,56 @@ def rule_id rule.id end + def empty_rule? + rule.empty_rule? + end + + def number_of_rest_symbols + rule.rhs.count - position + end + + def lhs + rule.lhs + end + def next_sym rule.rhs[position] end + def next_next_sym + rule.rhs[position + 1] + end + + def previous_sym + rule.rhs[position - 1] + end + def end_of_rule? rule.rhs.count == position end + def beginning_of_rule? + position == 0 + end + + def start_item? + rule.id == 0 && position == 0 + end + def new_by_next_position Item.new(rule: rule, position: position + 1) end - def previous_sym - rule.rhs[position - 1] + def symbols_before_dot + rule.rhs[0...position] + end + + def symbols_after_dot + rule.rhs[position..-1] + end + + def to_s + "#{lhs.id.s_value}: #{display_name}" end def display_name diff --git a/tool/lrama/lib/lrama/states_reporter.rb b/tool/lrama/lib/lrama/states_reporter.rb index d3dbe6b1b413c4..0d805829eb13f4 100644 --- a/tool/lrama/lib/lrama/states_reporter.rb +++ b/tool/lrama/lib/lrama/states_reporter.rb @@ -14,13 +14,13 @@ def report(io, **options) private - def _report(io, grammar: false, states: false, itemsets: false, lookaheads: false, solved: false, verbose: false) + def _report(io, grammar: false, states: false, itemsets: false, lookaheads: false, solved: false, counterexamples: false, verbose: false) # TODO: Unused terms # TODO: Unused rules report_conflicts(io) report_grammar(io) if grammar - report_states(io, itemsets, lookaheads, solved, verbose) + report_states(io, itemsets, lookaheads, solved, counterexamples, verbose) end def report_conflicts(io) @@ -71,7 +71,11 @@ def report_grammar(io) io << "\n\n" end - def report_states(io, itemsets, lookaheads, solved, verbose) + def report_states(io, itemsets, lookaheads, solved, counterexamples, verbose) + if counterexamples + cex = Counterexamples.new(@states) + end + @states.states.each do |state| # Report State io << "State #{state.id}\n\n" @@ -194,6 +198,27 @@ def report_states(io, itemsets, lookaheads, solved, verbose) io << "\n" if !state.resolved_conflicts.empty? end + if counterexamples && state.has_conflicts? + # Report counterexamples + examples = cex.compute(state) + examples.each do |example| + label0 = example.type == :shift_reduce ? "shift/reduce" : "reduce/reduce" + label1 = example.type == :shift_reduce ? "Shift derivation" : "First Reduce derivation" + label2 = example.type == :shift_reduce ? "Reduce derivation" : "Second Reduce derivation" + + io << " #{label0} conflict on token #{example.conflict_symbol.id.s_value}:\n" + io << " #{example.path1_item.to_s}\n" + io << " #{example.path2_item.to_s}\n" + io << " #{label1}\n" + example.derivations1.render_strings_for_report.each do |str| + io << " #{str}\n" + end + io << " #{label2}\n" + example.derivations2.render_strings_for_report.each do |str| + io << " #{str}\n" + end + end + end if verbose # Report direct_read_sets diff --git a/tool/lrama/lib/lrama/type.rb b/tool/lrama/lib/lrama/type.rb new file mode 100644 index 00000000000000..fe5ff7405821ed --- /dev/null +++ b/tool/lrama/lib/lrama/type.rb @@ -0,0 +1,4 @@ +module Lrama + class Type < Struct.new(:id, :tag, keyword_init: true) + end +end diff --git a/tool/lrama/lib/lrama/version.rb b/tool/lrama/lib/lrama/version.rb index 54eea75bfda222..3f2eb3b9d4f5a3 100644 --- a/tool/lrama/lib/lrama/version.rb +++ b/tool/lrama/lib/lrama/version.rb @@ -1,3 +1,3 @@ module Lrama - VERSION = "0.5.3".freeze + VERSION = "0.5.4".freeze end diff --git a/tool/lrama/template/bison/yacc.c b/tool/lrama/template/bison/yacc.c index 61d23d506b5137..8f57984ef33023 100644 --- a/tool/lrama/template/bison/yacc.c +++ b/tool/lrama/template/bison/yacc.c @@ -1220,26 +1220,30 @@ yydestruct (const char *yymsg, <%- if output.error_recovery -%> #ifndef YYMAXREPAIR -# define YYMAXREPAIR 3 +# define YYMAXREPAIR(<%= output.parse_param_name %>) (3) #endif -enum repair_type { +#ifndef YYERROR_RECOVERY_ENABLED +# define YYERROR_RECOVERY_ENABLED(<%= output.parse_param_name %>) (1) +#endif + +enum yy_repair_type { insert, delete, shift, }; -struct repair { - enum repair_type type; +struct yy_repair { + enum yy_repair_type type; yysymbol_kind_t term; }; -typedef struct repair repair; +typedef struct yy_repair yy_repair; -struct repairs { +struct yy_repairs { /* For debug */ int id; /* For breadth-first traversing */ - struct repairs *next; + struct yy_repairs *next; YYPTRDIFF_T stack_length; /* Bottom of states */ yy_state_t *states; @@ -1248,10 +1252,10 @@ struct repairs { /* repair length */ int repair_length; /* */ - struct repairs *prev_repair; - struct repair repair; + struct yy_repairs *prev_repair; + struct yy_repair repair; }; -typedef struct repairs repairs; +typedef struct yy_repairs yy_repairs; struct yy_term { yysymbol_kind_t kind; @@ -1260,12 +1264,12 @@ struct yy_term { }; typedef struct yy_term yy_term; -struct repair_terms { +struct yy_repair_terms { int id; int length; yy_term terms[]; }; -typedef struct repair_terms repair_terms; +typedef struct yy_repair_terms yy_repair_terms; static void yy_error_token_initialize (yysymbol_kind_t yykind, YYSTYPE * const yyvaluep, YYLTYPE * const yylocationp<%= output.user_formals %>) @@ -1280,11 +1284,11 @@ switch (yykind) YY_IGNORE_MAYBE_UNINITIALIZED_END } -static repair_terms * -yy_create_repair_terms(repairs *reps) +static yy_repair_terms * +yy_create_repair_terms(yy_repairs *reps<%= output.user_formals %>) { - repairs *r = reps; - repair_terms *rep_terms; + yy_repairs *r = reps; + yy_repair_terms *rep_terms; int count = 0; while (r->prev_repair) @@ -1293,7 +1297,7 @@ yy_create_repair_terms(repairs *reps) r = r->prev_repair; } - rep_terms = (repair_terms *) malloc (sizeof (repair_terms) + sizeof (yy_term) * count); + rep_terms = (yy_repair_terms *) YYMALLOC (sizeof (yy_repair_terms) + sizeof (yy_term) * count); rep_terms->id = reps->id; rep_terms->length = count; @@ -1309,46 +1313,46 @@ yy_create_repair_terms(repairs *reps) } static void -yy_print_repairs(repairs *reps) +yy_print_repairs(yy_repairs *reps<%= output.user_formals %>) { - repairs *r = reps; + yy_repairs *r = reps; - fprintf (stderr, + YYDPRINTF ((stderr, "id: %d, repair_length: %d, repair_state: %d, prev_repair_id: %d\n", - reps->id, reps->repair_length, *reps->state, reps->prev_repair->id); + reps->id, reps->repair_length, *reps->state, reps->prev_repair->id)); while (r->prev_repair) { - fprintf (stderr, "%s ", yysymbol_name (r->repair.term)); + YYDPRINTF ((stderr, "%s ", yysymbol_name (r->repair.term))); r = r->prev_repair; } - fprintf (stderr, "\n"); + YYDPRINTF ((stderr, "\n")); } static void -yy_print_repair_terms(repair_terms *rep_terms) +yy_print_repair_terms(yy_repair_terms *rep_terms<%= output.user_formals %>) { for (int i = 0; i < rep_terms->length; i++) - fprintf (stderr, "%s ", yysymbol_name (rep_terms->terms[i].kind)); + YYDPRINTF ((stderr, "%s ", yysymbol_name (rep_terms->terms[i].kind))); - fprintf (stderr, "\n"); + YYDPRINTF ((stderr, "\n")); } static void -yy_free_repairs(repairs *reps) +yy_free_repairs(yy_repairs *reps<%= output.user_formals %>) { while (reps) { - repairs *r = reps; + yy_repairs *r = reps; reps = reps->next; - free (r->states); - free (r); + YYFREE (r->states); + YYFREE (r); } } static int -yy_process_repairs(repairs *reps, yysymbol_kind_t token) +yy_process_repairs(yy_repairs *reps, yysymbol_kind_t token) { int yyn; int yystate = *reps->state; @@ -1417,22 +1421,22 @@ yy_process_repairs(repairs *reps, yysymbol_kind_t token) return 0; } -static repair_terms * -yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar) +static yy_repair_terms * +yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar<%= output.user_formals %>) { yysymbol_kind_t yytoken = YYTRANSLATE (yychar); - repair_terms *rep_terms = YY_NULLPTR; + yy_repair_terms *rep_terms = YY_NULLPTR; int count = 0; - repairs *head = (repairs *) malloc (sizeof (repairs)); - repairs *current = head; - repairs *tail = head; + yy_repairs *head = (yy_repairs *) YYMALLOC (sizeof (yy_repairs)); + yy_repairs *current = head; + yy_repairs *tail = head; YYPTRDIFF_T stack_length = yyssp - yyss + 1; head->id = count; head->next = 0; head->stack_length = stack_length; - head->states = (yy_state_t *) malloc (sizeof (yy_state_t) * (stack_length)); + head->states = (yy_state_t *) YYMALLOC (sizeof (yy_state_t) * (stack_length)); head->state = head->states + (yyssp - yyss); YYCOPY (head->states, yyss, stack_length); head->repair_length = 0; @@ -1456,14 +1460,14 @@ yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar) { if (yyx != YYSYMBOL_YYerror) { - if (current->repair_length + 1 > YYMAXREPAIR) + if (current->repair_length + 1 > YYMAXREPAIR(<%= output.parse_param_name %>)) continue; - repairs *new = (repairs *) malloc (sizeof (repairs)); + yy_repairs *new = (yy_repairs *) YYMALLOC (sizeof (yy_repairs)); new->id = count; new->next = 0; new->stack_length = stack_length; - new->states = (yy_state_t *) malloc (sizeof (yy_state_t) * (stack_length)); + new->states = (yy_state_t *) YYMALLOC (sizeof (yy_state_t) * (stack_length)); new->state = new->states + (current->state - current->states); YYCOPY (new->states, current->states, current->state - current->states + 1); new->repair_length = current->repair_length + 1; @@ -1474,7 +1478,7 @@ yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar) /* Process PDA assuming next token is yyx */ if (! yy_process_repairs (new, yyx)) { - free (new); + YYFREE (new); continue; } @@ -1484,18 +1488,18 @@ yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar) if (yyx == yytoken) { - rep_terms = yy_create_repair_terms (current); - fprintf (stderr, "repair_terms found. id: %d, length: %d\n", rep_terms->id, rep_terms->length); - yy_print_repairs (current); - yy_print_repair_terms (rep_terms); + rep_terms = yy_create_repair_terms (current<%= output.user_args %>); + YYDPRINTF ((stderr, "repair_terms found. id: %d, length: %d\n", rep_terms->id, rep_terms->length)); + yy_print_repairs (current<%= output.user_args %>); + yy_print_repair_terms (rep_terms<%= output.user_args %>); goto done; } - fprintf (stderr, + YYDPRINTF ((stderr, "New repairs is enqueued. count: %d, yystate: %d, yyx: %d\n", - count, yystate, yyx); - yy_print_repairs (new); + count, yystate, yyx)); + yy_print_repairs (new<%= output.user_args %>); } } } @@ -1505,11 +1509,11 @@ yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar) done: - yy_free_repairs(head); + yy_free_repairs(head<%= output.user_args %>); if (!rep_terms) { - fprintf (stderr, "repair_terms not found\n"); + YYDPRINTF ((stderr, "repair_terms not found\n")); } return rep_terms; @@ -1586,7 +1590,7 @@ YYLTYPE yylloc = yyloc_default; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[3]; <%- if output.error_recovery -%> - repair_terms *rep_terms = 0; + yy_repair_terms *rep_terms = 0; yy_term term_backup; int rep_terms_index; int yychar_backup; @@ -1726,32 +1730,35 @@ YYLTYPE yylloc = yyloc_default; /* Not known => get a lookahead token if don't already have one. */ <%- if output.error_recovery -%> - if (yychar == YYEMPTY && rep_terms) + if (YYERROR_RECOVERY_ENABLED(<%= output.parse_param_name %>)) { - - if (rep_terms_index < rep_terms->length) - { - YYDPRINTF ((stderr, "An error recovery token is used\n")); - yy_term term = rep_terms->terms[rep_terms_index]; - yytoken = term.kind; - yylval = term.value; - yylloc = term.location; - yychar = yytranslate_inverted[yytoken]; - YY_SYMBOL_PRINT ("Next error recovery token is", yytoken, &yylval, &yylloc<%= output.user_args %>); - rep_terms_index++; - } - else + if (yychar == YYEMPTY && rep_terms) { - YYDPRINTF ((stderr, "Error recovery is completed\n")); - yytoken = term_backup.kind; - yylval = term_backup.value; - yylloc = term_backup.location; - yychar = yychar_backup; - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc<%= output.user_args %>); - - free (rep_terms); - rep_terms = 0; - yychar_backup = 0; + + if (rep_terms_index < rep_terms->length) + { + YYDPRINTF ((stderr, "An error recovery token is used\n")); + yy_term term = rep_terms->terms[rep_terms_index]; + yytoken = term.kind; + yylval = term.value; + yylloc = term.location; + yychar = yytranslate_inverted[yytoken]; + YY_SYMBOL_PRINT ("Next error recovery token is", yytoken, &yylval, &yylloc<%= output.user_args %>); + rep_terms_index++; + } + else + { + YYDPRINTF ((stderr, "Error recovery is completed\n")); + yytoken = term_backup.kind; + yylval = term_backup.value; + yylloc = term_backup.location; + yychar = yychar_backup; + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc<%= output.user_args %>); + + YYFREE (rep_terms); + rep_terms = 0; + yychar_backup = 0; + } } } <%- end -%> @@ -1980,27 +1987,28 @@ YYLTYPE yylloc = yyloc_default; `-------------------------------------------------------------*/ yyerrlab1: <%- if output.error_recovery -%> - { - rep_terms = yyrecover (yyss, yyssp, yychar); - if (rep_terms) - { - for (int i = 0; i < rep_terms->length; i++) - { - yy_term *term = &rep_terms->terms[i]; - yy_error_token_initialize (term->kind, &term->value, &term->location<%= output.user_args %>); - } + if (YYERROR_RECOVERY_ENABLED(<%= output.parse_param_name %>)) + { + rep_terms = yyrecover (yyss, yyssp, yychar<%= output.user_args %>); + if (rep_terms) + { + for (int i = 0; i < rep_terms->length; i++) + { + yy_term *term = &rep_terms->terms[i]; + yy_error_token_initialize (term->kind, &term->value, &term->location<%= output.user_args %>); + } - yychar_backup = yychar; - /* Can be packed into (the tail of) rep_terms? */ - term_backup.kind = yytoken; - term_backup.value = yylval; - term_backup.location = yylloc; - rep_terms_index = 0; - yychar = YYEMPTY; + yychar_backup = yychar; + /* Can be packed into (the tail of) rep_terms? */ + term_backup.kind = yytoken; + term_backup.value = yylval; + term_backup.location = yylloc; + rep_terms_index = 0; + yychar = YYEMPTY; - goto yybackup; - } - } + goto yybackup; + } + } <%- end -%> yyerrstatus = 3; /* Each real token shifted decrements this. */ From 7433c8f7dde9eb82b94d59c71c17b4173047e008 Mon Sep 17 00:00:00 2001 From: Manu Date: Sat, 12 Aug 2023 12:57:12 +0530 Subject: [PATCH 150/158] [rubygems/rubygems] Clarify that `bundle info` takes a gem name https://github.com/rubygems/rubygems/commit/09ef74ef73 --- lib/bundler/man/bundle-add.1 | 2 +- lib/bundler/man/bundle-binstubs.1 | 2 +- lib/bundler/man/bundle-cache.1 | 2 +- lib/bundler/man/bundle-check.1 | 2 +- lib/bundler/man/bundle-clean.1 | 2 +- lib/bundler/man/bundle-config.1 | 2 +- lib/bundler/man/bundle-console.1 | 2 +- lib/bundler/man/bundle-doctor.1 | 2 +- lib/bundler/man/bundle-exec.1 | 2 +- lib/bundler/man/bundle-gem.1 | 2 +- lib/bundler/man/bundle-help.1 | 2 +- lib/bundler/man/bundle-info.1 | 6 +++--- lib/bundler/man/bundle-info.1.ronn | 6 +++--- lib/bundler/man/bundle-init.1 | 2 +- lib/bundler/man/bundle-inject.1 | 2 +- lib/bundler/man/bundle-install.1 | 2 +- lib/bundler/man/bundle-list.1 | 2 +- lib/bundler/man/bundle-lock.1 | 2 +- lib/bundler/man/bundle-open.1 | 2 +- lib/bundler/man/bundle-outdated.1 | 2 +- lib/bundler/man/bundle-platform.1 | 2 +- lib/bundler/man/bundle-plugin.1 | 2 +- lib/bundler/man/bundle-pristine.1 | 2 +- lib/bundler/man/bundle-remove.1 | 2 +- lib/bundler/man/bundle-show.1 | 2 +- lib/bundler/man/bundle-update.1 | 2 +- lib/bundler/man/bundle-version.1 | 2 +- lib/bundler/man/bundle-viz.1 | 2 +- lib/bundler/man/bundle.1 | 2 +- lib/bundler/man/gemfile.5 | 2 +- 30 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1 index 0f2fb918b9abae..8549855b0ddded 100644 --- a/lib/bundler/man/bundle-add.1 +++ b/lib/bundler/man/bundle-add.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-ADD" "1" "July 2023" "" "" +.TH "BUNDLE\-ADD" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1 index 71255230005b3d..40c338916a1a17 100644 --- a/lib/bundler/man/bundle-binstubs.1 +++ b/lib/bundler/man/bundle-binstubs.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-BINSTUBS" "1" "July 2023" "" "" +.TH "BUNDLE\-BINSTUBS" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1 index 81e267fafb72c0..69b1e1e3dd5b08 100644 --- a/lib/bundler/man/bundle-cache.1 +++ b/lib/bundler/man/bundle-cache.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CACHE" "1" "July 2023" "" "" +.TH "BUNDLE\-CACHE" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1 index 41323c20300c81..748a37e7d19c21 100644 --- a/lib/bundler/man/bundle-check.1 +++ b/lib/bundler/man/bundle-check.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CHECK" "1" "July 2023" "" "" +.TH "BUNDLE\-CHECK" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1 index c4a3f5985cb13d..af8f13cd8996c6 100644 --- a/lib/bundler/man/bundle-clean.1 +++ b/lib/bundler/man/bundle-clean.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CLEAN" "1" "July 2023" "" "" +.TH "BUNDLE\-CLEAN" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1 index 920849a065b043..241f9ab0248ebe 100644 --- a/lib/bundler/man/bundle-config.1 +++ b/lib/bundler/man/bundle-config.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CONFIG" "1" "July 2023" "" "" +.TH "BUNDLE\-CONFIG" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1 index ae133e1a810650..24fff46cecf966 100644 --- a/lib/bundler/man/bundle-console.1 +++ b/lib/bundler/man/bundle-console.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-CONSOLE" "1" "July 2023" "" "" +.TH "BUNDLE\-CONSOLE" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1 index 3cdaa070a3e0ee..57da8216cb5b41 100644 --- a/lib/bundler/man/bundle-doctor.1 +++ b/lib/bundler/man/bundle-doctor.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-DOCTOR" "1" "July 2023" "" "" +.TH "BUNDLE\-DOCTOR" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1 index 45f908ff0f1a96..852788db7ada28 100644 --- a/lib/bundler/man/bundle-exec.1 +++ b/lib/bundler/man/bundle-exec.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-EXEC" "1" "July 2023" "" "" +.TH "BUNDLE\-EXEC" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1 index 9bf9db772b50f4..8339b727cea880 100644 --- a/lib/bundler/man/bundle-gem.1 +++ b/lib/bundler/man/bundle-gem.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-GEM" "1" "July 2023" "" "" +.TH "BUNDLE\-GEM" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1 index 9aabc10f7dfdfe..9787c2d49f55ec 100644 --- a/lib/bundler/man/bundle-help.1 +++ b/lib/bundler/man/bundle-help.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-HELP" "1" "July 2023" "" "" +.TH "BUNDLE\-HELP" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-help\fR \- Displays detailed help for each subcommand diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1 index aff307cdd6e6ce..2cced715202743 100644 --- a/lib/bundler/man/bundle-info.1 +++ b/lib/bundler/man/bundle-info.1 @@ -1,16 +1,16 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INFO" "1" "July 2023" "" "" +.TH "BUNDLE\-INFO" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle . .SH "SYNOPSIS" -\fBbundle info\fR [GEM] [\-\-path] +\fBbundle info\fR [GEM_NAME] [\-\-path] . .SH "DESCRIPTION" -Print the basic information about the provided GEM such as homepage, version, path and summary\. +Given a gem name present in your bundle, print the basic information about it such as homepage, version, path and summary\. . .SH "OPTIONS" . diff --git a/lib/bundler/man/bundle-info.1.ronn b/lib/bundler/man/bundle-info.1.ronn index 47e457aa3c8155..cecdeb564f4586 100644 --- a/lib/bundler/man/bundle-info.1.ronn +++ b/lib/bundler/man/bundle-info.1.ronn @@ -3,13 +3,13 @@ bundle-info(1) -- Show information for the given gem in your bundle ## SYNOPSIS -`bundle info` [GEM] +`bundle info` [GEM_NAME] [--path] ## DESCRIPTION -Print the basic information about the provided GEM such as homepage, version, -path and summary. +Given a gem name present in your bundle, print the basic information about it + such as homepage, version, path and summary. ## OPTIONS diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1 index 27c7e3e65aaaa8..c7a9a155b53127 100644 --- a/lib/bundler/man/bundle-init.1 +++ b/lib/bundler/man/bundle-init.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INIT" "1" "July 2023" "" "" +.TH "BUNDLE\-INIT" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1 index 6fa6a40d37bca8..9e25c290858c69 100644 --- a/lib/bundler/man/bundle-inject.1 +++ b/lib/bundler/man/bundle-inject.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INJECT" "1" "July 2023" "" "" +.TH "BUNDLE\-INJECT" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1 index 713b730d8d1382..337683af064d3e 100644 --- a/lib/bundler/man/bundle-install.1 +++ b/lib/bundler/man/bundle-install.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-INSTALL" "1" "July 2023" "" "" +.TH "BUNDLE\-INSTALL" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1 index 278f4744aa658d..1680e6007a029e 100644 --- a/lib/bundler/man/bundle-list.1 +++ b/lib/bundler/man/bundle-list.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-LIST" "1" "July 2023" "" "" +.TH "BUNDLE\-LIST" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-list\fR \- List all the gems in the bundle diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1 index ed331fada8a0c5..8722c44b3d7d0b 100644 --- a/lib/bundler/man/bundle-lock.1 +++ b/lib/bundler/man/bundle-lock.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-LOCK" "1" "July 2023" "" "" +.TH "BUNDLE\-LOCK" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1 index f821b2d9a976cd..3513f0d09baaef 100644 --- a/lib/bundler/man/bundle-open.1 +++ b/lib/bundler/man/bundle-open.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-OPEN" "1" "July 2023" "" "" +.TH "BUNDLE\-OPEN" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1 index f16eeb6763eab6..129ff00f589780 100644 --- a/lib/bundler/man/bundle-outdated.1 +++ b/lib/bundler/man/bundle-outdated.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-OUTDATED" "1" "July 2023" "" "" +.TH "BUNDLE\-OUTDATED" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-outdated\fR \- List installed gems with newer versions available diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1 index 5230749ce82565..5021c46b4c44a0 100644 --- a/lib/bundler/man/bundle-platform.1 +++ b/lib/bundler/man/bundle-platform.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-PLATFORM" "1" "July 2023" "" "" +.TH "BUNDLE\-PLATFORM" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-platform\fR \- Displays platform compatibility information diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1 index 345cb52f9cfd90..ec30e1d0fda85d 100644 --- a/lib/bundler/man/bundle-plugin.1 +++ b/lib/bundler/man/bundle-plugin.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-PLUGIN" "1" "July 2023" "" "" +.TH "BUNDLE\-PLUGIN" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-plugin\fR \- Manage Bundler plugins diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1 index fb36b3f701f73c..af81c48d2b8ae8 100644 --- a/lib/bundler/man/bundle-pristine.1 +++ b/lib/bundler/man/bundle-pristine.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-PRISTINE" "1" "July 2023" "" "" +.TH "BUNDLE\-PRISTINE" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1 index 2ea4c5a24719d7..d86cf134bdeb6f 100644 --- a/lib/bundler/man/bundle-remove.1 +++ b/lib/bundler/man/bundle-remove.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-REMOVE" "1" "July 2023" "" "" +.TH "BUNDLE\-REMOVE" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-remove\fR \- Removes gems from the Gemfile diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1 index 3bf2e401c58314..aa91176bf22be2 100644 --- a/lib/bundler/man/bundle-show.1 +++ b/lib/bundler/man/bundle-show.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-SHOW" "1" "July 2023" "" "" +.TH "BUNDLE\-SHOW" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1 index 73c85eac3ce4b3..e4e10ad23b3b41 100644 --- a/lib/bundler/man/bundle-update.1 +++ b/lib/bundler/man/bundle-update.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-UPDATE" "1" "July 2023" "" "" +.TH "BUNDLE\-UPDATE" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-update\fR \- Update your gems to the latest available versions diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1 index 3e3bd9bb2813a0..5e3ed44600646e 100644 --- a/lib/bundler/man/bundle-version.1 +++ b/lib/bundler/man/bundle-version.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-VERSION" "1" "July 2023" "" "" +.TH "BUNDLE\-VERSION" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-version\fR \- Prints Bundler version information diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1 index 49fc73421365a0..d5330ec7549748 100644 --- a/lib/bundler/man/bundle-viz.1 +++ b/lib/bundler/man/bundle-viz.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE\-VIZ" "1" "July 2023" "" "" +.TH "BUNDLE\-VIZ" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1 index 4eae9321480131..99c65a72b52a9c 100644 --- a/lib/bundler/man/bundle.1 +++ b/lib/bundler/man/bundle.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNDLE" "1" "July 2023" "" "" +.TH "BUNDLE" "1" "August 2023" "" "" . .SH "NAME" \fBbundle\fR \- Ruby Dependency Management diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5 index 2989f646299f7b..f2f9aa6f07a4a5 100644 --- a/lib/bundler/man/gemfile.5 +++ b/lib/bundler/man/gemfile.5 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "GEMFILE" "5" "July 2023" "" "" +.TH "GEMFILE" "5" "August 2023" "" "" . .SH "NAME" \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs From 30a5b94517699589f6943163cd6b92f2f6c0023f Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Thu, 17 Aug 2023 10:11:17 -0400 Subject: [PATCH 151/158] YJIT: implement side chain fallback for setlocal to avoid exiting (#8227) * YJIT: implement side chain fallback for setlocal to avoid exiting * Update yjit/src/codegen.rs Co-authored-by: Takashi Kokubun --------- Co-authored-by: Takashi Kokubun --- test/ruby/test_yjit.rb | 2 +- vm_core.h | 1 + vm_insnhelper.c | 6 +++++ yjit/bindgen/src/main.rs | 1 + yjit/src/codegen.rs | 49 +++++++++++++++++++++++++++------- yjit/src/cruby_bindings.inc.rs | 1 + 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 190073b02845ef..0207f4aaf16577 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -661,7 +661,7 @@ def jit_method def test_send_block # Setlocal_wc_0 sometimes side-exits on write barrier - assert_compiles(<<~'RUBY', result: "b:n/b:y/b:y/b:n", exits: { :setlocal_WC_0 => 0..1 }) + assert_compiles(<<~'RUBY', result: "b:n/b:y/b:y/b:n") def internal_method(&b) "b:#{block_given? ? "y" : "n"}" end diff --git a/vm_core.h b/vm_core.h index a2c7edf206273c..25629d3789491a 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1758,6 +1758,7 @@ rb_thread_t * ruby_thread_from_native(void); int ruby_thread_set_native(rb_thread_t *th); int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp); void rb_vm_rewind_cfp(rb_execution_context_t *ec, rb_control_frame_t *cfp); +void rb_vm_env_write(const VALUE *ep, int index, VALUE v); VALUE rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler); void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE exception_class, VALUE mesg); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 7ee8fd2cbfdeb6..a325d070a252db 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -505,6 +505,12 @@ vm_env_write(const VALUE *ep, int index, VALUE v) } } +void +rb_vm_env_write(const VALUE *ep, int index, VALUE v) +{ + vm_env_write(ep, index, v); +} + VALUE rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler) { diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 6b6337d541733a..baa71fc6cf3fc0 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -283,6 +283,7 @@ fn main() { .blocklist_type("rb_control_frame_struct") .opaque_type("rb_control_frame_struct") .allowlist_function("rb_vm_bh_to_procval") + .allowlist_function("rb_vm_env_write") .allowlist_function("rb_vm_ep_local_ep") .allowlist_type("vm_special_object_type") .allowlist_var("VM_ENV_DATA_INDEX_SPECVAL") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 919e1662b820c0..88c567755142c9 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1546,8 +1546,7 @@ fn gen_expandarray( let array_opnd = asm.stack_opnd(0); - // num is the number of requested values. If there aren't enough in the - // array then we're going to push on nils. + // If the array operand is nil, just push on nils if asm.ctx.get_opnd_type(array_opnd.into()) == Type::Nil { asm.stack_pop(1); // pop after using the type info // special case for a, b = nil pattern @@ -1762,6 +1761,7 @@ fn gen_getlocal_wc1( fn gen_setlocal_generic( jit: &mut JITState, asm: &mut Assembler, + ocb: &mut OutlinedCb, ep_offset: u32, level: u32, ) -> Option { @@ -1770,6 +1770,29 @@ fn gen_setlocal_generic( // Load environment pointer EP at level let ep_opnd = gen_get_ep(asm, level); + // Fallback because of write barrier + if asm.ctx.get_chain_depth() > 0 + { + // Save the PC and SP because it runs GC + jit_prepare_routine_call(jit, asm); + + // Pop the value to write from the stack + let value_opnd = asm.stack_pop(1); + + // void rb_vm_env_write(const VALUE *ep, int index, VALUE v) + let index = -(ep_offset as i64); + asm.ccall( + rb_vm_env_write as *const u8, + vec![ + ep_opnd, + index.into(), + value_opnd, + ] + ); + + return Some(KeepCompiling); + } + // Write barriers may be required when VM_ENV_FLAG_WB_REQUIRED is set, however write barriers // only affect heap objects being written. If we know an immediate value is being written we // can skip this check. @@ -1783,7 +1806,15 @@ fn gen_setlocal_generic( asm.test(flags_opnd, VM_ENV_FLAG_WB_REQUIRED.into()); // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0 - asm.jnz(Target::side_exit(Counter::setlocal_wb_required)); + assert!(asm.ctx.get_chain_depth() == 0); + jit_chain_guard( + JCC_JNZ, + jit, + asm, + ocb, + 1, + Counter::setlocal_wb_required, + ); } if level == 0 { @@ -1804,29 +1835,29 @@ fn gen_setlocal_generic( fn gen_setlocal( jit: &mut JITState, asm: &mut Assembler, - _ocb: &mut OutlinedCb, + ocb: &mut OutlinedCb, ) -> Option { let idx = jit.get_arg(0).as_u32(); let level = jit.get_arg(1).as_u32(); - gen_setlocal_generic(jit, asm, idx, level) + gen_setlocal_generic(jit, asm, ocb, idx, level) } fn gen_setlocal_wc0( jit: &mut JITState, asm: &mut Assembler, - _ocb: &mut OutlinedCb, + ocb: &mut OutlinedCb, ) -> Option { let idx = jit.get_arg(0).as_u32(); - gen_setlocal_generic(jit, asm, idx, 0) + gen_setlocal_generic(jit, asm, ocb, idx, 0) } fn gen_setlocal_wc1( jit: &mut JITState, asm: &mut Assembler, - _ocb: &mut OutlinedCb, + ocb: &mut OutlinedCb, ) -> Option { let idx = jit.get_arg(0).as_u32(); - gen_setlocal_generic(jit, asm, idx, 1) + gen_setlocal_generic(jit, asm, ocb, idx, 1) } // new hash initialized from top N values diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 1d0704073d20eb..ccf5b530d6732e 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -1166,6 +1166,7 @@ extern "C" { pub static mut rb_block_param_proxy: VALUE; pub fn rb_vm_ep_local_ep(ep: *const VALUE) -> *const VALUE; pub fn rb_iseq_path(iseq: *const rb_iseq_t) -> VALUE; + pub fn rb_vm_env_write(ep: *const VALUE, index: ::std::os::raw::c_int, v: VALUE); pub fn rb_vm_bh_to_procval(ec: *const rb_execution_context_t, block_handler: VALUE) -> VALUE; pub fn rb_vm_frame_method_entry( cfp: *const rb_control_frame_t, From 75a4767525407755a33d3b140312c00f2cababd6 Mon Sep 17 00:00:00 2001 From: Ngan Pham Date: Sat, 12 Aug 2023 19:16:20 -0700 Subject: [PATCH 152/158] [rubygems/rubygems] Add `file` option to `ruby` method in Gemfile https://github.com/rubygems/rubygems/commit/fb9354b7bf --- lib/bundler/man/gemfile.5 | 13 +++++++++++++ lib/bundler/man/gemfile.5.ronn | 5 +++++ lib/bundler/ruby_dsl.rb | 6 ++++++ spec/bundler/bundler/ruby_dsl_spec.rb | 27 ++++++++++++++++++++++++++- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5 index f2f9aa6f07a4a5..9f6094b853b026 100644 --- a/lib/bundler/man/gemfile.5 +++ b/lib/bundler/man/gemfile.5 @@ -85,6 +85,19 @@ ruby "3\.1\.2" . .IP "" 0 . +.P +If you wish to derive your Ruby version from a version file (ie \.ruby\-version), you can use the \fBfile\fR option instead\. +. +.IP "" 4 +. +.nf + +ruby file: "\.ruby\-version" +. +.fi +. +.IP "" 0 +. .SS "ENGINE" Each application \fImay\fR specify a Ruby engine\. If an engine is specified, an engine version \fImust\fR also be specified\. . diff --git a/lib/bundler/man/gemfile.5.ronn b/lib/bundler/man/gemfile.5.ronn index 69a26b76850f31..39cd18d551cfbc 100644 --- a/lib/bundler/man/gemfile.5.ronn +++ b/lib/bundler/man/gemfile.5.ronn @@ -69,6 +69,11 @@ should be the Ruby version that the engine is compatible with. ruby "3.1.2" +If you wish to derive your Ruby version from a version file (ie .ruby-version), +you can use the `file` option instead. + + ruby file: ".ruby-version" + ### ENGINE Each application _may_ specify a Ruby engine. If an engine is specified, an diff --git a/lib/bundler/ruby_dsl.rb b/lib/bundler/ruby_dsl.rb index 3b3a0583a5bc85..d054969e8d22cc 100644 --- a/lib/bundler/ruby_dsl.rb +++ b/lib/bundler/ruby_dsl.rb @@ -5,9 +5,15 @@ module RubyDsl def ruby(*ruby_version) options = ruby_version.last.is_a?(Hash) ? ruby_version.pop : {} ruby_version.flatten! + raise GemfileError, "Please define :engine_version" if options[:engine] && options[:engine_version].nil? raise GemfileError, "Please define :engine" if options[:engine_version] && options[:engine].nil? + if options[:file] + raise GemfileError, "Cannot specify version when using the file option" if ruby_version.any? + ruby_version << Bundler.read_file(options[:file]).strip + end + if options[:engine] == "ruby" && options[:engine_version] && ruby_version != Array(options[:engine_version]) raise GemfileEvalError, "ruby_version must match the :engine_version for MRI" diff --git a/spec/bundler/bundler/ruby_dsl_spec.rb b/spec/bundler/bundler/ruby_dsl_spec.rb index bc1ca98457b77a..0ba55e949f7c3d 100644 --- a/spec/bundler/bundler/ruby_dsl_spec.rb +++ b/spec/bundler/bundler/ruby_dsl_spec.rb @@ -11,6 +11,7 @@ class MockDSL let(:dsl) { MockDSL.new } let(:ruby_version) { "2.0.0" } + let(:ruby_version_arg) { ruby_version } let(:version) { "2.0.0" } let(:engine) { "jruby" } let(:engine_version) { "9000" } @@ -23,7 +24,10 @@ class MockDSL let(:invoke) do proc do - args = Array(ruby_version) + [options] + args = [] + args << Array(ruby_version_arg) if ruby_version_arg + args << options + dsl.ruby(*args) end end @@ -91,5 +95,26 @@ class MockDSL it_behaves_like "it stores the ruby version" end end + + context "with a file option" do + let(:options) { { :file => "foo" } } + let(:version) { "3.2.2" } + let(:ruby_version) { "3.2.2" } + let(:ruby_version_arg) { nil } + let(:engine_version) { version } + let(:patchlevel) { nil } + let(:engine) { "ruby" } + before { allow(Bundler).to receive(:read_file).with("foo").and_return("#{version}\n") } + + it_behaves_like "it stores the ruby version" + + context "and a version" do + let(:ruby_version_arg) { "2.0.0" } + + it "raises an error" do + expect { subject }.to raise_error(Bundler::GemfileError, "Cannot specify version when using the file option") + end + end + end end end From 81d715099c93e8764d659a04a142822b8ec514e5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 15 Aug 2023 09:18:44 -0400 Subject: [PATCH 153/158] [ruby/yarp] Treat yp_buffer_t as an opaque pointer Right now, we have to keep the buffer FFI object in sync with the definition of yp_buffer_t because we access its fields directly. If we add more fields or change the order, things will get out of sync. Instead, let's treat yp_buffer_t as an opaque pointer and access its fields through accessor functions directly. This is more consistent with how we handle strings anyway. https://github.com/ruby/yarp/commit/878d845eff --- lib/yarp/ffi.rb | 107 ++++++++++++++++++++++++------------------ yarp/extension.c | 4 +- yarp/util/yp_buffer.c | 18 +++++++ yarp/util/yp_buffer.h | 10 +++- 4 files changed, 90 insertions(+), 49 deletions(-) diff --git a/lib/yarp/ffi.rb b/lib/yarp/ffi.rb index 293958dda6d51f..a547d506063f42 100644 --- a/lib/yarp/ffi.rb +++ b/lib/yarp/ffi.rb @@ -75,7 +75,10 @@ def self.load_exported_functions_from(header, *functions) load_exported_functions_from( "yarp/util/yp_buffer.h", + "yp_buffer_sizeof", "yp_buffer_init", + "yp_buffer_value", + "yp_buffer_length", "yp_buffer_free" ) @@ -88,34 +91,49 @@ def self.load_exported_functions_from(header, *functions) "yp_string_sizeof" ) - # This object represents a yp_buffer_t. Its structure must be kept in sync - # with the C version. - class YPBuffer < FFI::Struct - layout value: :pointer, length: :size_t, capacity: :size_t + # This object represents a yp_buffer_t. We only use it as an opaque pointer, + # so it doesn't need to know the fields of yp_buffer_t. + class YPBuffer + SIZEOF = LibRubyParser.yp_buffer_sizeof - # Read the contents of the buffer into a String object and return it. - def to_ruby_string - self[:value].read_string(self[:length]) + attr_reader :pointer + + def initialize(pointer) + @pointer = pointer end - end - # Initialize a new buffer and yield it to the block. The buffer will be - # automatically freed when the block returns. - def self.with_buffer(&block) - buffer = YPBuffer.new - - begin - raise unless yp_buffer_init(buffer) - yield buffer - ensure - yp_buffer_free(buffer) - buffer.pointer.free + def value + LibRubyParser.yp_buffer_value(pointer) + end + + def length + LibRubyParser.yp_buffer_length(pointer) + end + + def read + value.read_string(length) + end + + # Initialize a new buffer and yield it to the block. The buffer will be + # automatically freed when the block returns. + def self.with(&block) + pointer = FFI::MemoryPointer.new(SIZEOF) + + begin + raise unless LibRubyParser.yp_buffer_init(pointer) + yield new(pointer) + ensure + LibRubyParser.yp_buffer_free(pointer) + pointer.free + end end end # This object represents a yp_string_t. We only use it as an opaque pointer, # so it doesn't have to be an FFI::Struct. class YPString + SIZEOF = LibRubyParser.yp_string_sizeof + attr_reader :pointer def initialize(pointer) @@ -133,23 +151,18 @@ def length def read source.read_string(length) end - end - # This is the size of a yp_string_t. It is returned by the yp_string_sizeof - # function which we call once to ensure we have sufficient space for the - # yp_string_t FFI pointer. - SIZEOF_YP_STRING = yp_string_sizeof - - # Yields a yp_string_t pointer to the given block. - def self.with_string(filepath, &block) - string = FFI::MemoryPointer.new(SIZEOF_YP_STRING) - - begin - raise unless yp_string_mapped_init(string, filepath) - yield YPString.new(string) - ensure - yp_string_free(string) - string.free + # Yields a yp_string_t pointer to the given block. + def self.with(filepath, &block) + pointer = FFI::MemoryPointer.new(SIZEOF) + + begin + raise unless LibRubyParser.yp_string_mapped_init(pointer, filepath) + yield new(pointer) + ensure + LibRubyParser.yp_string_free(pointer) + pointer.free + end end end end @@ -162,10 +175,10 @@ def self.with_string(filepath, &block) VERSION = LibRubyParser.yp_version.read_string def self.dump_internal(source, source_size, filepath) - LibRubyParser.with_buffer do |buffer| + LibRubyParser::YPBuffer.with do |buffer| metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath - LibRubyParser.yp_parse_serialize(source, source_size, buffer, metadata) - buffer.to_ruby_string + LibRubyParser.yp_parse_serialize(source, source_size, buffer.pointer, metadata) + buffer.read end end private_class_method :dump_internal @@ -177,24 +190,24 @@ def self.dump(code, filepath = nil) # Mirror the YARP.dump_file API by using the serialization API. def self.dump_file(filepath) - LibRubyParser.with_string(filepath) do |string| + LibRubyParser::YPString.with(filepath) do |string| dump_internal(string.source, string.length, filepath) end end # Mirror the YARP.lex API by using the serialization API. def self.lex(code, filepath = nil) - LibRubyParser.with_buffer do |buffer| - LibRubyParser.yp_lex_serialize(code, code.bytesize, filepath, buffer) - - source = Source.new(code) - Serialize.load_tokens(source, buffer.to_ruby_string) + LibRubyParser::YPBuffer.with do |buffer| + LibRubyParser.yp_lex_serialize(code, code.bytesize, filepath, buffer.pointer) + Serialize.load_tokens(Source.new(code), buffer.read) end end # Mirror the YARP.lex_file API by using the serialization API. def self.lex_file(filepath) - LibRubyParser.with_string(filepath) { |string| lex(string.read, filepath) } + LibRubyParser::YPString.with(filepath) do |string| + lex(string.read, filepath) + end end # Mirror the YARP.parse API by using the serialization API. @@ -206,6 +219,8 @@ def self.parse(code, filepath = nil) # native strings instead of Ruby strings because it allows us to use mmap when # it is available. def self.parse_file(filepath) - LibRubyParser.with_string(filepath) { |string| parse(string.read, filepath) } + LibRubyParser::YPString.with(filepath) do |string| + parse(string.read, filepath) + end end end diff --git a/yarp/extension.c b/yarp/extension.c index 119c28004e30a7..455cdcadccce5b 100644 --- a/yarp/extension.c +++ b/yarp/extension.c @@ -66,7 +66,7 @@ dump_input(yp_string_t *input, const char *filepath) { yp_node_t *node = yp_parse(&parser); yp_serialize(&parser, node, &buffer); - VALUE result = rb_str_new(buffer.value, buffer.length); + VALUE result = rb_str_new(yp_buffer_value(&buffer), yp_buffer_length(&buffer)); yp_node_destroy(&parser, node); yp_buffer_free(&buffer); yp_parser_free(&parser); @@ -483,7 +483,7 @@ parse_serialize_file_metadata(VALUE self, VALUE filepath, VALUE metadata) { if (!yp_string_mapped_init(&input, checked)) return Qnil; yp_parse_serialize(yp_string_source(&input), yp_string_length(&input), &buffer, check_string(metadata)); - VALUE result = rb_str_new(buffer.value, buffer.length); + VALUE result = rb_str_new(yp_buffer_value(&buffer), yp_buffer_length(&buffer)); yp_buffer_free(&buffer); return result; diff --git a/yarp/util/yp_buffer.c b/yarp/util/yp_buffer.c index df33904039c9df..c9f06ae1c6dc0e 100644 --- a/yarp/util/yp_buffer.c +++ b/yarp/util/yp_buffer.c @@ -2,6 +2,12 @@ #define YP_BUFFER_INITIAL_SIZE 1024 +// Return the size of the yp_buffer_t struct. +size_t +yp_buffer_sizeof(void) { + return sizeof(yp_buffer_t); +} + // Initialize a yp_buffer_t with its default values. bool yp_buffer_init(yp_buffer_t *buffer) { @@ -12,6 +18,18 @@ yp_buffer_init(yp_buffer_t *buffer) { return buffer->value != NULL; } +// Return the value of the buffer. +char * +yp_buffer_value(yp_buffer_t *buffer) { + return buffer->value; +} + +// Return the length of the buffer. +size_t +yp_buffer_length(yp_buffer_t *buffer) { + return buffer->length; +} + // Append the given amount of space to the buffer. static inline void yp_buffer_append_length(yp_buffer_t *buffer, size_t length) { diff --git a/yarp/util/yp_buffer.h b/yarp/util/yp_buffer.h index 722315b96fa0a1..095f62a833c565 100644 --- a/yarp/util/yp_buffer.h +++ b/yarp/util/yp_buffer.h @@ -12,16 +12,24 @@ // A yp_buffer_t is a simple memory buffer that stores data in a contiguous // block of memory. It is used to store the serialized representation of a // YARP tree. -// NOTE: keep in sync with YARP::LibRubyParser::Buffer in lib/yarp.rb typedef struct { char *value; size_t length; size_t capacity; } yp_buffer_t; +// Return the size of the yp_buffer_t struct. +YP_EXPORTED_FUNCTION size_t yp_buffer_sizeof(void); + // Initialize a yp_buffer_t with its default values. YP_EXPORTED_FUNCTION bool yp_buffer_init(yp_buffer_t *buffer); +// Return the value of the buffer. +YP_EXPORTED_FUNCTION char * yp_buffer_value(yp_buffer_t *buffer); + +// Return the length of the buffer. +YP_EXPORTED_FUNCTION size_t yp_buffer_length(yp_buffer_t *buffer); + // Append the given amount of space as zeroes to the buffer. void yp_buffer_append_zeroes(yp_buffer_t *buffer, size_t length); From 40002dd7dc2513ba5209da198a182f3b6a6a0e41 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 16 Aug 2023 17:57:34 -0700 Subject: [PATCH 154/158] Resync YARP --- test/yarp/location_test.rb | 3 +- test/yarp/parse_test.rb | 30 +++++ test/yarp/snapshots/dash_heredocs.txt | 30 ++--- test/yarp/snapshots/dos_endings.txt | 8 +- .../heredoc_with_trailing_newline.txt | 6 +- test/yarp/snapshots/heredocs_nested.txt | 10 +- .../heredocs_with_ignored_newlines.txt | 11 +- ...cs_with_ignored_newlines_and_non_empty.txt | 6 +- .../heredoc__backslash_dos_format.txt | 15 +-- .../seattlerb/heredoc_backslash_nl.txt | 10 +- .../seattlerb/heredoc_bad_hex_escape.txt | 8 +- .../seattlerb/heredoc_bad_oct_escape.txt | 8 +- .../snapshots/seattlerb/heredoc_comma_arg.txt | 2 +- .../snapshots/seattlerb/heredoc_lineno.txt | 4 +- .../snapshots/seattlerb/heredoc_nested.txt | 6 +- .../snapshots/seattlerb/heredoc_squiggly.txt | 8 +- ...squiggly_blank_line_plus_interpolation.txt | 2 +- .../heredoc_squiggly_blank_lines.txt | 8 +- .../seattlerb/heredoc_squiggly_empty.txt | 4 +- .../seattlerb/heredoc_squiggly_interp.txt | 8 +- .../seattlerb/heredoc_squiggly_no_indent.txt | 6 +- .../seattlerb/heredoc_squiggly_tabs.txt | 8 +- .../seattlerb/heredoc_squiggly_tabs_extra.txt | 8 +- .../heredoc_squiggly_visually_blank_lines.txt | 8 +- .../heredoc_trailing_slash_continued_call.txt | 2 +- .../snapshots/seattlerb/heredoc_unicode.txt | 6 +- .../heredoc_with_carriage_return_escapes.txt | 6 +- ...c_with_carriage_return_escapes_windows.txt | 6 +- ...redoc_with_extra_carriage_horrible_mix.txt | 6 +- .../heredoc_with_extra_carriage_returns.txt | 6 +- ...oc_with_extra_carriage_returns_windows.txt | 6 +- ...erpolation_and_carriage_return_escapes.txt | 6 +- ...on_and_carriage_return_escapes_windows.txt | 6 +- .../heredoc_with_not_global_interpolation.txt | 6 +- .../heredoc_with_only_carriage_returns.txt | 6 +- ...doc_with_only_carriage_returns_windows.txt | 6 +- .../seattlerb/heredoc_wtf_I_hate_you.txt | 2 +- .../seattlerb/parse_line_heredoc.txt | 2 +- .../seattlerb/parse_line_heredoc_evstr.txt | 6 +- .../parse_line_heredoc_hardnewline.txt | 2 +- .../parse_line_heredoc_regexp_chars.txt | 4 +- test/yarp/snapshots/seattlerb/pctW_lineno.txt | 2 +- .../seattlerb/pct_Q_backslash_nl.txt | 2 +- .../seattlerb/pct_w_heredoc_interp_nested.txt | 6 +- .../slashy_newlines_within_string.txt | 2 +- .../seattlerb/str_heredoc_interp.txt | 6 +- .../yarp/snapshots/seattlerb/words_interp.txt | 2 +- test/yarp/snapshots/single_quote_heredocs.txt | 6 +- test/yarp/snapshots/strings.txt | 2 +- test/yarp/snapshots/tilde_heredocs.txt | 46 ++++--- test/yarp/snapshots/unescaping.txt | 6 +- .../unparser/corpus/literal/assignment.txt | 28 ++--- .../snapshots/unparser/corpus/literal/def.txt | 4 +- .../unparser/corpus/literal/dstr.txt | 22 ++-- .../unparser/corpus/literal/literal.txt | 12 +- .../unparser/corpus/semantic/block.txt | 8 +- .../unparser/corpus/semantic/dstr.txt | 59 +++++---- .../unparser/corpus/semantic/while.txt | 4 +- .../whitequark/array_words_interp.txt | 4 +- .../snapshots/whitequark/bug_heredoc_do.txt | 4 +- .../whitequark/bug_interp_single.txt | 2 +- .../whitequark/dedenting_heredoc.txt | 100 ++++++++-------- ...olating_heredoc_fake_line_continuation.txt | 6 +- ...nterpolating_heredoc_line_continuation.txt | 6 +- test/yarp/snapshots/whitequark/heredoc.txt | 10 +- .../snapshots/whitequark/interp_digit_var.txt | 16 +-- .../snapshots/whitequark/parser_bug_640.txt | 8 +- ...ps_truncated_parts_of_squiggly_heredoc.txt | 9 +- ...ser_slash_slash_n_escaping_in_literals.txt | 45 +++---- .../snapshots/whitequark/ruby_bug_11989.txt | 12 +- .../snapshots/whitequark/ruby_bug_11990.txt | 2 +- .../whitequark/slash_newline_in_heredocs.txt | 17 +-- yarp/serialize.c | 4 +- yarp/unescape.c | 64 +++++----- yarp/unescape.h | 2 +- yarp/util/yp_constant_pool.h | 3 + yarp/util/yp_list.c | 23 ++-- yarp/util/yp_list.h | 14 +-- yarp/util/yp_newline_list.h | 4 + yarp/util/yp_state_stack.c | 6 - yarp/util/yp_state_stack.h | 2 +- yarp/yarp.c | 112 ++++++++++++------ 82 files changed, 513 insertions(+), 480 deletions(-) diff --git a/test/yarp/location_test.rb b/test/yarp/location_test.rb index 2aaaa7aa761aa5..789bd49ec1a1dc 100644 --- a/test/yarp/location_test.rb +++ b/test/yarp/location_test.rb @@ -411,7 +411,8 @@ def test_InterpolatedRegularExpressionNode end def test_InterpolatedStringNode - assert_location(InterpolatedStringNode, "<<~A\nhello world\nA") + assert_location(InterpolatedStringNode, "\"foo \#@bar baz\"") + assert_location(InterpolatedStringNode, "<<~A\nhello world\nA", 0...4) end def test_InterpolatedSymbolNode diff --git a/test/yarp/parse_test.rb b/test/yarp/parse_test.rb index cda157d56c8511..7a910f7db2aacd 100644 --- a/test/yarp/parse_test.rb +++ b/test/yarp/parse_test.rb @@ -84,6 +84,10 @@ def test_parse_takes_file_path # changing the shape of the tree. assert_equal_nodes(result.value, YARP.load(source, YARP.dump(source, relative)).value) + # Next, check that the location ranges of each node in the tree are a + # superset of their respective child nodes. + assert_non_overlapping_locations(result.value) + # Next, assert that the newlines are in the expected places. expected_newlines = [0] source.b.scan("\n") { expected_newlines << $~.offset(0)[0] + 1 } @@ -137,6 +141,32 @@ def test_parse_takes_file_path private + # Check that the location ranges of each node in the tree are a superset of + # their respective child nodes. + def assert_non_overlapping_locations(node) + queue = [node] + + while (current = queue.shift) + # We only want to compare parent/child location overlap in the case that + # we are not looking at a heredoc. That's because heredoc locations are + # special in that they only use the declaration of the heredoc. + compare = !(current.is_a?(YARP::InterpolatedStringNode) || current.is_a?(YARP::InterpolatedXStringNode)) || !current.opening&.start_with?("<<") + + current.child_nodes.each do |child| + # child_nodes can return nil values, so we need to skip those. + next unless child + + # Now that we know we have a child node, add that to the queue. + queue << child + + if compare + assert_operator current.location.start_offset, :<=, child.location.start_offset + assert_operator current.location.end_offset, :>=, child.location.end_offset + end + end + end + end + def find_source_file_node(program) queue = [program] while (node = queue.shift) diff --git a/test/yarp/snapshots/dash_heredocs.txt b/test/yarp/snapshots/dash_heredocs.txt index 0745fd81ef94a6..24871b27358a04 100644 --- a/test/yarp/snapshots/dash_heredocs.txt +++ b/test/yarp/snapshots/dash_heredocs.txt @@ -1,13 +1,13 @@ -ProgramNode(0...231)( +ProgramNode(0...217)( [], - StatementsNode(0...231)( - [InterpolatedStringNode(0...15)( + StatementsNode(0...217)( + [InterpolatedStringNode(0...6)( (0...6), [StringNode(7...11)(nil, (7...11), nil, " a\n")], (11...15) ), - CallNode(16...58)( - InterpolatedStringNode(16...47)( + CallNode(16...36)( + InterpolatedStringNode(16...24)( (16...24), [StringNode(37...41)(nil, (37...41), nil, " a\n")], (41...47) @@ -15,8 +15,8 @@ ProgramNode(0...231)( nil, (25...26), nil, - ArgumentsNode(27...58)( - [InterpolatedStringNode(27...58)( + ArgumentsNode(27...36)( + [InterpolatedStringNode(27...36)( (27...36), [StringNode(47...51)(nil, (47...51), nil, " b\n")], (51...58) @@ -27,7 +27,7 @@ ProgramNode(0...231)( 0, "+" ), - InterpolatedXStringNode(59...81)( + InterpolatedXStringNode(59...67)( (59...67), [StringNode(68...72)(nil, (68...72), nil, " a\n"), EmbeddedStatementsNode(72...76)( @@ -50,17 +50,17 @@ ProgramNode(0...231)( StringNode(76...77)(nil, (76...77), nil, "\n")], (77...81) ), - InterpolatedStringNode(82...106)( + InterpolatedStringNode(82...88)( (82...88), [StringNode(98...102)(nil, (98...102), nil, " a\n")], (102...106) ), - InterpolatedStringNode(107...128)( + InterpolatedStringNode(107...113)( (107...113), [StringNode(114...122)(nil, (114...122), nil, " a\n" + " b\n")], (122...128) ), - InterpolatedStringNode(129...151)( + InterpolatedStringNode(129...137)( (129...137), [StringNode(138...142)(nil, (138...142), nil, " a\n"), EmbeddedStatementsNode(142...146)( @@ -83,7 +83,7 @@ ProgramNode(0...231)( StringNode(146...147)(nil, (146...147), nil, "\n")], (147...151) ), - InterpolatedStringNode(152...172)( + InterpolatedStringNode(152...158)( (152...158), [StringNode(159...163)(nil, (159...163), nil, " a\n"), EmbeddedStatementsNode(163...167)( @@ -107,13 +107,13 @@ ProgramNode(0...231)( (168...172) ), StringNode(173...179)((173...175), (175...178), (178...179), "abc"), - InterpolatedStringNode(181...200)( + InterpolatedStringNode(181...187)( (181...187), [StringNode(188...196)(nil, (188...196), nil, " a\n" + " b\n")], (196...200) ), - InterpolatedStringNode(201...208)((201...206), [], (207...208)), - InterpolatedStringNode(209...231)( + InterpolatedStringNode(201...206)((201...206), [], (207...208)), + InterpolatedStringNode(209...217)( (209...217), [StringNode(218...227)(nil, (218...227), nil, " a \#{1}\n")], (227...231) diff --git a/test/yarp/snapshots/dos_endings.txt b/test/yarp/snapshots/dos_endings.txt index e1c6c9fec19197..240ae043a42477 100644 --- a/test/yarp/snapshots/dos_endings.txt +++ b/test/yarp/snapshots/dos_endings.txt @@ -18,17 +18,17 @@ ProgramNode(0...108)( "puts" ), ArrayNode(28...37)( - [SymbolNode(31...36)(nil, (31...36), nil, "a\u0000\u0000b")], + [SymbolNode(31...36)(nil, (31...36), nil, "ab")], (28...31), (36...37) ), - InterpolatedStringNode(41...73)( + InterpolatedStringNode(41...45)( (41...45), [StringNode(47...70)( nil, (47...70), nil, - " 1 \u0000\u0000 2\r\n" + " 3\r\n" + " 1 2\r\n" + " 3\r\n" )], (70...73) ), @@ -49,7 +49,7 @@ ProgramNode(0...108)( (95...96), ArgumentsNode(96...107)( [CallNode(96...107)( - InterpolatedStringNode(96...128)( + InterpolatedStringNode(96...102)( (96...102), [StringNode(110...121)( nil, diff --git a/test/yarp/snapshots/heredoc_with_trailing_newline.txt b/test/yarp/snapshots/heredoc_with_trailing_newline.txt index d69085b36af42b..adaa524dda59f7 100644 --- a/test/yarp/snapshots/heredoc_with_trailing_newline.txt +++ b/test/yarp/snapshots/heredoc_with_trailing_newline.txt @@ -1,6 +1,4 @@ -ProgramNode(0...10)( +ProgramNode(0...6)( [], - StatementsNode(0...10)( - [InterpolatedStringNode(0...10)((0...6), [], (7...10))] - ) + StatementsNode(0...6)([InterpolatedStringNode(0...6)((0...6), [], (7...10))]) ) diff --git a/test/yarp/snapshots/heredocs_nested.txt b/test/yarp/snapshots/heredocs_nested.txt index ff25d3daa2a074..750e5e4473fa36 100644 --- a/test/yarp/snapshots/heredocs_nested.txt +++ b/test/yarp/snapshots/heredocs_nested.txt @@ -1,13 +1,13 @@ -ProgramNode(0...47)( +ProgramNode(0...7)( [], - StatementsNode(0...47)( - [InterpolatedStringNode(0...47)( + StatementsNode(0...7)( + [InterpolatedStringNode(0...7)( (0...7), [StringNode(8...12)(nil, (8...12), nil, "pre\n"), EmbeddedStatementsNode(12...36)( (12...14), - StatementsNode(15...35)( - [InterpolatedStringNode(15...35)( + StatementsNode(15...21)( + [InterpolatedStringNode(15...21)( (15...21), [StringNode(22...30)(nil, (22...30), nil, " hello\n")], (30...35) diff --git a/test/yarp/snapshots/heredocs_with_ignored_newlines.txt b/test/yarp/snapshots/heredocs_with_ignored_newlines.txt index 2c0638c0ba2b91..3fd8c7accb8386 100644 --- a/test/yarp/snapshots/heredocs_with_ignored_newlines.txt +++ b/test/yarp/snapshots/heredocs_with_ignored_newlines.txt @@ -1,8 +1,8 @@ -ProgramNode(0...106)( +ProgramNode(0...23)( [], - StatementsNode(0...106)( - [InterpolatedStringNode(0...14)((0...7), [], (9...14)), - InterpolatedStringNode(15...106)( + StatementsNode(0...23)( + [InterpolatedStringNode(0...7)((0...7), [], (9...14)), + InterpolatedStringNode(15...23)( (15...23), [StringNode(25...100)( nil, @@ -13,8 +13,7 @@ ProgramNode(0...106)( " not here\n" + "HERE\n" + "\n" + - "<<~BUT\n" + - " but\n" + + "<<~BUT but\n" + "BUT\n" + " there\n" )], diff --git a/test/yarp/snapshots/heredocs_with_ignored_newlines_and_non_empty.txt b/test/yarp/snapshots/heredocs_with_ignored_newlines_and_non_empty.txt index a002f2445183ab..876c64a2192a35 100644 --- a/test/yarp/snapshots/heredocs_with_ignored_newlines_and_non_empty.txt +++ b/test/yarp/snapshots/heredocs_with_ignored_newlines_and_non_empty.txt @@ -1,7 +1,7 @@ -ProgramNode(0...26)( +ProgramNode(0...6)( [], - StatementsNode(0...26)( - [InterpolatedStringNode(0...26)( + StatementsNode(0...6)( + [InterpolatedStringNode(0...6)( (0...6), [StringNode(7...23)(nil, (7...23), nil, " some\n" + " heredocs\n")], (23...26) diff --git a/test/yarp/snapshots/seattlerb/heredoc__backslash_dos_format.txt b/test/yarp/snapshots/seattlerb/heredoc__backslash_dos_format.txt index 36bb254c51288c..d8a5d9354f388a 100644 --- a/test/yarp/snapshots/seattlerb/heredoc__backslash_dos_format.txt +++ b/test/yarp/snapshots/seattlerb/heredoc__backslash_dos_format.txt @@ -1,17 +1,12 @@ -ProgramNode(0...35)( +ProgramNode(0...12)( [:str], - StatementsNode(0...35)( - [LocalVariableWriteNode(0...35)( + StatementsNode(0...12)( + [LocalVariableWriteNode(0...12)( :str, 0, - InterpolatedStringNode(6...35)( + InterpolatedStringNode(6...12)( (6...12), - [StringNode(14...30)( - nil, - (14...30), - nil, - "before\u0000\u0000after\r\n" - )], + [StringNode(14...30)(nil, (14...30), nil, "beforeafter\r\n")], (30...35) ), (0...3), diff --git a/test/yarp/snapshots/seattlerb/heredoc_backslash_nl.txt b/test/yarp/snapshots/seattlerb/heredoc_backslash_nl.txt index 36a074222bfb81..532b1fe9e7e84d 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_backslash_nl.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_backslash_nl.txt @@ -1,19 +1,19 @@ -ProgramNode(0...93)( +ProgramNode(0...49)( [], - StatementsNode(0...93)( + StatementsNode(0...49)( [StringNode(0...40)( (0...1), (1...39), (39...40), - " why would someone do this? \n" + " blah\n" + " why would someone do this? blah\n" ), - InterpolatedStringNode(42...93)( + InterpolatedStringNode(42...49)( (42...49), [StringNode(50...88)( nil, (50...88), nil, - " why would someone do this? \n" + " blah\n" + " why would someone do this? blah\n" )], (88...93) )] diff --git a/test/yarp/snapshots/seattlerb/heredoc_bad_hex_escape.txt b/test/yarp/snapshots/seattlerb/heredoc_bad_hex_escape.txt index 1917020fbde558..4bc1846ef128c1 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_bad_hex_escape.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_bad_hex_escape.txt @@ -1,10 +1,10 @@ -ProgramNode(0...21)( +ProgramNode(0...9)( [:s], - StatementsNode(0...21)( - [LocalVariableWriteNode(0...21)( + StatementsNode(0...9)( + [LocalVariableWriteNode(0...9)( :s, 0, - InterpolatedStringNode(4...21)( + InterpolatedStringNode(4...9)( (4...9), [StringNode(10...17)(nil, (10...17), nil, "a\xE9b\n")], (17...21) diff --git a/test/yarp/snapshots/seattlerb/heredoc_bad_oct_escape.txt b/test/yarp/snapshots/seattlerb/heredoc_bad_oct_escape.txt index 69776e014535b8..ebfb3b4da35c24 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_bad_oct_escape.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_bad_oct_escape.txt @@ -1,10 +1,10 @@ -ProgramNode(0...27)( +ProgramNode(0...10)( [:s], - StatementsNode(0...27)( - [LocalVariableWriteNode(0...27)( + StatementsNode(0...10)( + [LocalVariableWriteNode(0...10)( :s, 0, - InterpolatedStringNode(4...27)( + InterpolatedStringNode(4...10)( (4...10), [StringNode(11...23)(nil, (11...23), nil, "a\xA7b\n" + "cöd\n")], (23...27) diff --git a/test/yarp/snapshots/seattlerb/heredoc_comma_arg.txt b/test/yarp/snapshots/seattlerb/heredoc_comma_arg.txt index 98cc3184e11fbc..bbded2484ec43f 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_comma_arg.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_comma_arg.txt @@ -7,7 +7,7 @@ ProgramNode(0...47)( (16...17) ), ArrayNode(19...47)( - [InterpolatedStringNode(20...46)( + [InterpolatedStringNode(20...27)( (20...27), [StringNode(29...41)(nil, (29...41), nil, " some text\n")], (41...46) diff --git a/test/yarp/snapshots/seattlerb/heredoc_lineno.txt b/test/yarp/snapshots/seattlerb/heredoc_lineno.txt index e0a8f91a13bbaa..27708e25381e78 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_lineno.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_lineno.txt @@ -1,10 +1,10 @@ ProgramNode(0...41)( [:c, :d], StatementsNode(0...41)( - [LocalVariableWriteNode(0...34)( + [LocalVariableWriteNode(0...11)( :c, 0, - InterpolatedStringNode(4...34)( + InterpolatedStringNode(4...11)( (4...11), [StringNode(12...30)( nil, diff --git a/test/yarp/snapshots/seattlerb/heredoc_nested.txt b/test/yarp/snapshots/seattlerb/heredoc_nested.txt index fdc29de9e0dade..3c3d30d958aa6d 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_nested.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_nested.txt @@ -2,12 +2,12 @@ ProgramNode(0...23)( [], StatementsNode(0...23)( [ArrayNode(0...23)( - [InterpolatedStringNode(1...21)( + [InterpolatedStringNode(1...4)( (1...4), [EmbeddedStatementsNode(6...12)( (6...8), - StatementsNode(8...17)( - [InterpolatedStringNode(8...17)( + StatementsNode(8...11)( + [InterpolatedStringNode(8...11)( (8...11), [StringNode(13...15)(nil, (13...15), nil, "b\n")], (15...17) diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly.txt index 75c1d493108588..a1013d9e84e231 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly.txt @@ -1,10 +1,10 @@ -ProgramNode(0...31)( +ProgramNode(0...12)( [:a], - StatementsNode(0...31)( - [LocalVariableWriteNode(0...31)( + StatementsNode(0...12)( + [LocalVariableWriteNode(0...12)( :a, 0, - InterpolatedStringNode(4...31)( + InterpolatedStringNode(4...12)( (4...12), [StringNode(13...25)(nil, (13...25), nil, "x\n" + "y\n" + "z\n")], (25...31) diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt index d5f32777c1264f..e78764e926461f 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt @@ -11,7 +11,7 @@ ProgramNode(0...20)( (7...8), ArgumentsNode(8...19)( [CallNode(8...19)( - InterpolatedStringNode(8...42)( + InterpolatedStringNode(8...14)( (8...14), [StringNode(21...26)(nil, (21...26), nil, "\n"), EmbeddedStatementsNode(26...32)( diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt index 895a03d219a067..3bb7807c5c6d6a 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt @@ -1,10 +1,10 @@ -ProgramNode(0...24)( +ProgramNode(0...10)( [:a], - StatementsNode(0...24)( - [LocalVariableWriteNode(0...24)( + StatementsNode(0...10)( + [LocalVariableWriteNode(0...10)( :a, 0, - InterpolatedStringNode(4...24)( + InterpolatedStringNode(4...10)( (4...10), [StringNode(11...20)(nil, (11...20), nil, "x\n" + "\n" + "z\n")], (20...24) diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_empty.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_empty.txt index 8de32879f3073b..7303a5ee71cb35 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_empty.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_empty.txt @@ -1,4 +1,4 @@ -ProgramNode(0...7)( +ProgramNode(0...4)( [], - StatementsNode(0...7)([InterpolatedStringNode(0...7)((0...4), [], (5...7))]) + StatementsNode(0...4)([InterpolatedStringNode(0...4)((0...4), [], (5...7))]) ) diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_interp.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_interp.txt index 6d99151e709799..f895e997e7ca18 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_interp.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_interp.txt @@ -1,10 +1,10 @@ -ProgramNode(0...42)( +ProgramNode(0...10)( [:a], - StatementsNode(0...42)( - [LocalVariableWriteNode(0...42)( + StatementsNode(0...10)( + [LocalVariableWriteNode(0...10)( :a, 0, - InterpolatedStringNode(4...42)( + InterpolatedStringNode(4...10)( (4...10), [StringNode(11...22)(nil, (11...22), nil, " w\n" + "x"), EmbeddedStatementsNode(22...27)( diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_no_indent.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_no_indent.txt index 38fd30f6e2b46d..47a116dab26f12 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_no_indent.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_no_indent.txt @@ -1,7 +1,7 @@ -ProgramNode(0...9)( +ProgramNode(0...4)( [], - StatementsNode(0...9)( - [InterpolatedStringNode(0...9)( + StatementsNode(0...4)( + [InterpolatedStringNode(0...4)( (0...4), [StringNode(5...7)(nil, (5...7), nil, "a\n")], (7...9) diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs.txt index 0e18753a1c0af3..13d1844e3c7425 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs.txt @@ -1,10 +1,10 @@ -ProgramNode(0...49)( +ProgramNode(0...12)( [:a], - StatementsNode(0...49)( - [LocalVariableWriteNode(0...49)( + StatementsNode(0...12)( + [LocalVariableWriteNode(0...12)( :a, 0, - InterpolatedStringNode(4...49)( + InterpolatedStringNode(4...12)( (4...12), [StringNode(13...43)( nil, diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt index 2199b41826c6c1..da631943fceab6 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt @@ -1,10 +1,10 @@ -ProgramNode(0...43)( +ProgramNode(0...12)( [:a], - StatementsNode(0...43)( - [LocalVariableWriteNode(0...43)( + StatementsNode(0...12)( + [LocalVariableWriteNode(0...12)( :a, 0, - InterpolatedStringNode(4...43)( + InterpolatedStringNode(4...12)( (4...12), [StringNode(13...37)( nil, diff --git a/test/yarp/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt b/test/yarp/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt index 895a03d219a067..3bb7807c5c6d6a 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt @@ -1,10 +1,10 @@ -ProgramNode(0...24)( +ProgramNode(0...10)( [:a], - StatementsNode(0...24)( - [LocalVariableWriteNode(0...24)( + StatementsNode(0...10)( + [LocalVariableWriteNode(0...10)( :a, 0, - InterpolatedStringNode(4...24)( + InterpolatedStringNode(4...10)( (4...10), [StringNode(11...20)(nil, (11...20), nil, "x\n" + "\n" + "z\n")], (20...24) diff --git a/test/yarp/snapshots/seattlerb/heredoc_trailing_slash_continued_call.txt b/test/yarp/snapshots/seattlerb/heredoc_trailing_slash_continued_call.txt index 2ec330b49e9bfc..b672fceefca2dd 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_trailing_slash_continued_call.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_trailing_slash_continued_call.txt @@ -2,7 +2,7 @@ ProgramNode(0...22)( [], StatementsNode(0...22)( [CallNode(0...22)( - InterpolatedStringNode(0...16)( + InterpolatedStringNode(0...5)( (0...5), [StringNode(7...12)(nil, (7...12), nil, "blah\n")], (12...16) diff --git a/test/yarp/snapshots/seattlerb/heredoc_unicode.txt b/test/yarp/snapshots/seattlerb/heredoc_unicode.txt index 3f0b096d94b5ae..42e475b08a0528 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_unicode.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_unicode.txt @@ -1,7 +1,7 @@ -ProgramNode(0...20)( +ProgramNode(0...9)( [], - StatementsNode(0...20)( - [InterpolatedStringNode(0...20)( + StatementsNode(0...9)( + [InterpolatedStringNode(0...9)( (0...9), [StringNode(10...12)(nil, (10...12), nil, ".\n")], (12...20) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes.txt b/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes.txt index 24d7f88cff9099..f3a7cdd423acf8 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes.txt @@ -1,7 +1,7 @@ -ProgramNode(0...25)( +ProgramNode(0...5)( [], - StatementsNode(0...25)( - [InterpolatedStringNode(0...25)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(6...21)(nil, (6...21), nil, "foo\rbar\n" + "baz\r\n")], (21...25) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes_windows.txt b/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes_windows.txt index 6ac06a37301686..e206ee78a9c8dd 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes_windows.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_carriage_return_escapes_windows.txt @@ -1,7 +1,7 @@ -ProgramNode(0...29)( +ProgramNode(0...5)( [], - StatementsNode(0...29)( - [InterpolatedStringNode(0...29)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(7...24)(nil, (7...24), nil, "foo\rbar\r\n" + "baz\r\r\n")], (24...29) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt b/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt index fcf6267807d064..2c5d16dcabc667 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt @@ -1,7 +1,7 @@ -ProgramNode(0...19)( +ProgramNode(0...7)( [], - StatementsNode(0...19)( - [InterpolatedStringNode(0...19)( + StatementsNode(0...7)( + [InterpolatedStringNode(0...7)( (0...7), [StringNode(9...15)(nil, (9...15), nil, "body\r\n")], (15...19) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns.txt b/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns.txt index 3c538e92d1ad87..35583e32899ba5 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns.txt @@ -1,7 +1,7 @@ -ProgramNode(0...23)( +ProgramNode(0...5)( [], - StatementsNode(0...23)( - [InterpolatedStringNode(0...23)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(6...19)(nil, (6...19), nil, "foo\rbar\r\n" + "baz\n")], (19...23) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns_windows.txt b/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns_windows.txt index 5ef9682601e801..c36008cfcebcc8 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns_windows.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_extra_carriage_returns_windows.txt @@ -1,7 +1,7 @@ -ProgramNode(0...27)( +ProgramNode(0...5)( [], - StatementsNode(0...27)( - [InterpolatedStringNode(0...27)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(7...22)(nil, (7...22), nil, "foo\rbar\r\r\n" + "baz\r\n")], (22...27) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt b/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt index 57cd5f75df2a16..cfb1f9644370c7 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt @@ -1,7 +1,7 @@ -ProgramNode(0...21)( +ProgramNode(0...5)( [], - StatementsNode(0...21)( - [InterpolatedStringNode(0...21)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(6...11)(nil, (6...11), nil, "foo\r"), EmbeddedVariableNode(11...16)( diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt b/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt index 6cc4d8ad45d096..ee013f51378747 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt @@ -1,7 +1,7 @@ -ProgramNode(0...24)( +ProgramNode(0...5)( [], - StatementsNode(0...24)( - [InterpolatedStringNode(0...24)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(7...12)(nil, (7...12), nil, "foo\r"), EmbeddedVariableNode(12...17)( diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_not_global_interpolation.txt b/test/yarp/snapshots/seattlerb/heredoc_with_not_global_interpolation.txt index 3ea8c05892ae1f..be3f48e171bbdb 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_not_global_interpolation.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_not_global_interpolation.txt @@ -1,7 +1,7 @@ -ProgramNode(0...23)( +ProgramNode(0...10)( [], - StatementsNode(0...23)( - [InterpolatedStringNode(0...23)( + StatementsNode(0...10)( + [InterpolatedStringNode(0...10)( (0...10), [StringNode(11...15)(nil, (11...15), nil, "\#${\n")], (15...23) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns.txt b/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns.txt index d3c5c526550596..f4a65965f68fc1 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns.txt @@ -1,7 +1,7 @@ -ProgramNode(0...18)( +ProgramNode(0...5)( [], - StatementsNode(0...18)( - [InterpolatedStringNode(0...18)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(6...14)(nil, (6...14), nil, "\r\n" + "\r\r\n" + "\r\n")], (14...18) diff --git a/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns_windows.txt b/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns_windows.txt index c38bebfd070323..e3fbb71b7f4b2a 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns_windows.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_with_only_carriage_returns_windows.txt @@ -1,7 +1,7 @@ -ProgramNode(0...23)( +ProgramNode(0...5)( [], - StatementsNode(0...23)( - [InterpolatedStringNode(0...23)( + StatementsNode(0...5)( + [InterpolatedStringNode(0...5)( (0...5), [StringNode(7...18)( nil, diff --git a/test/yarp/snapshots/seattlerb/heredoc_wtf_I_hate_you.txt b/test/yarp/snapshots/seattlerb/heredoc_wtf_I_hate_you.txt index 9547fe76575114..c68a126eb09b46 100644 --- a/test/yarp/snapshots/seattlerb/heredoc_wtf_I_hate_you.txt +++ b/test/yarp/snapshots/seattlerb/heredoc_wtf_I_hate_you.txt @@ -9,7 +9,7 @@ ProgramNode(0...30)( ArgumentsNode(2...30)( [CallNode(2...30)( CallNode(2...26)( - InterpolatedStringNode(2...22)( + InterpolatedStringNode(2...8)( (2...8), [StringNode(12...16)(nil, (12...16), nil, " a\n")], (16...22) diff --git a/test/yarp/snapshots/seattlerb/parse_line_heredoc.txt b/test/yarp/snapshots/seattlerb/parse_line_heredoc.txt index e2a8c1c665b5f3..8e41b1648bc6f3 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_heredoc.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_heredoc.txt @@ -5,7 +5,7 @@ ProgramNode(6...88)( :string, 0, CallNode(15...31)( - InterpolatedStringNode(15...71)( + InterpolatedStringNode(15...25)( (15...25), [StringNode(32...57)( nil, diff --git a/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt b/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt index 23122ab3673505..8b95196e2d741d 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_heredoc_evstr.txt @@ -1,7 +1,7 @@ -ProgramNode(0...14)( +ProgramNode(0...4)( [], - StatementsNode(0...14)( - [InterpolatedStringNode(0...14)( + StatementsNode(0...4)( + [InterpolatedStringNode(0...4)( (0...4), [StringNode(5...7)(nil, (5...7), nil, "a\n"), EmbeddedStatementsNode(7...11)( diff --git a/test/yarp/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt b/test/yarp/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt index 573a260958608e..4f7ae811cfdf51 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt @@ -1,7 +1,7 @@ ProgramNode(0...48)( [], StatementsNode(0...48)( - [InterpolatedStringNode(0...34)( + [InterpolatedStringNode(0...8)( (0...8), [StringNode(9...28)( nil, diff --git a/test/yarp/snapshots/seattlerb/parse_line_heredoc_regexp_chars.txt b/test/yarp/snapshots/seattlerb/parse_line_heredoc_regexp_chars.txt index c252ec45dc437a..b3ed88d90eb66d 100644 --- a/test/yarp/snapshots/seattlerb/parse_line_heredoc_regexp_chars.txt +++ b/test/yarp/snapshots/seattlerb/parse_line_heredoc_regexp_chars.txt @@ -1,10 +1,10 @@ ProgramNode(6...74)( [:string], StatementsNode(6...74)( - [LocalVariableWriteNode(6...57)( + [LocalVariableWriteNode(6...22)( :string, 0, - InterpolatedStringNode(15...57)( + InterpolatedStringNode(15...22)( (15...22), [StringNode(23...48)( nil, diff --git a/test/yarp/snapshots/seattlerb/pctW_lineno.txt b/test/yarp/snapshots/seattlerb/pctW_lineno.txt index c9ed993026740a..d03e41c0f2f4a8 100644 --- a/test/yarp/snapshots/seattlerb/pctW_lineno.txt +++ b/test/yarp/snapshots/seattlerb/pctW_lineno.txt @@ -5,7 +5,7 @@ ProgramNode(0...28)( [StringNode(3...7)(nil, (3...7), nil, "a\n" + "b"), StringNode(8...9)(nil, (8...9), nil, "c"), StringNode(10...11)(nil, (10...11), nil, "d"), - StringNode(12...16)(nil, (12...16), nil, "e\n" + "f"), + StringNode(12...16)(nil, (12...16), nil, "ef"), StringNode(17...19)(nil, (17...19), nil, "gy"), StringNode(20...23)(nil, (20...23), nil, "hy"), StringNode(24...27)(nil, (24...27), nil, "iy")], diff --git a/test/yarp/snapshots/seattlerb/pct_Q_backslash_nl.txt b/test/yarp/snapshots/seattlerb/pct_Q_backslash_nl.txt index f8e3421ee4b650..69721af37214f0 100644 --- a/test/yarp/snapshots/seattlerb/pct_Q_backslash_nl.txt +++ b/test/yarp/snapshots/seattlerb/pct_Q_backslash_nl.txt @@ -1,4 +1,4 @@ ProgramNode(0...7)( [], - StatementsNode(0...7)([StringNode(0...7)((0...3), (3...6), (6...7), " \n")]) + StatementsNode(0...7)([StringNode(0...7)((0...3), (3...6), (6...7), " ")]) ) diff --git a/test/yarp/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt b/test/yarp/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt index 89ce74ce19627d..8c9604e40d9c85 100644 --- a/test/yarp/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt +++ b/test/yarp/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt @@ -3,12 +3,12 @@ ProgramNode(0...30)( StatementsNode(0...30)( [ArrayNode(0...30)( [StringNode(4...5)(nil, (4...5), nil, "1"), - InterpolatedStringNode(0...12)( + InterpolatedStringNode(6...12)( nil, [EmbeddedStatementsNode(6...12)( (6...8), - StatementsNode(8...19)( - [InterpolatedStringNode(8...19)( + StatementsNode(8...11)( + [InterpolatedStringNode(8...11)( (8...11), [StringNode(15...17)(nil, (15...17), nil, "2\n")], (17...19) diff --git a/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt b/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt index 52bd599ce9b734..1ef9123f4c8f5d 100644 --- a/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt +++ b/test/yarp/snapshots/seattlerb/slashy_newlines_within_string.txt @@ -11,7 +11,7 @@ ProgramNode(0...40)( (5...6), (6...32), (32...33), - "hello\n" + " my\n" + " dear\n" + " friend" + "hello my dear friend" )] ), nil, diff --git a/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt b/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt index 8c0ee1e1b7d263..22f5a96755a83f 100644 --- a/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt +++ b/test/yarp/snapshots/seattlerb/str_heredoc_interp.txt @@ -1,7 +1,7 @@ -ProgramNode(0...17)( +ProgramNode(0...4)( [], - StatementsNode(0...17)( - [InterpolatedStringNode(0...17)( + StatementsNode(0...4)( + [InterpolatedStringNode(0...4)( (0...4), [EmbeddedStatementsNode(5...9)( (5...7), diff --git a/test/yarp/snapshots/seattlerb/words_interp.txt b/test/yarp/snapshots/seattlerb/words_interp.txt index 658901cbda7a72..982de5f8069958 100644 --- a/test/yarp/snapshots/seattlerb/words_interp.txt +++ b/test/yarp/snapshots/seattlerb/words_interp.txt @@ -2,7 +2,7 @@ ProgramNode(0...9)( [], StatementsNode(0...9)( [ArrayNode(0...9)( - [InterpolatedStringNode(0...8)( + [InterpolatedStringNode(3...8)( nil, [EmbeddedStatementsNode(3...7)( (3...5), diff --git a/test/yarp/snapshots/single_quote_heredocs.txt b/test/yarp/snapshots/single_quote_heredocs.txt index 3e53eb791b59b5..13e0f12fac5dc0 100644 --- a/test/yarp/snapshots/single_quote_heredocs.txt +++ b/test/yarp/snapshots/single_quote_heredocs.txt @@ -1,7 +1,7 @@ -ProgramNode(0...48)( +ProgramNode(0...8)( [], - StatementsNode(0...48)( - [InterpolatedStringNode(0...48)( + StatementsNode(0...8)( + [InterpolatedStringNode(0...8)( (0...8), [StringNode(9...44)( nil, diff --git a/test/yarp/snapshots/strings.txt b/test/yarp/snapshots/strings.txt index ab74cd0bd957f2..38033453af3da3 100644 --- a/test/yarp/snapshots/strings.txt +++ b/test/yarp/snapshots/strings.txt @@ -120,7 +120,7 @@ ProgramNode(0...498)( ), ArrayNode(325...339)( [StringNode(328...329)(nil, (328...329), nil, "a"), - InterpolatedStringNode(0...336)( + InterpolatedStringNode(330...336)( nil, [StringNode(330...331)(nil, (330...331), nil, "b"), EmbeddedStatementsNode(331...335)( diff --git a/test/yarp/snapshots/tilde_heredocs.txt b/test/yarp/snapshots/tilde_heredocs.txt index fc51879e4ffe7e..864ea645b3de30 100644 --- a/test/yarp/snapshots/tilde_heredocs.txt +++ b/test/yarp/snapshots/tilde_heredocs.txt @@ -1,20 +1,19 @@ -ProgramNode(0...387)( +ProgramNode(0...372)( [], - StatementsNode(0...387)( - [InterpolatedStringNode(0...15)( + StatementsNode(0...372)( + [InterpolatedStringNode(0...6)( (0...6), [StringNode(7...11)(nil, (7...11), nil, "a\n")], (11...15) ), - InterpolatedStringNode(16...38)( + InterpolatedStringNode(16...22)( (16...22), [StringNode(23...34)(nil, (23...34), nil, "\ta\n" + "b\n" + "\t\tc\n")], (34...38) ), - InterpolatedStringNode(39...59)( + InterpolatedStringNode(39...45)( (39...45), - [StringNode(46...48)(nil, (46...48), nil, ""), - EmbeddedStatementsNode(48...52)( + [EmbeddedStatementsNode(48...52)( (48...50), StatementsNode(50...51)([IntegerNode(50...51)()]), (51...52) @@ -22,7 +21,7 @@ ProgramNode(0...387)( StringNode(52...55)(nil, (52...55), nil, " a\n")], (55...59) ), - InterpolatedStringNode(60...80)( + InterpolatedStringNode(60...66)( (60...66), [StringNode(67...71)(nil, (67...71), nil, "a "), EmbeddedStatementsNode(71...75)( @@ -33,7 +32,7 @@ ProgramNode(0...387)( StringNode(75...76)(nil, (75...76), nil, "\n")], (76...80) ), - InterpolatedStringNode(81...102)( + InterpolatedStringNode(81...87)( (81...87), [StringNode(88...93)(nil, (88...93), nil, " a\n"), EmbeddedStatementsNode(93...97)( @@ -44,7 +43,7 @@ ProgramNode(0...387)( StringNode(97...98)(nil, (97...98), nil, "\n")], (98...102) ), - InterpolatedStringNode(103...125)( + InterpolatedStringNode(103...109)( (103...109), [StringNode(110...116)(nil, (110...116), nil, "a\n"), EmbeddedStatementsNode(116...120)( @@ -55,52 +54,52 @@ ProgramNode(0...387)( StringNode(120...121)(nil, (120...121), nil, "\n")], (121...125) ), - InterpolatedStringNode(126...145)( + InterpolatedStringNode(126...132)( (126...132), [StringNode(133...141)(nil, (133...141), nil, "a\n" + "b\n")], (141...145) ), - InterpolatedStringNode(146...166)( + InterpolatedStringNode(146...152)( (146...152), [StringNode(153...162)(nil, (153...162), nil, "a\n" + " b\n")], (162...166) ), - InterpolatedStringNode(167...187)( + InterpolatedStringNode(167...173)( (167...173), [StringNode(174...183)(nil, (174...183), nil, "\ta\n" + "b\n")], (183...187) ), - InterpolatedStringNode(188...210)( + InterpolatedStringNode(188...196)( (188...196), [StringNode(197...206)(nil, (197...206), nil, "a \#{1}\n")], (206...210) ), - InterpolatedStringNode(211...229)( + InterpolatedStringNode(211...217)( (211...217), [StringNode(218...225)(nil, (218...225), nil, "a\n" + " b\n")], (225...229) ), - InterpolatedStringNode(230...248)( + InterpolatedStringNode(230...236)( (230...236), [StringNode(237...244)(nil, (237...244), nil, " a\n" + "b\n")], (244...248) ), - InterpolatedStringNode(249...275)( + InterpolatedStringNode(249...255)( (249...255), [StringNode(256...271)(nil, (256...271), nil, "a\n" + "b\n")], (271...275) ), - InterpolatedStringNode(276...296)( + InterpolatedStringNode(276...282)( (276...282), [StringNode(283...292)(nil, (283...292), nil, "a\n" + "\n" + "b\n")], (292...296) ), - InterpolatedStringNode(297...317)( + InterpolatedStringNode(297...303)( (297...303), [StringNode(304...313)(nil, (304...313), nil, "a\n" + "\n" + "b\n")], (313...317) ), - InterpolatedStringNode(318...340)( + InterpolatedStringNode(318...324)( (318...324), [StringNode(325...336)( nil, @@ -110,7 +109,7 @@ ProgramNode(0...387)( )], (336...340) ), - InterpolatedStringNode(341...365)( + InterpolatedStringNode(341...347)( (341...347), [StringNode(348...351)(nil, (348...351), nil, "\n"), EmbeddedStatementsNode(351...355)( @@ -121,10 +120,9 @@ ProgramNode(0...387)( StringNode(355...357)(nil, (355...357), nil, "a\n")], (357...365) ), - InterpolatedStringNode(366...387)( + InterpolatedStringNode(366...372)( (366...372), - [StringNode(373...375)(nil, (373...375), nil, ""), - EmbeddedStatementsNode(375...379)( + [EmbeddedStatementsNode(375...379)( (375...377), StatementsNode(377...378)([IntegerNode(377...378)()]), (378...379) diff --git a/test/yarp/snapshots/unescaping.txt b/test/yarp/snapshots/unescaping.txt index e63e8eb07229bd..17387dbc6cdf7c 100644 --- a/test/yarp/snapshots/unescaping.txt +++ b/test/yarp/snapshots/unescaping.txt @@ -1,6 +1,6 @@ -ProgramNode(0...55)( +ProgramNode(0...39)( [], - StatementsNode(0...55)( + StatementsNode(0...39)( [ArrayNode(0...10)( [StringNode(1...9)((1...2), (2...8), (8...9), "\u0003{1}")], (0...1), @@ -14,7 +14,7 @@ ProgramNode(0...55)( 0 ), StringNode(22...30)((22...23), (23...29), (29...30), "\u0003{1}"), - InterpolatedStringNode(32...55)( + InterpolatedStringNode(32...39)( (32...39), [StringNode(40...50)(nil, (40...50), nil, "\u0003{1}\n")], (50...55) diff --git a/test/yarp/snapshots/unparser/corpus/literal/assignment.txt b/test/yarp/snapshots/unparser/corpus/literal/assignment.txt index 4a1b5eeaf769ca..1423b7e4d071a7 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/assignment.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/assignment.txt @@ -1,6 +1,6 @@ -ProgramNode(0...719)( +ProgramNode(0...704)( [:a, :b, :foo, :c, :x], - StatementsNode(0...719)( + StatementsNode(0...704)( [GlobalVariableWriteNode(0...6)((0...2), (3...4), IntegerNode(5...6)()), MultiWriteNode(8...24)( [GlobalVariableWriteNode(8...10)((8...10), nil, nil), @@ -615,10 +615,10 @@ ProgramNode(0...719)( (554...557), StringNode(558...561)((558...560), (560...560), (560...561), "") ), - LocalVariableWriteNode(562...591)( + LocalVariableWriteNode(562...576)( :x, 0, - InterpolatedStringNode(566...591)( + InterpolatedStringNode(566...576)( (566...576), [StringNode(577...579)(nil, (577...579), nil, " "), EmbeddedStatementsNode(579...582)((579...581), nil, (581...582)), @@ -628,13 +628,13 @@ ProgramNode(0...719)( (562...563), (564...565) ), - CallNode(591...620)( + CallNode(591...605)( LocalVariableReadNode(591...592)(:x, 0), (592...593), (593...594), nil, - ArgumentsNode(595...620)( - [InterpolatedStringNode(595...620)( + ArgumentsNode(595...605)( + [InterpolatedStringNode(595...605)( (595...605), [StringNode(606...608)(nil, (606...608), nil, " "), EmbeddedStatementsNode(608...611)((608...610), nil, (610...611)), @@ -647,13 +647,13 @@ ProgramNode(0...719)( 0, "x=" ), - CallNode(620...651)( + CallNode(620...636)( LocalVariableReadNode(620...621)(:x, 0), nil, (621...623), (621...622), - ArgumentsNode(626...651)( - [InterpolatedStringNode(626...651)( + ArgumentsNode(626...636)( + [InterpolatedStringNode(626...636)( (626...636), [StringNode(637...639)(nil, (637...639), nil, " "), EmbeddedStatementsNode(639...642)((639...641), nil, (641...642)), @@ -672,8 +672,8 @@ ProgramNode(0...719)( nil, (652...664), (652...653), - ArgumentsNode(653...687)( - [InterpolatedStringNode(653...687)( + ArgumentsNode(653...663)( + [InterpolatedStringNode(653...663)( (653...663), [StringNode(673...675)(nil, (673...675), nil, " "), EmbeddedStatementsNode(675...678)( @@ -703,10 +703,10 @@ ProgramNode(0...719)( ), (665...668) ), - InstanceVariableOperatorOrWriteNode(687...719)( + InstanceVariableOperatorOrWriteNode(687...704)( (687...689), (690...693), - InterpolatedStringNode(694...719)( + InterpolatedStringNode(694...704)( (694...704), [StringNode(705...707)(nil, (705...707), nil, " "), EmbeddedStatementsNode(707...710)((707...709), nil, (709...710)), diff --git a/test/yarp/snapshots/unparser/corpus/literal/def.txt b/test/yarp/snapshots/unparser/corpus/literal/def.txt index 4a875be76193ce..360c39b5e09798 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/def.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/def.txt @@ -983,8 +983,8 @@ ProgramNode(0...913)( (860...861), nil, nil, - StatementsNode(864...893)( - [InterpolatedStringNode(864...893)( + StatementsNode(864...874)( + [InterpolatedStringNode(864...874)( (864...874), [StringNode(875...879)(nil, (875...879), nil, " "), EmbeddedStatementsNode(879...882)((879...881), nil, (881...882)), diff --git a/test/yarp/snapshots/unparser/corpus/literal/dstr.txt b/test/yarp/snapshots/unparser/corpus/literal/dstr.txt index b76f9da57d11e4..846614936967e2 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/dstr.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/dstr.txt @@ -19,7 +19,7 @@ ProgramNode(0...299)( (21...23), TrueNode(24...28)(), StatementsNode(31...64)( - [InterpolatedStringNode(31...61)( + [InterpolatedStringNode(31...41)( (31...41), [StringNode(42...44)(nil, (42...44), nil, "a\n"), EmbeddedStatementsNode(44...47)((44...46), nil, (46...47)), @@ -31,7 +31,7 @@ ProgramNode(0...299)( nil, (65...68) ), - InterpolatedStringNode(69...109)( + InterpolatedStringNode(69...79)( (69...79), [StringNode(80...89)(nil, (80...89), nil, "\#{}\#{}\n"), EmbeddedStatementsNode(89...92)((89...91), nil, (91...92)), @@ -43,7 +43,7 @@ ProgramNode(0...299)( (101...109) ), RescueModifierNode(109...130)( - InterpolatedStringNode(109...145)( + InterpolatedStringNode(109...119)( (109...119), [EmbeddedStatementsNode(131...134)((131...133), nil, (133...134)), StringNode(134...137)(nil, (134...137), nil, "\n" + "a\n")], @@ -91,11 +91,11 @@ ProgramNode(0...299)( IfNode(174...225)( (174...176), TrueNode(177...181)(), - StatementsNode(184...222)( - [ReturnNode(184...222)( + StatementsNode(184...201)( + [ReturnNode(184...201)( (184...190), - ArgumentsNode(191...222)( - [InterpolatedStringNode(191...222)( + ArgumentsNode(191...201)( + [InterpolatedStringNode(191...201)( (191...201), [StringNode(202...206)(nil, (202...206), nil, " "), EmbeddedStatementsNode(206...211)( @@ -117,8 +117,8 @@ ProgramNode(0...299)( nil, (226...229), (229...230), - ArgumentsNode(230...259)( - [InterpolatedStringNode(230...259)( + ArgumentsNode(230...240)( + [InterpolatedStringNode(230...240)( (230...240), [StringNode(242...244)(nil, (242...244), nil, " "), EmbeddedStatementsNode(244...250)( @@ -152,8 +152,8 @@ ProgramNode(0...299)( nil, (259...262), (262...263), - ArgumentsNode(263...298)( - [InterpolatedStringNode(263...298)( + ArgumentsNode(263...273)( + [InterpolatedStringNode(263...273)( (263...273), [StringNode(281...283)(nil, (281...283), nil, " "), EmbeddedStatementsNode(283...289)( diff --git a/test/yarp/snapshots/unparser/corpus/literal/literal.txt b/test/yarp/snapshots/unparser/corpus/literal/literal.txt index bab790a7134a27..9b0fad50720ceb 100644 --- a/test/yarp/snapshots/unparser/corpus/literal/literal.txt +++ b/test/yarp/snapshots/unparser/corpus/literal/literal.txt @@ -3,9 +3,9 @@ ProgramNode(0...916)( StatementsNode(0...916)( [HashNode(0...38)( (0...1), - [AssocNode(2...53)( + [AssocNode(2...21)( StringNode(2...7)((2...3), (3...6), (6...7), "foo"), - InterpolatedStringNode(11...53)( + InterpolatedStringNode(11...21)( (11...21), [StringNode(39...41)(nil, (39...41), nil, " "), EmbeddedStatementsNode(41...44)((41...43), nil, (43...44)), @@ -47,8 +47,8 @@ ProgramNode(0...916)( nil, (98...99), (99...100), - ArgumentsNode(100...128)( - [InterpolatedStringNode(100...128)( + ArgumentsNode(100...110)( + [InterpolatedStringNode(100...110)( (100...110), [StringNode(114...116)(nil, (114...116), nil, " "), EmbeddedStatementsNode(116...119)( @@ -99,9 +99,9 @@ ProgramNode(0...916)( ), HashNode(137...167)( (137...138), - [AssocNode(139...182)( + [AssocNode(139...158)( StringNode(139...144)((139...140), (140...143), (143...144), "foo"), - InterpolatedStringNode(148...182)( + InterpolatedStringNode(148...158)( (148...158), [StringNode(168...170)(nil, (168...170), nil, " "), EmbeddedStatementsNode(170...173)((170...172), nil, (172...173)), diff --git a/test/yarp/snapshots/unparser/corpus/semantic/block.txt b/test/yarp/snapshots/unparser/corpus/semantic/block.txt index 4e8eb82fe074e2..16524948974d20 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/block.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/block.txt @@ -95,8 +95,8 @@ ProgramNode(0...148)( nil, (82...85), (85...86), - ArgumentsNode(86...109)( - [InterpolatedStringNode(86...109)( + ArgumentsNode(86...92)( + [InterpolatedStringNode(86...92)( (86...92), [StringNode(101...105)(nil, (101...105), nil, " b\n")], (105...109) @@ -131,8 +131,8 @@ ProgramNode(0...148)( nil, (118...121), (121...122), - ArgumentsNode(122...141)( - [InterpolatedStringNode(122...141)( + ArgumentsNode(122...128)( + [InterpolatedStringNode(122...128)( (122...128), [StringNode(133...137)(nil, (133...137), nil, " b\n")], (137...141) diff --git a/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt b/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt index 10345e1db54db4..14843a83a65114 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/dstr.txt @@ -1,62 +1,62 @@ ProgramNode(0...608)( [], StatementsNode(0...608)( - [InterpolatedStringNode(0...10)((0...5), [], (6...10)), - InterpolatedStringNode(11...23)((11...18), [], (19...23)), - InterpolatedStringNode(24...35)((24...30), [], (31...35)), - InterpolatedStringNode(36...49)((36...44), [], (45...49)), - InterpolatedStringNode(50...64)( + [InterpolatedStringNode(0...5)((0...5), [], (6...10)), + InterpolatedStringNode(11...18)((11...18), [], (19...23)), + InterpolatedStringNode(24...30)((24...30), [], (31...35)), + InterpolatedStringNode(36...44)((36...44), [], (45...49)), + InterpolatedStringNode(50...55)( (50...55), [StringNode(56...60)(nil, (56...60), nil, " a\n")], (60...64) ), - InterpolatedStringNode(65...81)( + InterpolatedStringNode(65...72)( (65...72), [StringNode(73...77)(nil, (73...77), nil, " a\n")], (77...81) ), - InterpolatedStringNode(82...102)( + InterpolatedStringNode(82...87)( (82...87), [StringNode(88...94)(nil, (88...94), nil, " a\n" + " "), EmbeddedStatementsNode(94...97)((94...96), nil, (96...97)), StringNode(97...98)(nil, (97...98), nil, "\n")], (98...102) ), - InterpolatedStringNode(103...124)( + InterpolatedStringNode(103...109)( (103...109), [StringNode(110...116)(nil, (110...116), nil, "a\n"), EmbeddedStatementsNode(116...119)((116...118), nil, (118...119)), StringNode(119...120)(nil, (119...120), nil, "\n")], (120...124) ), - InterpolatedStringNode(125...150)( + InterpolatedStringNode(125...131)( (125...131), [StringNode(132...138)(nil, (132...138), nil, "a\n"), EmbeddedStatementsNode(138...141)((138...140), nil, (140...141)), StringNode(141...146)(nil, (141...146), nil, "\n" + "b\n")], (146...150) ), - InterpolatedStringNode(151...172)( + InterpolatedStringNode(151...157)( (151...157), [StringNode(158...168)(nil, (158...168), nil, "a\n" + " b\n")], (168...172) ), - InterpolatedStringNode(173...190)( + InterpolatedStringNode(173...180)( (173...180), [StringNode(181...186)(nil, (181...186), nil, "a\n" + "\n" + "b\n")], (186...190) ), - InterpolatedStringNode(191...210)( + InterpolatedStringNode(191...198)( (191...198), [StringNode(199...206)(nil, (199...206), nil, " a\n" + "\n" + " b\n")], (206...210) ), - InterpolatedStringNode(211...229)( + InterpolatedStringNode(211...218)( (211...218), [StringNode(219...225)(nil, (219...225), nil, " a\\nb\n")], (225...229) ), - InterpolatedStringNode(230...251)( + InterpolatedStringNode(230...235)( (230...235), [EmbeddedStatementsNode(236...239)((236...238), nil, (238...239)), StringNode(239...242)(nil, (239...242), nil, "a\n" + " "), @@ -64,35 +64,33 @@ ProgramNode(0...608)( StringNode(245...247)(nil, (245...247), nil, "a\n")], (247...251) ), - InterpolatedStringNode(252...275)( + InterpolatedStringNode(252...257)( (252...257), [StringNode(258...260)(nil, (258...260), nil, " "), EmbeddedStatementsNode(260...263)((260...262), nil, (262...263)), StringNode(263...271)(nil, (263...271), nil, "\n" + " \#{}\n")], (271...275) ), - InterpolatedStringNode(276...296)( + InterpolatedStringNode(276...281)( (276...281), [StringNode(282...284)(nil, (282...284), nil, " a"), EmbeddedStatementsNode(284...287)((284...286), nil, (286...287)), StringNode(287...292)(nil, (287...292), nil, "b\n" + " c\n")], (292...296) ), - InterpolatedStringNode(297...314)( + InterpolatedStringNode(297...303)( (297...303), - [StringNode(304...306)(nil, (304...306), nil, ""), - EmbeddedStatementsNode(306...309)((306...308), nil, (308...309)), + [EmbeddedStatementsNode(306...309)((306...308), nil, (308...309)), StringNode(309...310)(nil, (309...310), nil, "\n")], (310...314) ), IfNode(315...349)( (315...317), TrueNode(318...322)(), - StatementsNode(325...346)( - [InterpolatedStringNode(325...346)( + StatementsNode(325...331)( + [InterpolatedStringNode(325...331)( (325...331), - [StringNode(332...336)(nil, (332...336), nil, ""), - EmbeddedStatementsNode(336...339)((336...338), nil, (338...339)), + [EmbeddedStatementsNode(336...339)((336...338), nil, (338...339)), StringNode(339...340)(nil, (339...340), nil, "\n")], (340...346) )] @@ -103,8 +101,8 @@ ProgramNode(0...608)( IfNode(351...386)( (351...353), TrueNode(354...358)(), - StatementsNode(361...383)( - [InterpolatedStringNode(361...383)( + StatementsNode(361...367)( + [InterpolatedStringNode(361...367)( (361...367), [StringNode(368...373)(nil, (368...373), nil, "b"), EmbeddedStatementsNode(373...376)((373...375), nil, (375...376)), @@ -118,11 +116,10 @@ ProgramNode(0...608)( IfNode(388...423)( (388...390), TrueNode(391...395)(), - StatementsNode(398...420)( - [InterpolatedStringNode(398...420)( + StatementsNode(398...404)( + [InterpolatedStringNode(398...404)( (398...404), - [StringNode(405...409)(nil, (405...409), nil, ""), - EmbeddedStatementsNode(409...412)((409...411), nil, (411...412)), + [EmbeddedStatementsNode(409...412)((409...411), nil, (411...412)), StringNode(412...414)(nil, (412...414), nil, "a\n")], (414...420) )] @@ -133,8 +130,8 @@ ProgramNode(0...608)( IfNode(425...464)( (425...427), TrueNode(428...432)(), - StatementsNode(435...461)( - [InterpolatedStringNode(435...461)( + StatementsNode(435...443)( + [InterpolatedStringNode(435...443)( (435...443), [StringNode(444...455)( nil, diff --git a/test/yarp/snapshots/unparser/corpus/semantic/while.txt b/test/yarp/snapshots/unparser/corpus/semantic/while.txt index 1e8be734ac1ae4..fd495fbd587488 100644 --- a/test/yarp/snapshots/unparser/corpus/semantic/while.txt +++ b/test/yarp/snapshots/unparser/corpus/semantic/while.txt @@ -102,8 +102,8 @@ ProgramNode(0...188)( nil, (106...107), (107...108), - ArgumentsNode(108...123)( - [InterpolatedStringNode(108...123)((108...114), [], (119...123))] + ArgumentsNode(108...114)( + [InterpolatedStringNode(108...114)((108...114), [], (119...123))] ), (114...115), BlockNode(116...130)( diff --git a/test/yarp/snapshots/whitequark/array_words_interp.txt b/test/yarp/snapshots/whitequark/array_words_interp.txt index e70dcc7a8908d2..3cc21323f7f910 100644 --- a/test/yarp/snapshots/whitequark/array_words_interp.txt +++ b/test/yarp/snapshots/whitequark/array_words_interp.txt @@ -3,7 +3,7 @@ ProgramNode(0...38)( StatementsNode(0...38)( [ArrayNode(0...14)( [StringNode(3...6)(nil, (3...6), nil, "foo"), - InterpolatedStringNode(0...13)( + InterpolatedStringNode(7...13)( nil, [EmbeddedStatementsNode(7...13)( (7...9), @@ -29,7 +29,7 @@ ProgramNode(0...38)( ), ArrayNode(16...38)( [StringNode(19...22)(nil, (19...22), nil, "foo"), - InterpolatedStringNode(0...37)( + InterpolatedStringNode(23...37)( nil, [EmbeddedStatementsNode(23...29)( (23...25), diff --git a/test/yarp/snapshots/whitequark/bug_heredoc_do.txt b/test/yarp/snapshots/whitequark/bug_heredoc_do.txt index b3ca8ffab1b2d7..947af0ece7d74c 100644 --- a/test/yarp/snapshots/whitequark/bug_heredoc_do.txt +++ b/test/yarp/snapshots/whitequark/bug_heredoc_do.txt @@ -6,8 +6,8 @@ ProgramNode(0...23)( nil, (0...1), nil, - ArgumentsNode(2...20)( - [InterpolatedStringNode(2...20)((2...10), [], (14...20))] + ArgumentsNode(2...10)( + [InterpolatedStringNode(2...10)((2...10), [], (14...20))] ), nil, BlockNode(11...23)([], nil, nil, (11...13), (20...23)), diff --git a/test/yarp/snapshots/whitequark/bug_interp_single.txt b/test/yarp/snapshots/whitequark/bug_interp_single.txt index abfa2dfe89be15..bd56c9998ae95e 100644 --- a/test/yarp/snapshots/whitequark/bug_interp_single.txt +++ b/test/yarp/snapshots/whitequark/bug_interp_single.txt @@ -11,7 +11,7 @@ ProgramNode(0...16)( (5...6) ), ArrayNode(8...16)( - [InterpolatedStringNode(0...15)( + [InterpolatedStringNode(11...15)( nil, [EmbeddedStatementsNode(11...15)( (11...13), diff --git a/test/yarp/snapshots/whitequark/dedenting_heredoc.txt b/test/yarp/snapshots/whitequark/dedenting_heredoc.txt index 144b17bcd7b1d9..10692b50cfebd3 100644 --- a/test/yarp/snapshots/whitequark/dedenting_heredoc.txt +++ b/test/yarp/snapshots/whitequark/dedenting_heredoc.txt @@ -1,13 +1,13 @@ -ProgramNode(0...327)( +ProgramNode(0...309)( [], - StatementsNode(0...327)( - [CallNode(0...28)( + StatementsNode(0...309)( + [CallNode(0...8)( nil, nil, (0...1), nil, - ArgumentsNode(2...28)( - [InterpolatedStringNode(2...28)( + ArgumentsNode(2...8)( + [InterpolatedStringNode(2...8)( (2...8), [StringNode(9...17)(nil, (9...17), nil, " x\n"), EmbeddedStatementsNode(17...25)( @@ -26,13 +26,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(29...55)( + CallNode(29...37)( nil, nil, (29...30), nil, - ArgumentsNode(31...55)( - [InterpolatedStringNode(31...55)( + ArgumentsNode(31...37)( + [InterpolatedStringNode(31...37)( (31...37), [StringNode(38...46)(nil, (38...46), nil, " x\n"), EmbeddedStatementsNode(46...52)( @@ -61,13 +61,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(56...78)( + CallNode(56...62)( nil, nil, (56...57), nil, - ArgumentsNode(58...78)( - [InterpolatedStringNode(58...78)( + ArgumentsNode(58...62)( + [InterpolatedStringNode(58...62)( (58...62), [StringNode(63...76)(nil, (63...76), nil, "x\n" + "y\n")], (76...78) @@ -78,13 +78,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(79...97)( + CallNode(79...85)( nil, nil, (79...80), nil, - ArgumentsNode(81...97)( - [InterpolatedStringNode(81...97)( + ArgumentsNode(81...85)( + [InterpolatedStringNode(81...85)( (81...85), [StringNode(86...95)(nil, (86...95), nil, "\tx\n" + "y\n")], (95...97) @@ -95,13 +95,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(98...124)( + CallNode(98...104)( nil, nil, (98...99), nil, - ArgumentsNode(100...124)( - [InterpolatedStringNode(100...124)( + ArgumentsNode(100...104)( + [InterpolatedStringNode(100...104)( (100...104), [StringNode(105...122)(nil, (105...122), nil, "x\n" + "y\n")], (122...124) @@ -112,13 +112,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(125...148)( + CallNode(125...131)( nil, nil, (125...126), nil, - ArgumentsNode(127...148)( - [InterpolatedStringNode(127...148)( + ArgumentsNode(127...131)( + [InterpolatedStringNode(127...131)( (127...131), [StringNode(132...146)(nil, (132...146), nil, "\tx\n" + "y\n")], (146...148) @@ -129,13 +129,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(149...170)( + CallNode(149...155)( nil, nil, (149...150), nil, - ArgumentsNode(151...170)( - [InterpolatedStringNode(151...170)( + ArgumentsNode(151...155)( + [InterpolatedStringNode(151...155)( (151...155), [StringNode(156...168)(nil, (156...168), nil, " x\n" + "\ty\n")], (168...170) @@ -146,13 +146,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(171...193)( + CallNode(171...177)( nil, nil, (171...172), nil, - ArgumentsNode(173...193)( - [InterpolatedStringNode(173...193)( + ArgumentsNode(173...177)( + [InterpolatedStringNode(173...177)( (173...177), [StringNode(178...191)(nil, (178...191), nil, " x\n" + " y\n")], (191...193) @@ -163,26 +163,26 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(194...205)( + CallNode(194...200)( nil, nil, (194...195), nil, - ArgumentsNode(196...205)( - [InterpolatedStringNode(196...205)((196...200), [], (201...205))] + ArgumentsNode(196...200)( + [InterpolatedStringNode(196...200)((196...200), [], (201...205))] ), nil, nil, 0, "p" ), - CallNode(206...222)( + CallNode(206...212)( nil, nil, (206...207), nil, - ArgumentsNode(208...222)( - [InterpolatedStringNode(208...222)( + ArgumentsNode(208...212)( + [InterpolatedStringNode(208...212)( (208...212), [StringNode(213...220)( nil, @@ -198,13 +198,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(223...241)( + CallNode(223...229)( nil, nil, (223...224), nil, - ArgumentsNode(225...241)( - [InterpolatedStringNode(225...241)( + ArgumentsNode(225...229)( + [InterpolatedStringNode(225...229)( (225...229), [StringNode(230...239)( nil, @@ -220,13 +220,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(242...261)( + CallNode(242...248)( nil, nil, (242...243), nil, - ArgumentsNode(244...261)( - [InterpolatedStringNode(244...261)( + ArgumentsNode(244...248)( + [InterpolatedStringNode(244...248)( (244...248), [StringNode(249...259)(nil, (249...259), nil, "x\n" + " y\n")], (259...261) @@ -237,13 +237,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(262...275)( + CallNode(262...268)( nil, nil, (262...263), nil, - ArgumentsNode(264...275)( - [InterpolatedStringNode(264...275)( + ArgumentsNode(264...268)( + [InterpolatedStringNode(264...268)( (264...268), [StringNode(269...273)(nil, (269...273), nil, "x\n")], (273...275) @@ -254,13 +254,13 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(276...290)( + CallNode(276...282)( nil, nil, (276...277), nil, - ArgumentsNode(278...290)( - [InterpolatedStringNode(278...290)( + ArgumentsNode(278...282)( + [InterpolatedStringNode(278...282)( (278...282), [StringNode(283...288)(nil, (283...288), nil, "ð\n")], (288...290) @@ -271,26 +271,26 @@ ProgramNode(0...327)( 0, "p" ), - CallNode(291...300)( + CallNode(291...297)( nil, nil, (291...292), nil, - ArgumentsNode(293...300)( - [InterpolatedStringNode(293...300)((293...297), [], (298...300))] + ArgumentsNode(293...297)( + [InterpolatedStringNode(293...297)((293...297), [], (298...300))] ), nil, nil, 0, "p" ), - CallNode(301...327)( + CallNode(301...309)( nil, nil, (301...302), nil, - ArgumentsNode(303...327)( - [InterpolatedXStringNode(303...327)( + ArgumentsNode(303...309)( + [InterpolatedXStringNode(303...309)( (303...309), [StringNode(310...318)(nil, (310...318), nil, " x\n"), EmbeddedStatementsNode(318...324)( diff --git a/test/yarp/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt b/test/yarp/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt index 57cd4345c41dd9..f076eed1fec25a 100644 --- a/test/yarp/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt +++ b/test/yarp/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt @@ -1,7 +1,7 @@ -ProgramNode(0...27)( +ProgramNode(0...8)( [], - StatementsNode(0...27)( - [InterpolatedStringNode(0...27)( + StatementsNode(0...8)( + [InterpolatedStringNode(0...8)( (0...8), [StringNode(9...23)(nil, (9...23), nil, "baz\\\n" + "qux\n")], (23...27) diff --git a/test/yarp/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt b/test/yarp/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt index eea236db485ff3..ce1617b1ad3026 100644 --- a/test/yarp/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt +++ b/test/yarp/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt @@ -1,7 +1,7 @@ -ProgramNode(0...26)( +ProgramNode(0...8)( [], - StatementsNode(0...26)( - [InterpolatedStringNode(0...26)( + StatementsNode(0...8)( + [InterpolatedStringNode(0...8)( (0...8), [StringNode(9...22)(nil, (9...22), nil, "baz\\\n" + "qux\n")], (22...26) diff --git a/test/yarp/snapshots/whitequark/heredoc.txt b/test/yarp/snapshots/whitequark/heredoc.txt index ca45278d3cd561..c61829ebd4eca1 100644 --- a/test/yarp/snapshots/whitequark/heredoc.txt +++ b/test/yarp/snapshots/whitequark/heredoc.txt @@ -1,17 +1,17 @@ -ProgramNode(0...66)( +ProgramNode(0...52)( [], - StatementsNode(0...66)( - [InterpolatedStringNode(0...22)( + StatementsNode(0...52)( + [InterpolatedStringNode(0...8)( (0...8), [StringNode(9...17)(nil, (9...17), nil, "foo\n" + "bar\n")], (17...22) ), - InterpolatedStringNode(23...43)( + InterpolatedStringNode(23...29)( (23...29), [StringNode(30...38)(nil, (30...38), nil, "foo\n" + "bar\n")], (38...43) ), - InterpolatedXStringNode(44...66)( + InterpolatedXStringNode(44...52)( (44...52), [StringNode(53...61)(nil, (53...61), nil, "foo\n" + "bar\n")], (61...66) diff --git a/test/yarp/snapshots/whitequark/interp_digit_var.txt b/test/yarp/snapshots/whitequark/interp_digit_var.txt index 283ebb19f2ff9f..45d18f9ef22e15 100644 --- a/test/yarp/snapshots/whitequark/interp_digit_var.txt +++ b/test/yarp/snapshots/whitequark/interp_digit_var.txt @@ -1,6 +1,6 @@ -ProgramNode(1...444)( +ProgramNode(1...433)( [], - StatementsNode(1...444)( + StatementsNode(1...433)( [StringNode(1...6)((1...2), (2...5), (5...6), "\#@1"), StringNode(9...15)((9...10), (10...14), (14...15), "\#@@1"), ArrayNode(18...25)( @@ -89,32 +89,32 @@ ProgramNode(1...444)( SymbolNode(296...303)((296...298), (298...302), (302...303), "\#@@1"), XStringNode(306...311)((306...307), (307...310), (310...311), "\#@1"), XStringNode(314...320)((314...315), (315...319), (319...320), "\#@@1"), - InterpolatedStringNode(322...341)( + InterpolatedStringNode(322...331)( (322...331), [StringNode(332...336)(nil, (332...336), nil, "\#@1\n")], (336...341) ), - InterpolatedStringNode(342...362)( + InterpolatedStringNode(342...351)( (342...351), [StringNode(352...357)(nil, (352...357), nil, "\#@@1\n")], (357...362) ), - InterpolatedStringNode(363...382)( + InterpolatedStringNode(363...372)( (363...372), [StringNode(373...377)(nil, (373...377), nil, "\#@1\n")], (377...382) ), - InterpolatedStringNode(383...403)( + InterpolatedStringNode(383...392)( (383...392), [StringNode(393...398)(nil, (393...398), nil, "\#@@1\n")], (398...403) ), - InterpolatedXStringNode(404...423)( + InterpolatedXStringNode(404...413)( (404...413), [StringNode(414...418)(nil, (414...418), nil, "\#@1\n")], (418...423) ), - InterpolatedXStringNode(424...444)( + InterpolatedXStringNode(424...433)( (424...433), [StringNode(434...439)(nil, (434...439), nil, "\#@@1\n")], (439...444) diff --git a/test/yarp/snapshots/whitequark/parser_bug_640.txt b/test/yarp/snapshots/whitequark/parser_bug_640.txt index 7af6f48f95361d..5ca73c08a5739a 100644 --- a/test/yarp/snapshots/whitequark/parser_bug_640.txt +++ b/test/yarp/snapshots/whitequark/parser_bug_640.txt @@ -1,9 +1,9 @@ -ProgramNode(0...24)( +ProgramNode(0...6)( [], - StatementsNode(0...24)( - [InterpolatedStringNode(0...24)( + StatementsNode(0...6)( + [InterpolatedStringNode(0...6)( (0...6), - [StringNode(7...20)(nil, (7...20), nil, "baz\n" + "qux\n")], + [StringNode(7...20)(nil, (7...20), nil, "bazqux\n")], (20...24) )] ) diff --git a/test/yarp/snapshots/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt b/test/yarp/snapshots/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt index b9b0a9ca4dd275..d2fe26f163da54 100644 --- a/test/yarp/snapshots/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt +++ b/test/yarp/snapshots/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt @@ -1,10 +1,9 @@ -ProgramNode(0...19)( +ProgramNode(0...7)( [], - StatementsNode(0...19)( - [InterpolatedStringNode(0...19)( + StatementsNode(0...7)( + [InterpolatedStringNode(0...7)( (0...7), - [StringNode(8...10)(nil, (8...10), nil, ""), - EmbeddedStatementsNode(10...13)((10...12), nil, (12...13)), + [EmbeddedStatementsNode(10...13)((10...12), nil, (12...13)), StringNode(13...14)(nil, (13...14), nil, "\n")], (14...19) )] diff --git a/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt b/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt index 2802c084e43a78..16db486beb243e 100644 --- a/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt +++ b/test/yarp/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt @@ -1,15 +1,15 @@ ProgramNode(0...210)( [], StatementsNode(0...210)( - [StringNode(0...6)((0...1), (1...5), (5...6), "a\n" + "b"), + [StringNode(0...6)((0...1), (1...5), (5...6), "ab"), ArrayNode(8...16)( - [SymbolNode(11...15)(nil, (11...15), nil, "a\n" + "b")], + [SymbolNode(11...15)(nil, (11...15), nil, "ab")], (8...11), (15...16) ), - StringNode(18...26)((18...21), (21...25), (25...26), "a\n" + "b"), + StringNode(18...26)((18...21), (21...25), (25...26), "ab"), ArrayNode(28...36)( - [StringNode(31...35)(nil, (31...35), nil, "a\n" + "b")], + [StringNode(31...35)(nil, (31...35), nil, "ab")], (28...31), (35...36) ), @@ -19,21 +19,15 @@ ProgramNode(0...210)( (45...46) ), StringNode(48...56)((48...51), (51...55), (55...56), "a\\\n" + "b"), - RegularExpressionNode(58...66)( - (58...61), - (61...65), - (65...66), - "a\n" + "b", - 0 - ), - SymbolNode(68...76)((68...71), (71...75), (75...76), "a\n" + "b"), + RegularExpressionNode(58...66)((58...61), (61...65), (65...66), "ab", 0), + SymbolNode(68...76)((68...71), (71...75), (75...76), "ab"), ArrayNode(78...86)( [StringNode(81...85)(nil, (81...85), nil, "a\\\n" + "b")], (78...81), (85...86) ), - XStringNode(88...96)((88...91), (91...95), (95...96), "a\n" + "b"), - StringNode(98...105)((98...100), (100...104), (104...105), "a\n" + "b"), + XStringNode(88...96)((88...91), (91...95), (95...96), "ab"), + StringNode(98...105)((98...100), (100...104), (104...105), "ab"), StringNode(107...113)( (107...108), (108...112), @@ -44,31 +38,26 @@ ProgramNode(0...210)( (115...116), (116...120), (120...121), - "a\n" + "b", + "ab", 0 ), - SymbolNode(123...130)(nil, (125...129), nil, "a\n" + "b"), - SymbolNode(132...139)((132...134), (134...138), (138...139), "a\n" + "b"), - InterpolatedStringNode(141...161)( + SymbolNode(123...130)(nil, (125...129), nil, "ab"), + SymbolNode(132...139)((132...134), (134...138), (138...139), "ab"), + InterpolatedStringNode(141...150)( (141...150), - [StringNode(151...156)(nil, (151...156), nil, "a\n" + "b\n")], + [StringNode(151...156)(nil, (151...156), nil, "ab\n")], (156...161) ), - InterpolatedStringNode(162...182)( + InterpolatedStringNode(162...171)( (162...171), [StringNode(172...177)(nil, (172...177), nil, "a\\\n" + "b\n")], (177...182) ), - InterpolatedXStringNode(183...203)( + InterpolatedXStringNode(183...192)( (183...192), - [StringNode(193...198)(nil, (193...198), nil, "a\n" + "b\n")], + [StringNode(193...198)(nil, (193...198), nil, "ab\n")], (198...203) ), - XStringNode(204...210)( - (204...205), - (205...209), - (209...210), - "a\n" + "b" - )] + XStringNode(204...210)((204...205), (205...209), (209...210), "ab")] ) ) diff --git a/test/yarp/snapshots/whitequark/ruby_bug_11989.txt b/test/yarp/snapshots/whitequark/ruby_bug_11989.txt index fb5f7330c96878..847bc83fac538c 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_11989.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_11989.txt @@ -1,15 +1,15 @@ -ProgramNode(0...21)( +ProgramNode(0...8)( [], - StatementsNode(0...21)( - [CallNode(0...21)( + StatementsNode(0...8)( + [CallNode(0...8)( nil, nil, (0...1), nil, - ArgumentsNode(2...21)( - [InterpolatedStringNode(2...21)( + ArgumentsNode(2...8)( + [InterpolatedStringNode(2...8)( (2...8), - [StringNode(9...19)(nil, (9...19), nil, "x\n" + " y\n")], + [StringNode(9...19)(nil, (9...19), nil, "x\n" + " y\n")], (19...21) )] ), diff --git a/test/yarp/snapshots/whitequark/ruby_bug_11990.txt b/test/yarp/snapshots/whitequark/ruby_bug_11990.txt index 1a1a68796e2db9..379407bffb1c32 100644 --- a/test/yarp/snapshots/whitequark/ruby_bug_11990.txt +++ b/test/yarp/snapshots/whitequark/ruby_bug_11990.txt @@ -8,7 +8,7 @@ ProgramNode(0...12)( nil, ArgumentsNode(2...12)( [StringConcatNode(2...12)( - InterpolatedStringNode(2...19)( + InterpolatedStringNode(2...6)( (2...6), [StringNode(13...17)(nil, (13...17), nil, "x\n")], (17...19) diff --git a/test/yarp/snapshots/whitequark/slash_newline_in_heredocs.txt b/test/yarp/snapshots/whitequark/slash_newline_in_heredocs.txt index facffc7a2a150d..7485f4c8bdba39 100644 --- a/test/yarp/snapshots/whitequark/slash_newline_in_heredocs.txt +++ b/test/yarp/snapshots/whitequark/slash_newline_in_heredocs.txt @@ -1,19 +1,14 @@ -ProgramNode(0...56)( +ProgramNode(0...33)( [], - StatementsNode(0...56)( - [InterpolatedStringNode(0...27)( + StatementsNode(0...33)( + [InterpolatedStringNode(0...4)( (0...4), - [StringNode(5...25)( - nil, - (5...25), - nil, - " 1 \n" + " 2\n" + " 3\n" - )], + [StringNode(5...25)(nil, (5...25), nil, " 1 2\n" + " 3\n")], (25...27) ), - InterpolatedStringNode(29...56)( + InterpolatedStringNode(29...33)( (29...33), - [StringNode(34...54)(nil, (34...54), nil, "1 \n" + "2\n" + "3\n")], + [StringNode(34...54)(nil, (34...54), nil, "1 2\n" + "3\n")], (54...56) )] ) diff --git a/yarp/serialize.c b/yarp/serialize.c index fbdf337f8dab1f..1960cd1fa9f533 100644 --- a/yarp/serialize.c +++ b/yarp/serialize.c @@ -1526,7 +1526,7 @@ void yp_serialize_comment(yp_parser_t *parser, yp_comment_t *comment, yp_buffer_ } void yp_serialize_comment_list(yp_parser_t *parser, yp_list_t list, yp_buffer_t *buffer) { - yp_buffer_append_u32(buffer, yp_list_size(&list)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(yp_list_size(&list))); yp_comment_t *comment; for (comment = (yp_comment_t *) list.head; comment != NULL; comment = (yp_comment_t *) comment->node.next) { @@ -1546,7 +1546,7 @@ void yp_serialize_diagnostic(yp_parser_t *parser, yp_diagnostic_t *diagnostic, y } void yp_serialize_diagnostic_list(yp_parser_t *parser, yp_list_t list, yp_buffer_t *buffer) { - yp_buffer_append_u32(buffer, yp_list_size(&list)); + yp_buffer_append_u32(buffer, yp_sizet_to_u32(yp_list_size(&list))); yp_diagnostic_t *diagnostic; for (diagnostic = (yp_diagnostic_t *) list.head; diagnostic != NULL; diagnostic = (yp_diagnostic_t *) diagnostic->node.next) { diff --git a/yarp/unescape.c b/yarp/unescape.c index 51ab2b3597a1b3..f1c40347a41e6f 100644 --- a/yarp/unescape.c +++ b/yarp/unescape.c @@ -180,22 +180,6 @@ unescape_char(const unsigned char value, const unsigned char flags) { static const char * unescape(char *dest, size_t *dest_length, const char *backslash, const char *end, yp_list_t *error_list, const unsigned char flags, bool write_to_str) { switch (backslash[1]) { - // \a \b \e \f \n \r \s \t \v - case '\r': { - // if this is an \r\n we need to escape both - if (write_to_str) { - dest[(*dest_length)++] = (char) unescape_char(unescape_chars[(unsigned char) backslash[1]], flags); - } - - if (backslash + 2 < end && backslash[2] == '\n') { - if (write_to_str) { - dest[(*dest_length)++] = (char) unescape_char(unescape_chars[(unsigned char) backslash[2]], flags); - } - return backslash + 3; - } - - return backslash + 2; - } case 'a': case 'b': case 'e': @@ -398,14 +382,23 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid meta escape sequence"); return backslash + 3; } + // \n + case '\n': + return backslash + 2; + // \r + case '\r': + if (backslash + 2 < end && backslash[2] == '\n') { + return backslash + 3; + } + + /* fallthrough */ // In this case we're escaping something that doesn't need escaping. - default: - { - if (write_to_str) { - dest[(*dest_length)++] = backslash[1]; - } - return backslash + 2; + default: { + if (write_to_str) { + dest[(*dest_length)++] = backslash[1]; } + return backslash + 2; + } } } @@ -438,26 +431,24 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end // \c? or \C-? delete, ASCII 7Fh (DEL) // YP_EXPORTED_FUNCTION void -yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t length, yp_string_t *string, yp_unescape_type_t unescape_type, yp_list_t *error_list) { +yp_unescape_manipulate_string(yp_parser_t *parser, yp_string_t *string, yp_unescape_type_t unescape_type, yp_list_t *error_list) { if (unescape_type == YP_UNESCAPE_NONE) { // If we're not unescaping then we can reference the source directly. - yp_string_shared_init(string, value, value + length); return; } - const char *backslash = yp_memchr(value, '\\', length, parser->encoding_changed, &parser->encoding); + const char *backslash = yp_memchr(string->source, '\\', string->length, parser->encoding_changed, &parser->encoding); if (backslash == NULL) { // Here there are no escapes, so we can reference the source directly. - yp_string_shared_init(string, value, value + length); return; } // Here we have found an escape character, so we need to handle all escapes // within the string. - char *allocated = malloc(length); + char *allocated = malloc(string->length); if (allocated == NULL) { - yp_diagnostic_list_append(error_list, value, value + length, "Failed to allocate memory for unescaping."); + yp_diagnostic_list_append(error_list, string->source, string->source + string->length, "Failed to allocate memory for unescaping."); return; } @@ -468,13 +459,13 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len // This is the current position in the source string that we're looking at. // It's going to move along behind the backslash so that we can copy each // segment of the string that doesn't contain an escape. - const char *cursor = value; - const char *end = value + length; + const char *cursor = string->source; + const char *end = string->source + string->length; // For each escape found in the source string, we will handle it and update // the moving cursor->backslash window. while (backslash != NULL && backslash + 1 < end) { - assert(dest_length < length); + assert(dest_length < string->length); // This is the size of the segment of the string from the previous escape // or the start of the string to the current escape. @@ -520,6 +511,10 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len cursor = end; } + // If the string was already allocated, then we need to free that memory + // here. That's because we're about to override it with the escaped string. + yp_string_free(string); + // We also need to update the length at the end. This is because every escape // reduces the length of the final string, and we don't want garbage at the // end. @@ -530,13 +525,12 @@ YP_EXPORTED_FUNCTION bool yp_unescape_string(const char *start, size_t length, yp_unescape_type_t unescape_type, yp_string_t *result) { bool success; - yp_list_t error_list; - yp_list_init(&error_list); - yp_parser_t parser; yp_parser_init(&parser, start, length, ""); - yp_unescape_manipulate_string(&parser, start, length, result, unescape_type, &error_list); + yp_list_t error_list = YP_LIST_EMPTY; + yp_string_shared_init(result, start, start + length); + yp_unescape_manipulate_string(&parser, result, unescape_type, &error_list); success = yp_list_empty_p(&error_list); yp_list_free(&error_list); diff --git a/yarp/unescape.h b/yarp/unescape.h index b76ac9f7a4158c..d3c68fb015b0dd 100644 --- a/yarp/unescape.h +++ b/yarp/unescape.h @@ -31,7 +31,7 @@ typedef enum { // Unescape the contents of the given token into the given string using the // given unescape mode. -YP_EXPORTED_FUNCTION void yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t length, yp_string_t *string, yp_unescape_type_t unescape_type, yp_list_t *error_list); +YP_EXPORTED_FUNCTION void yp_unescape_manipulate_string(yp_parser_t *parser, yp_string_t *string, yp_unescape_type_t unescape_type, yp_list_t *error_list); // Accepts a source string and a type of unescaping and returns the unescaped version. // The caller must yp_string_free(result); after calling this function. diff --git a/yarp/util/yp_constant_pool.h b/yarp/util/yp_constant_pool.h index 992f6a57a51b7c..3726ecc44a28d6 100644 --- a/yarp/util/yp_constant_pool.h +++ b/yarp/util/yp_constant_pool.h @@ -51,6 +51,9 @@ typedef struct { size_t capacity; } yp_constant_pool_t; +// Define an empty constant pool. +#define YP_CONSTANT_POOL_EMPTY ((yp_constant_pool_t) { .constants = NULL, .size = 0, .capacity = 0 }) + // Initialize a new constant pool with a given capacity. bool yp_constant_pool_init(yp_constant_pool_t *pool, size_t capacity); diff --git a/yarp/util/yp_list.c b/yarp/util/yp_list.c index 9945e72ffe1f76..e03dd79d8d89a8 100644 --- a/yarp/util/yp_list.c +++ b/yarp/util/yp_list.c @@ -1,28 +1,15 @@ #include "yarp/util/yp_list.h" -// Initializes a new list. -YP_EXPORTED_FUNCTION void -yp_list_init(yp_list_t *list) { - *list = (yp_list_t) { .head = NULL, .tail = NULL }; -} - // Returns true if the given list is empty. YP_EXPORTED_FUNCTION bool yp_list_empty_p(yp_list_t *list) { return list->head == NULL; } -YP_EXPORTED_FUNCTION uint32_t +// Returns the size of the list. +YP_EXPORTED_FUNCTION size_t yp_list_size(yp_list_t *list) { - yp_list_node_t *node = list->head; - uint32_t length = 0; - - while (node != NULL) { - length++; - node = node->next; - } - - return length; + return list->size; } // Append a node to the given list. @@ -33,7 +20,9 @@ yp_list_append(yp_list_t *list, yp_list_node_t *node) { } else { list->tail->next = node; } + list->tail = node; + list->size++; } // Deallocate the internal state of the given list. @@ -47,4 +36,6 @@ yp_list_free(yp_list_t *list) { free(node); node = next; } + + list->size = 0; } diff --git a/yarp/util/yp_list.h b/yarp/util/yp_list.h index 46f67bd96fdf6a..205a5a7eab4a8f 100644 --- a/yarp/util/yp_list.h +++ b/yarp/util/yp_list.h @@ -15,9 +15,7 @@ // int value; // } yp_int_node_t; // -// yp_list_t list; -// yp_list_init(&list); -// +// yp_list_t list = YP_LIST_EMPTY; // yp_int_node_t *node = malloc(sizeof(yp_int_node_t)); // node->value = 5; // @@ -45,18 +43,20 @@ typedef struct yp_list_node { // 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 { + size_t size; yp_list_node_t *head; yp_list_node_t *tail; } yp_list_t; -// Initializes a new list. -YP_EXPORTED_FUNCTION void yp_list_init(yp_list_t *list); +// This represents an empty list. It's used to initialize a stack-allocated list +// as opposed to a method call. +#define YP_LIST_EMPTY ((yp_list_t) { .size = 0, .head = NULL, .tail = NULL }) // Returns true if the given list is empty. YP_EXPORTED_FUNCTION bool yp_list_empty_p(yp_list_t *list); -// Returns the size of the list in O(n) time. -YP_EXPORTED_FUNCTION uint32_t yp_list_size(yp_list_t *list); +// Returns the size of the list. +YP_EXPORTED_FUNCTION size_t yp_list_size(yp_list_t *list); // Append a node to the given list. void yp_list_append(yp_list_t *list, yp_list_node_t *node); diff --git a/yarp/util/yp_newline_list.h b/yarp/util/yp_newline_list.h index 91dbd64a82c531..095acd5168e840 100644 --- a/yarp/util/yp_newline_list.h +++ b/yarp/util/yp_newline_list.h @@ -35,6 +35,10 @@ typedef struct { size_t column; } yp_line_column_t; +#define YP_NEWLINE_LIST_EMPTY ((yp_newline_list_t) { \ + .start = NULL, .offsets = NULL, .size = 0, .capacity = 0, .last_offset = 0, .last_index = 0 \ +}) + // Initialize a new newline list with the given capacity. Returns true if the // allocation of the offsets succeeds, otherwise returns false. bool yp_newline_list_init(yp_newline_list_t *list, const char *start, size_t capacity); diff --git a/yarp/util/yp_state_stack.c b/yarp/util/yp_state_stack.c index 76c2eafceadaea..7ff95bd61166a5 100644 --- a/yarp/util/yp_state_stack.c +++ b/yarp/util/yp_state_stack.c @@ -1,11 +1,5 @@ #include "yarp/util/yp_state_stack.h" -// Initializes the state stack to an empty stack. -void -yp_state_stack_init(yp_state_stack_t *stack) { - *stack = 0; -} - // Pushes a value onto the stack. void yp_state_stack_push(yp_state_stack_t *stack, bool value) { diff --git a/yarp/util/yp_state_stack.h b/yarp/util/yp_state_stack.h index 2f2e2d322e5406..69d8d7d54b4322 100644 --- a/yarp/util/yp_state_stack.h +++ b/yarp/util/yp_state_stack.h @@ -10,7 +10,7 @@ typedef uint32_t yp_state_stack_t; // Initializes the state stack to an empty stack. -void yp_state_stack_init(yp_state_stack_t *stack); +#define YP_STATE_STACK_EMPTY ((yp_state_stack_t) 0) // Pushes a value onto the stack. void yp_state_stack_push(yp_state_stack_t *stack, bool value); diff --git a/yarp/yarp.c b/yarp/yarp.c index e474a46d081753..675d5e1cb26774 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -2706,6 +2706,10 @@ yp_interpolated_string_node_create(yp_parser_t *parser, const yp_token_t *openin // Append a part to an InterpolatedStringNode node. static inline void yp_interpolated_string_node_append(yp_interpolated_string_node_t *node, yp_node_t *part) { + if (node->parts.size == 0 && node->opening_loc.start == NULL) { + node->base.location.start = part->location.start; + } + yp_node_list_append(&node->parts, part); node->base.location.end = part->location.end; } @@ -3934,10 +3938,10 @@ yp_symbol_node_label_create(yp_parser_t *parser, const yp_token_t *token) { yp_token_t label = { .type = YP_TOKEN_LABEL, .start = token->start, .end = token->end - 1 }; node = yp_symbol_node_create(parser, &opening, &label, &closing); - ptrdiff_t length = label.end - label.start; - assert(length >= 0); + assert((label.end - label.start) >= 0); + yp_string_shared_init(&node->unescaped, label.start, label.end); - yp_unescape_manipulate_string(parser, label.start, (size_t) length, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list); + yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list); break; } case YP_TOKEN_MISSING: { @@ -7203,11 +7207,16 @@ parser_lex(yp_parser_t *parser) { break; } case '\\': { - // If we hit escapes, then we need to treat the next token - // literally. In this case we'll skip past the next character and - // find the next breakpoint. - if (breakpoint[1] == '\n') { + // If we hit an escape, then we need to skip past + // however many characters the escape takes up. However + // it's important that if \n or \r\n are escaped that we + // stop looping before the newline and not after the + // newline so that we can still potentially find the + // terminator of the heredoc. + if (breakpoint + 1 < parser->end && breakpoint[1] == '\n') { breakpoint++; + } else if (breakpoint + 2 < parser->end && breakpoint[1] == '\r' && breakpoint[2] == '\n') { + breakpoint += 2; } else { yp_unescape_type_t unescape_type = (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL; size_t difference = yp_unescape_calculate_difference(breakpoint, parser->end, unescape_type, false, &parser->error_list); @@ -7218,6 +7227,7 @@ parser_lex(yp_parser_t *parser) { breakpoint = yp_strpbrk(parser, breakpoint + difference, breakpoints, parser->end - (breakpoint + difference)); } + break; } case '#': { @@ -7264,10 +7274,10 @@ static yp_regular_expression_node_t * yp_regular_expression_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) { yp_regular_expression_node_t *node = yp_regular_expression_node_create(parser, opening, content, closing); - ptrdiff_t length = content->end - content->start; - assert(length >= 0); + assert((content->end - content->start) >= 0); + yp_string_shared_init(&node->unescaped, content->start, content->end); - yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list); + yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list); return node; } @@ -7275,10 +7285,10 @@ static yp_symbol_node_t * yp_symbol_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) { yp_symbol_node_t *node = yp_symbol_node_create(parser, opening, content, closing); - ptrdiff_t length = content->end - content->start; - assert(length >= 0); + assert((content->end - content->start) >= 0); + yp_string_shared_init(&node->unescaped, content->start, content->end); - yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list); + yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list); return node; } @@ -7286,10 +7296,10 @@ static yp_string_node_t * yp_string_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing, yp_unescape_type_t unescape_type) { yp_string_node_t *node = yp_string_node_create(parser, opening, content, closing); - ptrdiff_t length = content->end - content->start; - assert(length >= 0); + assert((content->end - content->start) >= 0); + yp_string_shared_init(&node->unescaped, content->start, content->end); - yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, unescape_type, &parser->error_list); + yp_unescape_manipulate_string(parser, &node->unescaped, unescape_type, &parser->error_list); return node; } @@ -7297,10 +7307,10 @@ static yp_x_string_node_t * yp_xstring_node_create_and_unescape(yp_parser_t *parser, const yp_token_t *opening, const yp_token_t *content, const yp_token_t *closing) { yp_x_string_node_t *node = yp_xstring_node_create(parser, opening, content, closing); - ptrdiff_t length = content->end - content->start; - assert(length >= 0); + assert((content->end - content->start) >= 0); + yp_string_shared_init(&node->unescaped, content->start, content->end); - yp_unescape_manipulate_string(parser, content->start, (size_t) length, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list); + yp_unescape_manipulate_string(parser, &node->unescaped, YP_UNESCAPE_ALL, &parser->error_list); return node; } @@ -9172,7 +9182,12 @@ parse_string_part(yp_parser_t *parser) { yp_unescape_type_t unescape_type = YP_UNESCAPE_ALL; if (parser->lex_modes.current->mode == YP_LEX_HEREDOC) { - if (parser->lex_modes.current->as.heredoc.quote == YP_HEREDOC_QUOTE_SINGLE) { + if (parser->lex_modes.current->as.heredoc.indent == YP_HEREDOC_INDENT_TILDE) { + // If we're in a tilde heredoc, we want to unescape it later + // because we don't want unescaped newlines to disappear + // before we handle them in the dedent. + unescape_type = YP_UNESCAPE_NONE; + } else if (parser->lex_modes.current->as.heredoc.quote == YP_HEREDOC_QUOTE_SINGLE) { unescape_type = YP_UNESCAPE_MINIMAL; } } @@ -9545,14 +9560,30 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu int common_whitespace; if ((common_whitespace = parse_heredoc_common_whitespace(parser, nodes)) <= 0) return; - // Iterate over all nodes, and trim whitespace accordingly. - for (size_t index = 0; index < nodes->size; index++) { - yp_node_t *node = nodes->nodes[index]; - if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) continue; + // The next node should be dedented if it's the first node in the list or if + // if follows a string node. + 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. + size_t write_index = 0; + + for (size_t read_index = 0; read_index < nodes->size; read_index++) { + yp_node_t *node = nodes->nodes[read_index]; + + // We're not manipulating child nodes that aren't strings. In this case + // we'll skip past it and indicate that the subsequent node should not + // be dedented. + if (!YP_NODE_TYPE_P(node, YP_NODE_STRING_NODE)) { + nodes->nodes[write_index++] = node; + dedent_next = false; + continue; + } // Get a reference to the string struct that is being held by the string // node. This is the value we're going to actual manipulate. - yp_string_t *string = &((yp_string_node_t *) node)->unescaped; + yp_string_t *string = &(((yp_string_node_t *) node)->unescaped); yp_string_ensure_owned(string); // Now get the bounds of the existing string. We'll use this as a @@ -9568,7 +9599,6 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu // whitespace, so we'll maintain a pointer to the current position in the // string that we're writing to. char *dest_cursor = source_start; - bool dedent_next = (index == 0) || YP_NODE_TYPE_P(nodes->nodes[index - 1], YP_NODE_STRING_NODE); while (source_cursor < source_end) { // If we need to dedent the next element within the heredoc or the next @@ -9613,8 +9643,20 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu dedent_next = true; } - string->length = dest_length; + // We only want to write this node into the list if it has any content. + if (dest_length == 0) { + yp_node_destroy(parser, node); + } else { + string->length = dest_length; + yp_unescape_manipulate_string(parser, string, (quote == YP_HEREDOC_QUOTE_SINGLE) ? YP_UNESCAPE_MINIMAL : YP_UNESCAPE_ALL, &parser->error_list); + nodes->nodes[write_index++] = node; + } + + // We always dedent the next node if it follows a string node. + dedent_next = true; } + + nodes->size = write_index; } static yp_node_t * @@ -10673,12 +10715,15 @@ parse_expression_prefix(yp_parser_t *parser, yp_binding_power_t binding_power) { lex_state_set(parser, YP_LEX_STATE_END); expect(parser, YP_TOKEN_HEREDOC_END, "Expected a closing delimiter for heredoc."); + if (quote == YP_HEREDOC_QUOTE_BACKTICK) { assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_X_STRING_NODE)); yp_interpolated_xstring_node_closing_set(((yp_interpolated_x_string_node_t *) node), &parser->previous); + node->location = ((yp_interpolated_x_string_node_t *) node)->opening_loc; } else { assert(YP_NODE_TYPE_P(node, YP_NODE_INTERPOLATED_STRING_NODE)); yp_interpolated_string_node_closing_set((yp_interpolated_string_node_t *) node, &parser->previous); + node->location = ((yp_interpolated_string_node_t *) node)->opening_loc; } // If this is a heredoc that is indented with a ~, then we need to dedent @@ -13190,6 +13235,8 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char .enclosure_nesting = 0, .lambda_enclosure_nesting = -1, .brace_nesting = 0, + .do_loop_stack = YP_STATE_STACK_EMPTY, + .accepts_block_stack = YP_STATE_STACK_EMPTY, .lex_modes = { .index = 0, .stack = {{ .mode = YP_LEX_DEFAULT }}, @@ -13201,6 +13248,9 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char .current = { .type = YP_TOKEN_EOF, .start = source, .end = source }, .next_start = NULL, .heredoc_end = NULL, + .comment_list = YP_LIST_EMPTY, + .warning_list = YP_LIST_EMPTY, + .error_list = YP_LIST_EMPTY, .current_scope = NULL, .current_context = NULL, .recovering = false, @@ -13213,16 +13263,12 @@ yp_parser_init(yp_parser_t *parser, const char *source, size_t size, const char .pattern_matching_newlines = false, .in_keyword_arg = false, .filepath_string = filepath_string, + .constant_pool = YP_CONSTANT_POOL_EMPTY, + .newline_list = YP_NEWLINE_LIST_EMPTY }; - yp_state_stack_init(&parser->do_loop_stack); - yp_state_stack_init(&parser->accepts_block_stack); yp_accepts_block_stack_push(parser, true); - yp_list_init(&parser->warning_list); - yp_list_init(&parser->error_list); - yp_list_init(&parser->comment_list); - // 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. From f50e814dae946d49dd798976262ff60bd2797fbd Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 17 Aug 2023 10:01:54 -0700 Subject: [PATCH 155/158] Resync YARP to https://github.com/ruby/yarp/commit/11ad3fb590 --- .../fixtures/endless_range_in_conditional.txt | 3 + .../endless_range_in_conditional.txt | 31 ++++++++++ yarp/api_node.c | 62 +++++++++---------- yarp/yarp.c | 8 ++- 4 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 test/yarp/fixtures/endless_range_in_conditional.txt create mode 100644 test/yarp/snapshots/endless_range_in_conditional.txt diff --git a/test/yarp/fixtures/endless_range_in_conditional.txt b/test/yarp/fixtures/endless_range_in_conditional.txt new file mode 100644 index 00000000000000..6048008584e804 --- /dev/null +++ b/test/yarp/fixtures/endless_range_in_conditional.txt @@ -0,0 +1,3 @@ +if 1..2 ; end +if ..1 ; end +if 1.. ; end diff --git a/test/yarp/snapshots/endless_range_in_conditional.txt b/test/yarp/snapshots/endless_range_in_conditional.txt new file mode 100644 index 00000000000000..4360818e40de56 --- /dev/null +++ b/test/yarp/snapshots/endless_range_in_conditional.txt @@ -0,0 +1,31 @@ +ProgramNode(0...39)( + [], + StatementsNode(0...39)( + [IfNode(0...13)( + (0...2), + FlipFlopNode(3...7)( + IntegerNode(3...4)(), + IntegerNode(6...7)(), + (4...6), + 0 + ), + nil, + nil, + (10...13) + ), + IfNode(14...26)( + (14...16), + FlipFlopNode(17...20)(nil, IntegerNode(19...20)(), (17...19), 0), + nil, + nil, + (23...26) + ), + IfNode(27...39)( + (27...29), + FlipFlopNode(30...33)(IntegerNode(30...31)(), nil, (31...33), 0), + nil, + nil, + (36...39) + )] + ) +) diff --git a/yarp/api_node.c b/yarp/api_node.c index 9ebd1d6673a310..f15b92235cfc8c 100644 --- a/yarp/api_node.c +++ b/yarp/api_node.c @@ -1009,7 +1009,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[2]; // arguments - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->arguments.size); for (size_t index = 0; index < cast->arguments.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } @@ -1026,7 +1026,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[4]; // elements - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->elements.size); for (size_t index = 0; index < cast->elements.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } @@ -1052,7 +1052,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = rb_ary_pop(value_stack); // requireds - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->requireds.size); for (size_t index = 0; index < cast->requireds.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -1061,7 +1061,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[2] = rb_ary_pop(value_stack); // posts - argv[3] = rb_ary_new(); + argv[3] = rb_ary_new_capa(cast->posts.size); for (size_t index = 0; index < cast->posts.size; index++) { rb_ary_push(argv[3], rb_ary_pop(value_stack)); } @@ -1177,7 +1177,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[6]; // locals - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); } @@ -1226,7 +1226,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = rb_ary_pop(value_stack); // locals - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { yp_location_t location = cast->locals.locations[index]; rb_ary_push(argv[1], yp_location_new(parser, location.start, location.end, source)); @@ -1391,7 +1391,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = rb_ary_pop(value_stack); // conditions - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->conditions.size); for (size_t index = 0; index < cast->conditions.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -1417,7 +1417,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[8]; // locals - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); } @@ -1753,7 +1753,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[3] = rb_ary_pop(value_stack); // locals - argv[4] = rb_ary_new(); + argv[4] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { rb_ary_push(argv[4], rb_id2sym(constants[cast->locals.ids[index] - 1])); } @@ -1904,7 +1904,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[1] = rb_ary_pop(value_stack); // requireds - argv[2] = rb_ary_new(); + argv[2] = rb_ary_new_capa(cast->requireds.size); for (size_t index = 0; index < cast->requireds.size; index++) { rb_ary_push(argv[2], rb_ary_pop(value_stack)); } @@ -2124,7 +2124,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); // elements - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->elements.size); for (size_t index = 0; index < cast->elements.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -2147,7 +2147,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = rb_ary_pop(value_stack); // assocs - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->assocs.size); for (size_t index = 0; index < cast->assocs.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -2341,7 +2341,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); // parts - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->parts.size); for (size_t index = 0; index < cast->parts.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -2367,7 +2367,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); // parts - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->parts.size); for (size_t index = 0; index < cast->parts.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -2390,7 +2390,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = cast->opening_loc.start == NULL ? Qnil : yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); // parts - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->parts.size); for (size_t index = 0; index < cast->parts.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -2413,7 +2413,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = yp_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source); // parts - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->parts.size); for (size_t index = 0; index < cast->parts.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -2433,7 +2433,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[2]; // elements - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->elements.size); for (size_t index = 0; index < cast->elements.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } @@ -2484,7 +2484,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[5]; // locals - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); } @@ -2675,7 +2675,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[6]; // locals - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); } @@ -2704,7 +2704,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[6]; // targets - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->targets.size); for (size_t index = 0; index < cast->targets.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } @@ -2830,19 +2830,19 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[8]; // requireds - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->requireds.size); for (size_t index = 0; index < cast->requireds.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } // optionals - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->optionals.size); for (size_t index = 0; index < cast->optionals.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } // posts - argv[2] = rb_ary_new(); + argv[2] = rb_ary_new_capa(cast->posts.size); for (size_t index = 0; index < cast->posts.size; index++) { rb_ary_push(argv[2], rb_ary_pop(value_stack)); } @@ -2851,7 +2851,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[3] = rb_ary_pop(value_stack); // keywords - argv[4] = rb_ary_new(); + argv[4] = rb_ary_new_capa(cast->keywords.size); for (size_t index = 0; index < cast->keywords.size; index++) { rb_ary_push(argv[4], rb_ary_pop(value_stack)); } @@ -2980,7 +2980,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[3]; // locals - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); } @@ -3072,7 +3072,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[4]; // parameters - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->parameters.size); for (size_t index = 0; index < cast->parameters.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } @@ -3132,7 +3132,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); // exceptions - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->exceptions.size); for (size_t index = 0; index < cast->exceptions.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } @@ -3215,7 +3215,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[7]; // locals - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->locals.size); for (size_t index = 0; index < cast->locals.size; index++) { rb_ary_push(argv[0], rb_id2sym(constants[cast->locals.ids[index] - 1])); } @@ -3298,7 +3298,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[2]; // body - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->body.size); for (size_t index = 0; index < cast->body.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } @@ -3413,7 +3413,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { VALUE argv[3]; // names - argv[0] = rb_ary_new(); + argv[0] = rb_ary_new_capa(cast->names.size); for (size_t index = 0; index < cast->names.size; index++) { rb_ary_push(argv[0], rb_ary_pop(value_stack)); } @@ -3485,7 +3485,7 @@ yp_ast_new(yp_parser_t *parser, yp_node_t *node, rb_encoding *encoding) { argv[0] = yp_location_new(parser, cast->keyword_loc.start, cast->keyword_loc.end, source); // conditions - argv[1] = rb_ary_new(); + argv[1] = rb_ary_new_capa(cast->conditions.size); for (size_t index = 0; index < cast->conditions.size; index++) { rb_ary_push(argv[1], rb_ary_pop(value_stack)); } diff --git a/yarp/yarp.c b/yarp/yarp.c index 675d5e1cb26774..67402541301928 100644 --- a/yarp/yarp.c +++ b/yarp/yarp.c @@ -459,8 +459,12 @@ yp_flip_flop(yp_node_t *node) { } case YP_NODE_RANGE_NODE: { yp_range_node_t *cast = (yp_range_node_t *) node; - yp_flip_flop(cast->left); - yp_flip_flop(cast->right); + if (cast->left) { + yp_flip_flop(cast->left); + } + if (cast->right) { + yp_flip_flop(cast->right); + } // Here we change the range node into a flip flop node. We can do // this since the nodes are exactly the same except for the type. From 818998b41b41a4f2f4120b0a0b6a92e4009ee5ba Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 17 Aug 2023 10:27:32 -0700 Subject: [PATCH 156/158] Refactor YARP_IGNORE_FILE_PATTERN `.git.*` covers those two cases. Co-authored-by: Nobuyoshi Nakada --- tool/sync_default_gems.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 17865b8afb3e5b..dfe9d4ee00f396 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -444,9 +444,7 @@ def sync_default_gems(gem) YARP_IGNORE_FILE_PATTERN = /\A(?:[A-Z]\w*\.(?:md|txt) |[^\/]+\.yml - |\.gitignore |\.git.* - |\.github\/.* |[A-Z]\w+file |COPYING |CONTRIBUTING\.md From 52506cbf516da1a606fad6a6779ab6136c4f353b Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 16 Aug 2023 13:54:55 -0400 Subject: [PATCH 157/158] Move total_allocated_objects to size pool This commit moves the `total_allocated_objects` statistic to the size pool which allows for `total_allocated_objects` key in `GC.stat_heap`. --- gc.c | 27 ++++++++++++++++++++------- test/ruby/test_gc.rb | 13 +++++++++++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/gc.c b/gc.c index cc318b15e06364..6006325afbacc5 100644 --- a/gc.c +++ b/gc.c @@ -708,6 +708,7 @@ typedef struct rb_size_pool_struct { size_t total_freed_pages; size_t force_major_gc_count; size_t force_incremental_marking_finish_count; + size_t total_allocated_objects; /* Sweeping statistics */ size_t freed_slots; @@ -751,7 +752,6 @@ typedef struct rb_objspace { } flags; rb_event_flag_t hook_events; - size_t total_allocated_objects; VALUE next_object_id; rb_size_pool_t size_pools[SIZE_POOL_COUNT]; @@ -1195,6 +1195,17 @@ total_freed_pages(rb_objspace_t *objspace) return count; } +static inline size_t +total_allocated_objects(rb_objspace_t *objspace) +{ + size_t count = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + count += size_pool->total_allocated_objects; + } + return count; +} + #define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode) #define gc_mode_set(objspace, mode) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(mode)) @@ -2480,9 +2491,6 @@ newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace, MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj); } - // TODO: make it atomic, or ractor local - objspace->total_allocated_objects++; - #if RGENGC_PROFILE if (wb_protected) { objspace->profile.total_generated_normal_object_count++; @@ -2703,6 +2711,8 @@ newobj_alloc(rb_objspace_t *objspace, rb_ractor_t *cr, size_t size_pool_idx, boo } } + size_pool->total_allocated_objects++; + return obj; } @@ -5045,7 +5055,7 @@ objspace_available_slots(rb_objspace_t *objspace) static size_t objspace_live_slots(rb_objspace_t *objspace) { - return (objspace->total_allocated_objects - objspace->profile.total_freed_objects) - heap_pages_final_slots; + return (total_allocated_objects(objspace) - objspace->profile.total_freed_objects) - heap_pages_final_slots; } static size_t @@ -9229,7 +9239,7 @@ gc_start(rb_objspace_t *objspace, unsigned int reason) objspace->profile.count++; objspace->profile.latest_gc_info = reason; - objspace->profile.total_allocated_objects_at_gc_start = objspace->total_allocated_objects; + objspace->profile.total_allocated_objects_at_gc_start = total_allocated_objects(objspace); objspace->profile.heap_used_at_gc_start = heap_allocated_pages; gc_prof_setup_new_record(objspace, reason); gc_reset_malloc_info(objspace, do_full_mark); @@ -11058,7 +11068,7 @@ gc_stat_internal(VALUE hash_or_sym) SET(heap_tomb_pages, heap_tomb_total_pages(objspace)); SET(total_allocated_pages, total_allocated_pages(objspace)); SET(total_freed_pages, total_freed_pages(objspace)); - SET(total_allocated_objects, objspace->total_allocated_objects); + SET(total_allocated_objects, total_allocated_objects(objspace)); SET(total_freed_objects, objspace->profile.total_freed_objects); SET(malloc_increase_bytes, malloc_increase); SET(malloc_increase_bytes_limit, malloc_limit); @@ -11150,6 +11160,7 @@ enum gc_stat_heap_sym { gc_stat_heap_sym_total_freed_pages, gc_stat_heap_sym_force_major_gc_count, gc_stat_heap_sym_force_incremental_marking_finish_count, + gc_stat_heap_sym_total_allocated_objects, gc_stat_heap_sym_last }; @@ -11170,6 +11181,7 @@ setup_gc_stat_heap_symbols(void) S(total_freed_pages); S(force_major_gc_count); S(force_incremental_marking_finish_count); + S(total_allocated_objects); #undef S } } @@ -11214,6 +11226,7 @@ gc_stat_heap_internal(int size_pool_idx, VALUE hash_or_sym) SET(total_freed_pages, size_pool->total_freed_pages); SET(force_major_gc_count, size_pool->force_major_gc_count); SET(force_incremental_marking_finish_count, size_pool->force_incremental_marking_finish_count); + SET(total_allocated_objects, size_pool->total_allocated_objects); #undef SET if (!NIL_P(key)) { /* matched key should return above */ diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index aabdfc0cf8dc77..7513aca46dab09 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -164,6 +164,7 @@ def test_stat_heap assert_operator stat_heap[:total_freed_pages], :>=, 0 assert_operator stat_heap[:force_major_gc_count], :>=, 0 assert_operator stat_heap[:force_incremental_marking_finish_count], :>=, 0 + assert_operator stat_heap[:total_allocated_objects], :>=, 0 end GC.stat_heap(0, stat_heap) @@ -186,6 +187,11 @@ def test_stat_heap_all GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT].times do |i| GC.stat_heap(i, stat_heap) + # Remove keys that can vary between invocations + %i(total_allocated_objects).each do |sym| + stat_heap[sym] = stat_heap_all[i][sym] = 0 + end + assert_equal stat_heap, stat_heap_all[i] end @@ -197,8 +203,10 @@ def test_stat_heap_constraints stat = GC.stat stat_heap = GC.stat_heap - GC.stat(stat) - GC.stat_heap(nil, stat_heap) + 2.times do + GC.stat(stat) + GC.stat_heap(nil, stat_heap) + end stat_heap_sum = Hash.new(0) stat_heap.values.each do |hash| @@ -211,6 +219,7 @@ def test_stat_heap_constraints assert_equal stat[:heap_available_slots], stat_heap_sum[:heap_eden_slots] + stat_heap_sum[:heap_tomb_slots] assert_equal stat[:total_allocated_pages], stat_heap_sum[:total_allocated_pages] assert_equal stat[:total_freed_pages], stat_heap_sum[:total_freed_pages] + assert_equal stat[:total_allocated_objects], stat_heap_sum[:total_allocated_objects] end def test_latest_gc_info From 5db8b9b366271fb2ec25ca76722a3d25a4bb7de7 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 16 Aug 2023 14:05:32 -0400 Subject: [PATCH 158/158] Move total_freed_objects to size pool This commit moves the `total_freed_objects` statistic to the size pool which allows for `total_freed_objects` key in `GC.stat_heap`. --- gc.c | 31 ++++++++++++++++++++++--------- test/ruby/test_gc.rb | 3 +++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/gc.c b/gc.c index 6006325afbacc5..361b1ee70e0b63 100644 --- a/gc.c +++ b/gc.c @@ -709,6 +709,7 @@ typedef struct rb_size_pool_struct { size_t force_major_gc_count; size_t force_incremental_marking_finish_count; size_t total_allocated_objects; + size_t total_freed_objects; /* Sweeping statistics */ size_t freed_slots; @@ -820,7 +821,6 @@ typedef struct rb_objspace { /* basic statistics */ size_t count; - size_t total_freed_objects; uint64_t marking_time_ns; struct timespec marking_start_time; uint64_t sweeping_time_ns; @@ -1206,6 +1206,17 @@ total_allocated_objects(rb_objspace_t *objspace) return count; } +static inline size_t +total_freed_objects(rb_objspace_t *objspace) +{ + size_t count = 0; + for (int i = 0; i < SIZE_POOL_COUNT; i++) { + rb_size_pool_t *size_pool = &size_pools[i]; + count += size_pool->total_freed_objects; + } + return count; +} + #define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode) #define gc_mode_set(objspace, mode) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(mode)) @@ -4305,7 +4316,7 @@ finalize_list(rb_objspace_t *objspace, VALUE zombie) page->final_slots--; page->free_slots++; heap_page_add_freeobj(objspace, page, zombie); - objspace->profile.total_freed_objects++; + page->size_pool->total_freed_objects++; } RB_VM_LOCK_LEAVE(); @@ -5055,7 +5066,7 @@ objspace_available_slots(rb_objspace_t *objspace) static size_t objspace_live_slots(rb_objspace_t *objspace) { - return (total_allocated_objects(objspace) - objspace->profile.total_freed_objects) - heap_pages_final_slots; + return total_allocated_objects(objspace) - total_freed_objects(objspace) - heap_pages_final_slots; } static size_t @@ -5518,7 +5529,7 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context ctx->freed_slots, ctx->empty_slots, ctx->final_slots); sweep_page->free_slots += ctx->freed_slots + ctx->empty_slots; - objspace->profile.total_freed_objects += ctx->freed_slots; + sweep_page->size_pool->total_freed_objects += ctx->freed_slots; if (heap_pages_deferred_final && !finalizing) { rb_thread_t *th = GET_THREAD(); @@ -7906,9 +7917,8 @@ gc_verify_internal_consistency_(rb_objspace_t *objspace) !finalizing && ruby_single_main_ractor != NULL) { if (objspace_live_slots(objspace) != data.live_object_count) { - fprintf(stderr, "heap_pages_final_slots: %"PRIdSIZE", " - "objspace->profile.total_freed_objects: %"PRIdSIZE"\n", - heap_pages_final_slots, objspace->profile.total_freed_objects); + fprintf(stderr, "heap_pages_final_slots: %"PRIdSIZE", total_freed_objects: %"PRIdSIZE"\n", + heap_pages_final_slots, total_freed_objects(objspace)); rb_bug("inconsistent live slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace_live_slots(objspace), data.live_object_count); } @@ -11069,7 +11079,7 @@ gc_stat_internal(VALUE hash_or_sym) SET(total_allocated_pages, total_allocated_pages(objspace)); SET(total_freed_pages, total_freed_pages(objspace)); SET(total_allocated_objects, total_allocated_objects(objspace)); - SET(total_freed_objects, objspace->profile.total_freed_objects); + SET(total_freed_objects, total_freed_objects(objspace)); SET(malloc_increase_bytes, malloc_increase); SET(malloc_increase_bytes_limit, malloc_limit); SET(minor_gc_count, objspace->profile.minor_gc_count); @@ -11161,6 +11171,7 @@ enum gc_stat_heap_sym { gc_stat_heap_sym_force_major_gc_count, gc_stat_heap_sym_force_incremental_marking_finish_count, gc_stat_heap_sym_total_allocated_objects, + gc_stat_heap_sym_total_freed_objects, gc_stat_heap_sym_last }; @@ -11182,6 +11193,7 @@ setup_gc_stat_heap_symbols(void) S(force_major_gc_count); S(force_incremental_marking_finish_count); S(total_allocated_objects); + S(total_freed_objects); #undef S } } @@ -11227,6 +11239,7 @@ gc_stat_heap_internal(int size_pool_idx, VALUE hash_or_sym) SET(force_major_gc_count, size_pool->force_major_gc_count); SET(force_incremental_marking_finish_count, size_pool->force_incremental_marking_finish_count); SET(total_allocated_objects, size_pool->total_allocated_objects); + SET(total_freed_objects, size_pool->total_freed_objects); #undef SET if (!NIL_P(key)) { /* matched key should return above */ @@ -12819,7 +12832,7 @@ gc_prof_set_heap_info(rb_objspace_t *objspace) { if (gc_prof_enabled(objspace)) { gc_profile_record *record = gc_prof_record(objspace); - size_t live = objspace->profile.total_allocated_objects_at_gc_start - objspace->profile.total_freed_objects; + size_t live = objspace->profile.total_allocated_objects_at_gc_start - total_freed_objects(objspace); size_t total = objspace->profile.heap_used_at_gc_start * HEAP_PAGE_OBJ_LIMIT; #if GC_PROFILE_MORE_DETAIL diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index 7513aca46dab09..8d77e65bbe781b 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -165,6 +165,8 @@ def test_stat_heap assert_operator stat_heap[:force_major_gc_count], :>=, 0 assert_operator stat_heap[:force_incremental_marking_finish_count], :>=, 0 assert_operator stat_heap[:total_allocated_objects], :>=, 0 + assert_operator stat_heap[:total_freed_objects], :>=, 0 + assert_operator stat_heap[:total_freed_objects], :<=, stat_heap[:total_allocated_objects] end GC.stat_heap(0, stat_heap) @@ -220,6 +222,7 @@ def test_stat_heap_constraints assert_equal stat[:total_allocated_pages], stat_heap_sum[:total_allocated_pages] assert_equal stat[:total_freed_pages], stat_heap_sum[:total_freed_pages] assert_equal stat[:total_allocated_objects], stat_heap_sum[:total_allocated_objects] + assert_equal stat[:total_freed_objects], stat_heap_sum[:total_freed_objects] end def test_latest_gc_info